Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/CHANGES b/CHANGES
index 0d66a556b7b6..4b68f4832909 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,13106 +1,13141 @@
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.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 3baa8ce016f8..d5dc36c285ba 100755
--- a/Configure
+++ b/Configure
@@ -1,3457 +1,3514 @@
#! /usr/bin/env perl
# -*- mode: perl; -*-
# Copyright 2016-2018 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";
# 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-]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.
# 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
# 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
# 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
# Minimum warning options... any contributions to OpenSSL should at least get
# past these.
# 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"
;
# 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
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"
;
# 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 $@;
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} // {};
} else {
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/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 "");
# 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",
"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",
"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";
}
my %deprecated_disablables = (
"ssl2" => undef,
"buf-freelists" => undef,
"ripemd" => "rmd160",
"ui" => "ui-console",
);
# 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",
"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",
);
# Note: => pair form used for aesthetics, not to truly make a hash table
my @disable_cascades = (
# "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 ],
sub { 0 == scalar grep { !$disabled{$_} } @dtls }
=> [ "dtls" ],
"tls" => [ @tls ],
sub { 0 == scalar grep { !$disabled{$_} } @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 ] );
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 ] );
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 => [],
CXX => env('CXX'),
CXXFLAGS => [],
CPP => undef,
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
MT => undef,
MTFLAGS => [],
PERL => env('PERL') || ($^O ne "VMS" ? $^X : "perl"),
RANLIB => env('RANLIB'),
RC => env('RC') || env('WINDRES'),
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 => [],
);
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/;
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})
{
$disabled{$deprecated_disablables{$1}} = "option";
}
}
else
{
$disabled{$1} = "option";
}
# 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;
}
}
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} .= " ".$_; }
}
}
if (defined($config{api}) && !exists $apitable->{$config{api}}) {
die "***** Unsupported api compatibility level: $config{api}\n",
}
if (keys %deprecated_options)
{
warn "***** Deprecated options: ",
join(", ", keys %deprecated_options), "\n";
}
if (keys %unsupported_options)
{
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";
}
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";
}
}
}
@tocheckfor = (keys %new_tocheckfor);
}
our $die = sub { die @_; };
if ($target eq "TABLE") {
local $die = sub { warn @_; };
foreach (sort keys %table) {
print_table_entry($_, "TABLE");
}
exit 0;
}
if ($target eq "LIST") {
foreach (sort keys %table) {
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");
}
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;
-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 ===============================
+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;
# 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;
}
}
&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 ];
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{$_} // "")) {
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{$_};
}
}
$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{$_};
}
# 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',
'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";
}
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};
}
# 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";
}
} 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}}) {
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";
}
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{$_} = "";
}
}
else
{
push @{$config{lib_defines}}, "OPENSSL_PIC";
}
if ($target{sys_id} ne "")
{
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/);
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/);
}
if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) {
push @{$config{lib_defines}}, "KECCAK1600_ASM";
}
if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) {
push @{$config{lib_defines}}, "RC4_ASM";
}
if ($target{md5_asm_src}) {
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";
}
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/);
}
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";
}
}
if ($target{modes_asm_src} =~ /ghash-/) {
push @{$config{lib_defines}}, "GHASH_ASM";
}
if ($target{ec_asm_src} =~ /ecp_nistz256/) {
push @{$config{lib_defines}}, "ECP_NISTZ256_ASM";
}
if ($target{ec_asm_src} =~ /x25519/) {
push @{$config{lib_defines}}, "X25519_ASM";
}
if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
push @{$config{lib_defines}}, "PADLOCK_ASM";
}
if ($target{poly1305_asm_src} ne "") {
push @{$config{lib_defines}}, "POLY1305_ASM";
}
}
my %predefined = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
# 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__})) {
# 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};
}
}
if (!$disabled{asm} && !$predefined{__MACH__} && $^O ne 'VMS') {
# probe for -Wa,--noexecstack option...
if ($predefined{__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;
my $def_int="unsigned 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{b64l},$config{b64},$config{b32})
=(0,1,0) if $_ eq 'SIXTY_FOUR_BIT';
($config{b64l},$config{b64},$config{b32})
=(1,0,0) if $_ eq 'SIXTY_FOUR_BIT_LONG';
($config{b64l},$config{b64},$config{b32})
=(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;
}
if ($strict_warnings)
{
my $wopt;
my $gccver = $predefined{__GNUC__} // -1;
die "ERROR --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}});
}
}
}
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";
}
}
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";
} else {
push @{$config{engdirs}}, "afalg";
}
} else {
$disabled{afalgeng} = "cross-compiling";
}
} else {
$disabled{afalgeng} = "not-linux";
}
}
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';
if (defined $config{$_}) {
push @{$config{$_}}, @{$useradd{$_}};
} else {
$config{$_} = [ @{$useradd{$_}} ];
}
}
# ALL MODIFICATIONS TO %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" );
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;
}
# Then, look in our standard directory
push @build_file_templates,
( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
@build_file_template_names );
my $build_file_template;
for $_ (@build_file_templates) {
$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";
}
$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}})) {
+ (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";
} elsif (ref($config{$_}) eq "HASH") {
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 <<"EOF";
);
EOF
print OUT "our %target = (\n";
foreach (sort keys %target) {
if (ref($target{$_}) eq "ARRAY") {
print OUT " ", $_, " => [ ", join(", ",
map { quotify("perl", $_) }
@{$target{$_}}), " ],\n";
} else {
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";
} else {
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";
}
}
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";
**********************************************************************
*** ***
-*** If you want to report a building issue, please include the ***
-*** output from this command: ***
+*** 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 ***
*** ***
-*** 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;
}
}
# 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 {
();
}
} (@_);
$add_called = 1;
if ($found_array) {
[ @values ];
} else {
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 = ();
%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 {
$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";
}
if (!defined($table{$target})) {
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{$_};
}
}
}
# 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}});
sub process_values {
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;
}
$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;
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);
}
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",
);
if ($type eq "TABLE") {
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{$_}) {
if (ref($target{$_}) eq "ARRAY") {
print " '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
} else {
print " '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\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;
}
},
);
my $for = shift;
my $processor =
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";
}
return @result;
}
diff --git a/INSTALL b/INSTALL
index ff0aa6d12792..4ce6651b6b34 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,1217 +1,1217 @@
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.
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.
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-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 resources manipulator.
- RCFLAGS Flags for the Windows reources manipulator.
+ 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
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
OpenSSL 1.1.0 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 Unixly platforms, "makefile" on native Windows,
+ ("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 in 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 POSIXly platforms, shared libraries are named libcrypto.so.1.1
+ 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 explicitely provide this option. Note also
+ 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 45c183c9b291..b95e93027f83 100644
--- a/NEWS
+++ b/NEWS
@@ -1,920 +1,925 @@
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.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/README b/README
index e70acb3139b6..affb172e8ba8 100644
--- a/README
+++ b/README
@@ -1,93 +1,93 @@
- OpenSSL 1.1.1 11 Sep 2018
+ OpenSSL 1.1.1a 20 Nov 2018
Copyright (c) 1998-2018 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/app_rand.c b/apps/app_rand.c
index 28caad41a7d8..2b0bbde03423 100644
--- a/apps/app_rand.c
+++ b/apps/app_rand.c
@@ -1,94 +1,93 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 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 "apps.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/conf.h>
static char *save_rand_file;
void app_RAND_load_conf(CONF *c, const char *section)
{
const char *randfile = NCONF_get_string(c, section, "RANDFILE");
if (randfile == NULL) {
ERR_clear_error();
return;
}
if (RAND_load_file(randfile, -1) < 0) {
BIO_printf(bio_err, "Can't load %s into RNG\n", randfile);
ERR_print_errors(bio_err);
- return;
}
if (save_rand_file == NULL)
save_rand_file = OPENSSL_strdup(randfile);
}
static int loadfiles(char *name)
{
char *p;
int last, ret = 1;
for ( ; ; ) {
last = 0;
for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++)
continue;
if (*p == '\0')
last = 1;
*p = '\0';
if (RAND_load_file(name, -1) < 0) {
BIO_printf(bio_err, "Can't load %s into RNG\n", name);
ERR_print_errors(bio_err);
ret = 0;
}
if (last)
break;
name = p + 1;
if (*name == '\0')
break;
}
return ret;
}
void app_RAND_write(void)
{
if (save_rand_file == NULL)
return;
if (RAND_write_file(save_rand_file) == -1) {
BIO_printf(bio_err, "Cannot write random bytes:\n");
ERR_print_errors(bio_err);
}
OPENSSL_free(save_rand_file);
save_rand_file = NULL;
}
/*
* See comments in opt_verify for explanation of this.
*/
enum r_range { OPT_R_ENUM };
int opt_rand(int opt)
{
switch ((enum r_range)opt) {
case OPT_R__FIRST:
case OPT_R__LAST:
break;
case OPT_R_RAND:
return loadfiles(opt_arg());
break;
case OPT_R_WRITERAND:
OPENSSL_free(save_rand_file);
save_rand_file = OPENSSL_strdup(opt_arg());
break;
}
return 1;
}
diff --git a/apps/apps.c b/apps/apps.c
index 9be656054a45..653e3973e04d 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -1,2746 +1,2752 @@
/*
* Copyright 1995-2018 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
*/
#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
/*
* On VMS, you need to define this to get the declaration of fileno(). The
* value 2 is to make sure no function defined in POSIX-2 is left undefined.
*/
# define _POSIX_C_SOURCE 2
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifndef OPENSSL_NO_POSIX_IO
# include <sys/stat.h>
# include <fcntl.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/ui.h>
#include <openssl/safestack.h>
#ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h>
#endif
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#include <openssl/bn.h>
#include <openssl/ssl.h>
#include "s_apps.h"
#include "apps.h"
#ifdef _WIN32
static int WIN32_rename(const char *from, const char *to);
# define rename(from,to) WIN32_rename((from),(to))
#endif
typedef struct {
const char *name;
unsigned long flag;
unsigned long mask;
} NAME_EX_TBL;
static UI_METHOD *ui_method = NULL;
static const UI_METHOD *ui_fallback_method = NULL;
static int set_table_opts(unsigned long *flags, const char *arg,
const NAME_EX_TBL * in_tbl);
static int set_multi_opts(unsigned long *flags, const char *arg,
const NAME_EX_TBL * in_tbl);
int app_init(long mesgwin);
int chopup_args(ARGS *arg, char *buf)
{
int quoted;
char c = '\0', *p = NULL;
arg->argc = 0;
if (arg->size == 0) {
arg->size = 20;
arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space");
}
for (p = buf;;) {
/* Skip whitespace. */
while (*p && isspace(_UC(*p)))
p++;
if (!*p)
break;
/* The start of something good :-) */
if (arg->argc >= arg->size) {
char **tmp;
arg->size += 20;
tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size);
if (tmp == NULL)
return 0;
arg->argv = tmp;
}
quoted = *p == '\'' || *p == '"';
if (quoted)
c = *p++;
arg->argv[arg->argc++] = p;
/* now look for the end of this */
if (quoted) {
while (*p && *p != c)
p++;
*p++ = '\0';
} else {
while (*p && !isspace(_UC(*p)))
p++;
if (*p)
*p++ = '\0';
}
}
arg->argv[arg->argc] = NULL;
return 1;
}
#ifndef APP_INIT
int app_init(long mesgwin)
{
return 1;
}
#endif
int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath, int noCAfile, int noCApath)
{
if (CAfile == NULL && CApath == NULL) {
if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0)
return 0;
if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0)
return 0;
return 1;
}
return SSL_CTX_load_verify_locations(ctx, CAfile, CApath);
}
#ifndef OPENSSL_NO_CT
int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path)
{
if (path == NULL)
return SSL_CTX_set_default_ctlog_list_file(ctx);
return SSL_CTX_set_ctlog_list_file(ctx, path);
}
#endif
static unsigned long nmflag = 0;
static char nmflag_set = 0;
int set_nameopt(const char *arg)
{
int ret = set_name_ex(&nmflag, arg);
if (ret)
nmflag_set = 1;
return ret;
}
unsigned long get_nameopt(void)
{
return (nmflag_set) ? nmflag : XN_FLAG_ONELINE;
}
int dump_cert_text(BIO *out, X509 *x)
{
print_name(out, "subject=", X509_get_subject_name(x), get_nameopt());
BIO_puts(out, "\n");
print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt());
BIO_puts(out, "\n");
return 0;
}
static int ui_open(UI *ui)
{
int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method);
if (opener)
return opener(ui);
return 1;
}
static int ui_read(UI *ui, UI_STRING *uis)
{
int (*reader)(UI *ui, UI_STRING *uis) = NULL;
if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
&& UI_get0_user_data(ui)) {
switch (UI_get_string_type(uis)) {
case UIT_PROMPT:
case UIT_VERIFY:
{
const char *password =
((PW_CB_DATA *)UI_get0_user_data(ui))->password;
if (password && password[0] != '\0') {
UI_set_result(ui, uis, password);
return 1;
}
}
break;
case UIT_NONE:
case UIT_BOOLEAN:
case UIT_INFO:
case UIT_ERROR:
break;
}
}
reader = UI_method_get_reader(ui_fallback_method);
if (reader)
return reader(ui, uis);
return 1;
}
static int ui_write(UI *ui, UI_STRING *uis)
{
int (*writer)(UI *ui, UI_STRING *uis) = NULL;
if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
&& UI_get0_user_data(ui)) {
switch (UI_get_string_type(uis)) {
case UIT_PROMPT:
case UIT_VERIFY:
{
const char *password =
((PW_CB_DATA *)UI_get0_user_data(ui))->password;
if (password && password[0] != '\0')
return 1;
}
break;
case UIT_NONE:
case UIT_BOOLEAN:
case UIT_INFO:
case UIT_ERROR:
break;
}
}
writer = UI_method_get_writer(ui_fallback_method);
if (writer)
return writer(ui, uis);
return 1;
}
static int ui_close(UI *ui)
{
int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method);
if (closer)
return closer(ui);
return 1;
}
int setup_ui_method(void)
{
ui_fallback_method = UI_null();
#ifndef OPENSSL_NO_UI_CONSOLE
ui_fallback_method = UI_OpenSSL();
#endif
ui_method = UI_create_method("OpenSSL application user interface");
UI_method_set_opener(ui_method, ui_open);
UI_method_set_reader(ui_method, ui_read);
UI_method_set_writer(ui_method, ui_write);
UI_method_set_closer(ui_method, ui_close);
return 0;
}
void destroy_ui_method(void)
{
if (ui_method) {
UI_destroy_method(ui_method);
ui_method = NULL;
}
}
const UI_METHOD *get_ui_method(void)
{
return ui_method;
}
int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp)
{
int res = 0;
UI *ui = NULL;
PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
ui = UI_new_method(ui_method);
if (ui) {
int ok = 0;
char *buff = NULL;
int ui_flags = 0;
const char *prompt_info = NULL;
char *prompt;
if (cb_data != NULL && cb_data->prompt_info != NULL)
prompt_info = cb_data->prompt_info;
prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
if (!prompt) {
BIO_printf(bio_err, "Out of memory\n");
UI_free(ui);
return 0;
}
ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
/* We know that there is no previous user data to return to us */
(void)UI_add_user_data(ui, cb_data);
ok = UI_add_input_string(ui, prompt, ui_flags, buf,
PW_MIN_LENGTH, bufsiz - 1);
if (ok >= 0 && verify) {
buff = app_malloc(bufsiz, "password buffer");
ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
PW_MIN_LENGTH, bufsiz - 1, buf);
}
if (ok >= 0)
do {
ok = UI_process(ui);
} while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
OPENSSL_clear_free(buff, (unsigned int)bufsiz);
if (ok >= 0)
res = strlen(buf);
if (ok == -1) {
BIO_printf(bio_err, "User interface error\n");
ERR_print_errors(bio_err);
OPENSSL_cleanse(buf, (unsigned int)bufsiz);
res = 0;
}
if (ok == -2) {
BIO_printf(bio_err, "aborted!\n");
OPENSSL_cleanse(buf, (unsigned int)bufsiz);
res = 0;
}
UI_free(ui);
OPENSSL_free(prompt);
}
return res;
}
static char *app_get_pass(const char *arg, int keepbio);
int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2)
{
int same;
if (arg2 == NULL || arg1 == NULL || strcmp(arg1, arg2))
same = 0;
else
same = 1;
if (arg1 != NULL) {
*pass1 = app_get_pass(arg1, same);
if (*pass1 == NULL)
return 0;
} else if (pass1 != NULL) {
*pass1 = NULL;
}
if (arg2 != NULL) {
*pass2 = app_get_pass(arg2, same ? 2 : 0);
if (*pass2 == NULL)
return 0;
} else if (pass2 != NULL) {
*pass2 = NULL;
}
return 1;
}
static char *app_get_pass(const char *arg, int keepbio)
{
char *tmp, tpass[APP_PASS_LEN];
static BIO *pwdbio = NULL;
int i;
if (strncmp(arg, "pass:", 5) == 0)
return OPENSSL_strdup(arg + 5);
if (strncmp(arg, "env:", 4) == 0) {
tmp = getenv(arg + 4);
if (tmp == NULL) {
BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4);
return NULL;
}
return OPENSSL_strdup(tmp);
}
if (!keepbio || pwdbio == NULL) {
if (strncmp(arg, "file:", 5) == 0) {
pwdbio = BIO_new_file(arg + 5, "r");
if (pwdbio == NULL) {
BIO_printf(bio_err, "Can't open file %s\n", arg + 5);
return NULL;
}
#if !defined(_WIN32)
/*
* Under _WIN32, which covers even Win64 and CE, file
* descriptors referenced by BIO_s_fd are not inherited
* by child process and therefore below is not an option.
* It could have been an option if bss_fd.c was operating
* on real Windows descriptors, such as those obtained
* with CreateFile.
*/
} else if (strncmp(arg, "fd:", 3) == 0) {
BIO *btmp;
i = atoi(arg + 3);
if (i >= 0)
pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
if ((i < 0) || !pwdbio) {
BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3);
return NULL;
}
/*
* Can't do BIO_gets on an fd BIO so add a buffering BIO
*/
btmp = BIO_new(BIO_f_buffer());
pwdbio = BIO_push(btmp, pwdbio);
#endif
} else if (strcmp(arg, "stdin") == 0) {
pwdbio = dup_bio_in(FORMAT_TEXT);
if (!pwdbio) {
BIO_printf(bio_err, "Can't open BIO for stdin\n");
return NULL;
}
} else {
BIO_printf(bio_err, "Invalid password argument \"%s\"\n", arg);
return NULL;
}
}
i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
if (keepbio != 1) {
BIO_free_all(pwdbio);
pwdbio = NULL;
}
if (i <= 0) {
BIO_printf(bio_err, "Error reading password from BIO\n");
return NULL;
}
tmp = strchr(tpass, '\n');
if (tmp != NULL)
*tmp = 0;
return OPENSSL_strdup(tpass);
}
CONF *app_load_config_bio(BIO *in, const char *filename)
{
long errorline = -1;
CONF *conf;
int i;
conf = NCONF_new(NULL);
i = NCONF_load_bio(conf, in, &errorline);
if (i > 0)
return conf;
if (errorline <= 0) {
BIO_printf(bio_err, "%s: Can't load ", opt_getprog());
} else {
BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(),
errorline);
}
if (filename != NULL)
BIO_printf(bio_err, "config file \"%s\"\n", filename);
else
BIO_printf(bio_err, "config input");
NCONF_free(conf);
return NULL;
}
CONF *app_load_config(const char *filename)
{
BIO *in;
CONF *conf;
in = bio_open_default(filename, 'r', FORMAT_TEXT);
if (in == NULL)
return NULL;
conf = app_load_config_bio(in, filename);
BIO_free(in);
return conf;
}
CONF *app_load_config_quiet(const char *filename)
{
BIO *in;
CONF *conf;
in = bio_open_default_quiet(filename, 'r', FORMAT_TEXT);
if (in == NULL)
return NULL;
conf = app_load_config_bio(in, filename);
BIO_free(in);
return conf;
}
int app_load_modules(const CONF *config)
{
CONF *to_free = NULL;
if (config == NULL)
config = to_free = app_load_config_quiet(default_config_file);
if (config == NULL)
return 1;
if (CONF_modules_load(config, NULL, 0) <= 0) {
BIO_printf(bio_err, "Error configuring OpenSSL modules\n");
ERR_print_errors(bio_err);
NCONF_free(to_free);
return 0;
}
NCONF_free(to_free);
return 1;
}
int add_oid_section(CONF *conf)
{
char *p;
STACK_OF(CONF_VALUE) *sktmp;
CONF_VALUE *cnf;
int i;
if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) {
ERR_clear_error();
return 1;
}
if ((sktmp = NCONF_get_section(conf, p)) == NULL) {
BIO_printf(bio_err, "problem loading oid section %s\n", p);
return 0;
}
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
cnf = sk_CONF_VALUE_value(sktmp, i);
if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
BIO_printf(bio_err, "problem creating object %s=%s\n",
cnf->name, cnf->value);
return 0;
}
}
return 1;
}
static int load_pkcs12(BIO *in, const char *desc,
pem_password_cb *pem_cb, void *cb_data,
EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
{
const char *pass;
char tpass[PEM_BUFSIZE];
int len, ret = 0;
PKCS12 *p12;
p12 = d2i_PKCS12_bio(in, NULL);
if (p12 == NULL) {
BIO_printf(bio_err, "Error loading PKCS12 file for %s\n", desc);
goto die;
}
/* See if an empty password will do */
if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) {
pass = "";
} else {
if (!pem_cb)
pem_cb = (pem_password_cb *)password_callback;
len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
if (len < 0) {
BIO_printf(bio_err, "Passphrase callback error for %s\n", desc);
goto die;
}
if (len < PEM_BUFSIZE)
tpass[len] = 0;
if (!PKCS12_verify_mac(p12, tpass, len)) {
BIO_printf(bio_err,
"Mac verify error (wrong password?) in PKCS12 file for %s\n",
desc);
goto die;
}
pass = tpass;
}
ret = PKCS12_parse(p12, pass, pkey, cert, ca);
die:
PKCS12_free(p12);
return ret;
}
#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl)
{
char *host = NULL, *port = NULL, *path = NULL;
BIO *bio = NULL;
OCSP_REQ_CTX *rctx = NULL;
int use_ssl, rv = 0;
if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
goto err;
if (use_ssl) {
BIO_puts(bio_err, "https not supported\n");
goto err;
}
bio = BIO_new_connect(host);
if (!bio || !BIO_set_conn_port(bio, port))
goto err;
rctx = OCSP_REQ_CTX_new(bio, 1024);
if (rctx == NULL)
goto err;
if (!OCSP_REQ_CTX_http(rctx, "GET", path))
goto err;
if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host))
goto err;
if (pcert) {
do {
rv = X509_http_nbio(rctx, pcert);
} while (rv == -1);
} else {
do {
rv = X509_CRL_http_nbio(rctx, pcrl);
} while (rv == -1);
}
err:
OPENSSL_free(host);
OPENSSL_free(path);
OPENSSL_free(port);
BIO_free_all(bio);
OCSP_REQ_CTX_free(rctx);
if (rv != 1) {
BIO_printf(bio_err, "Error loading %s from %s\n",
pcert ? "certificate" : "CRL", url);
ERR_print_errors(bio_err);
}
return rv;
}
#endif
X509 *load_cert(const char *file, int format, const char *cert_descrip)
{
X509 *x = NULL;
BIO *cert;
if (format == FORMAT_HTTP) {
#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
load_cert_crl_http(file, &x, NULL);
#endif
return x;
}
if (file == NULL) {
unbuffer(stdin);
cert = dup_bio_in(format);
} else {
cert = bio_open_default(file, 'r', format);
}
if (cert == NULL)
goto end;
if (format == FORMAT_ASN1) {
x = d2i_X509_bio(cert, NULL);
} else if (format == FORMAT_PEM) {
x = PEM_read_bio_X509_AUX(cert, NULL,
(pem_password_cb *)password_callback, NULL);
} else if (format == FORMAT_PKCS12) {
if (!load_pkcs12(cert, cert_descrip, NULL, NULL, NULL, &x, NULL))
goto end;
} else {
BIO_printf(bio_err, "bad input format specified for %s\n", cert_descrip);
goto end;
}
end:
if (x == NULL) {
BIO_printf(bio_err, "unable to load certificate\n");
ERR_print_errors(bio_err);
}
BIO_free(cert);
return x;
}
X509_CRL *load_crl(const char *infile, int format)
{
X509_CRL *x = NULL;
BIO *in = NULL;
if (format == FORMAT_HTTP) {
#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
load_cert_crl_http(infile, NULL, &x);
#endif
return x;
}
in = bio_open_default(infile, 'r', format);
if (in == NULL)
goto end;
if (format == FORMAT_ASN1) {
x = d2i_X509_CRL_bio(in, NULL);
} else if (format == FORMAT_PEM) {
x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
} else {
BIO_printf(bio_err, "bad input format specified for input crl\n");
goto end;
}
if (x == NULL) {
BIO_printf(bio_err, "unable to load CRL\n");
ERR_print_errors(bio_err);
goto end;
}
end:
BIO_free(in);
return x;
}
EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *key_descrip)
{
BIO *key = NULL;
EVP_PKEY *pkey = NULL;
PW_CB_DATA cb_data;
cb_data.password = pass;
cb_data.prompt_info = file;
if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
BIO_printf(bio_err, "no keyfile specified\n");
goto end;
}
if (format == FORMAT_ENGINE) {
if (e == NULL) {
BIO_printf(bio_err, "no engine specified\n");
} else {
#ifndef OPENSSL_NO_ENGINE
if (ENGINE_init(e)) {
pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data);
ENGINE_finish(e);
}
if (pkey == NULL) {
BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip);
ERR_print_errors(bio_err);
}
#else
BIO_printf(bio_err, "engines not supported\n");
#endif
}
goto end;
}
if (file == NULL && maybe_stdin) {
unbuffer(stdin);
key = dup_bio_in(format);
} else {
key = bio_open_default(file, 'r', format);
}
if (key == NULL)
goto end;
if (format == FORMAT_ASN1) {
pkey = d2i_PrivateKey_bio(key, NULL);
} else if (format == FORMAT_PEM) {
pkey = PEM_read_bio_PrivateKey(key, NULL,
(pem_password_cb *)password_callback,
&cb_data);
} else if (format == FORMAT_PKCS12) {
if (!load_pkcs12(key, key_descrip,
(pem_password_cb *)password_callback, &cb_data,
&pkey, NULL, NULL))
goto end;
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
} else if (format == FORMAT_MSBLOB) {
pkey = b2i_PrivateKey_bio(key);
} else if (format == FORMAT_PVK) {
pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback,
&cb_data);
#endif
} else {
BIO_printf(bio_err, "bad input format specified for key file\n");
goto end;
}
end:
BIO_free(key);
if (pkey == NULL) {
BIO_printf(bio_err, "unable to load %s\n", key_descrip);
ERR_print_errors(bio_err);
}
return pkey;
}
EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *key_descrip)
{
BIO *key = NULL;
EVP_PKEY *pkey = NULL;
PW_CB_DATA cb_data;
cb_data.password = pass;
cb_data.prompt_info = file;
if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
BIO_printf(bio_err, "no keyfile specified\n");
goto end;
}
if (format == FORMAT_ENGINE) {
if (e == NULL) {
BIO_printf(bio_err, "no engine specified\n");
} else {
#ifndef OPENSSL_NO_ENGINE
pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data);
if (pkey == NULL) {
BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip);
ERR_print_errors(bio_err);
}
#else
BIO_printf(bio_err, "engines not supported\n");
#endif
}
goto end;
}
if (file == NULL && maybe_stdin) {
unbuffer(stdin);
key = dup_bio_in(format);
} else {
key = bio_open_default(file, 'r', format);
}
if (key == NULL)
goto end;
if (format == FORMAT_ASN1) {
pkey = d2i_PUBKEY_bio(key, NULL);
} else if (format == FORMAT_ASN1RSA) {
#ifndef OPENSSL_NO_RSA
RSA *rsa;
rsa = d2i_RSAPublicKey_bio(key, NULL);
if (rsa) {
pkey = EVP_PKEY_new();
if (pkey != NULL)
EVP_PKEY_set1_RSA(pkey, rsa);
RSA_free(rsa);
} else
#else
BIO_printf(bio_err, "RSA keys not supported\n");
#endif
pkey = NULL;
} else if (format == FORMAT_PEMRSA) {
#ifndef OPENSSL_NO_RSA
RSA *rsa;
rsa = PEM_read_bio_RSAPublicKey(key, NULL,
(pem_password_cb *)password_callback,
&cb_data);
if (rsa != NULL) {
pkey = EVP_PKEY_new();
if (pkey != NULL)
EVP_PKEY_set1_RSA(pkey, rsa);
RSA_free(rsa);
} else
#else
BIO_printf(bio_err, "RSA keys not supported\n");
#endif
pkey = NULL;
} else if (format == FORMAT_PEM) {
pkey = PEM_read_bio_PUBKEY(key, NULL,
(pem_password_cb *)password_callback,
&cb_data);
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
} else if (format == FORMAT_MSBLOB) {
pkey = b2i_PublicKey_bio(key);
#endif
}
end:
BIO_free(key);
if (pkey == NULL)
BIO_printf(bio_err, "unable to load %s\n", key_descrip);
return pkey;
}
static int load_certs_crls(const char *file, int format,
const char *pass, const char *desc,
STACK_OF(X509) **pcerts,
STACK_OF(X509_CRL) **pcrls)
{
int i;
BIO *bio;
STACK_OF(X509_INFO) *xis = NULL;
X509_INFO *xi;
PW_CB_DATA cb_data;
int rv = 0;
cb_data.password = pass;
cb_data.prompt_info = file;
if (format != FORMAT_PEM) {
BIO_printf(bio_err, "bad input format specified for %s\n", desc);
return 0;
}
bio = bio_open_default(file, 'r', FORMAT_PEM);
if (bio == NULL)
return 0;
xis = PEM_X509_INFO_read_bio(bio, NULL,
(pem_password_cb *)password_callback,
&cb_data);
BIO_free(bio);
if (pcerts != NULL && *pcerts == NULL) {
*pcerts = sk_X509_new_null();
if (*pcerts == NULL)
goto end;
}
if (pcrls != NULL && *pcrls == NULL) {
*pcrls = sk_X509_CRL_new_null();
if (*pcrls == NULL)
goto end;
}
for (i = 0; i < sk_X509_INFO_num(xis); i++) {
xi = sk_X509_INFO_value(xis, i);
if (xi->x509 != NULL && pcerts != NULL) {
if (!sk_X509_push(*pcerts, xi->x509))
goto end;
xi->x509 = NULL;
}
if (xi->crl != NULL && pcrls != NULL) {
if (!sk_X509_CRL_push(*pcrls, xi->crl))
goto end;
xi->crl = NULL;
}
}
if (pcerts != NULL && sk_X509_num(*pcerts) > 0)
rv = 1;
if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0)
rv = 1;
end:
sk_X509_INFO_pop_free(xis, X509_INFO_free);
if (rv == 0) {
if (pcerts != NULL) {
sk_X509_pop_free(*pcerts, X509_free);
*pcerts = NULL;
}
if (pcrls != NULL) {
sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
*pcrls = NULL;
}
BIO_printf(bio_err, "unable to load %s\n",
pcerts ? "certificates" : "CRLs");
ERR_print_errors(bio_err);
}
return rv;
}
void* app_malloc(int sz, const char *what)
{
void *vp = OPENSSL_malloc(sz);
if (vp == NULL) {
BIO_printf(bio_err, "%s: Could not allocate %d bytes for %s\n",
opt_getprog(), sz, what);
ERR_print_errors(bio_err);
exit(1);
}
return vp;
}
/*
* Initialize or extend, if *certs != NULL, a certificate stack.
*/
int load_certs(const char *file, STACK_OF(X509) **certs, int format,
const char *pass, const char *desc)
{
return load_certs_crls(file, format, pass, desc, certs, NULL);
}
/*
* Initialize or extend, if *crls != NULL, a certificate stack.
*/
int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
const char *pass, const char *desc)
{
return load_certs_crls(file, format, pass, desc, NULL, crls);
}
#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)
#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
int set_cert_ex(unsigned long *flags, const char *arg)
{
static const NAME_EX_TBL cert_tbl[] = {
{"compatible", X509_FLAG_COMPAT, 0xffffffffl},
{"ca_default", X509_FLAG_CA, 0xffffffffl},
{"no_header", X509_FLAG_NO_HEADER, 0},
{"no_version", X509_FLAG_NO_VERSION, 0},
{"no_serial", X509_FLAG_NO_SERIAL, 0},
{"no_signame", X509_FLAG_NO_SIGNAME, 0},
{"no_validity", X509_FLAG_NO_VALIDITY, 0},
{"no_subject", X509_FLAG_NO_SUBJECT, 0},
{"no_issuer", X509_FLAG_NO_ISSUER, 0},
{"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
{"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
{"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
{"no_aux", X509_FLAG_NO_AUX, 0},
{"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
{"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
{"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
{"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
{"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
{NULL, 0, 0}
};
return set_multi_opts(flags, arg, cert_tbl);
}
int set_name_ex(unsigned long *flags, const char *arg)
{
static const NAME_EX_TBL ex_tbl[] = {
{"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
{"esc_2254", ASN1_STRFLGS_ESC_2254, 0},
{"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
{"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
{"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
{"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
{"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
{"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
{"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
{"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
{"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
{"compat", XN_FLAG_COMPAT, 0xffffffffL},
{"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
{"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
{"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
{"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
{"dn_rev", XN_FLAG_DN_REV, 0},
{"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
{"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
{"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
{"align", XN_FLAG_FN_ALIGN, 0},
{"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
{"space_eq", XN_FLAG_SPC_EQ, 0},
{"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
{"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
{"oneline", XN_FLAG_ONELINE, 0xffffffffL},
{"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
{"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
{NULL, 0, 0}
};
if (set_multi_opts(flags, arg, ex_tbl) == 0)
return 0;
if (*flags != XN_FLAG_COMPAT
&& (*flags & XN_FLAG_SEP_MASK) == 0)
*flags |= XN_FLAG_SEP_CPLUS_SPC;
return 1;
}
int set_ext_copy(int *copy_type, const char *arg)
{
if (strcasecmp(arg, "none") == 0)
*copy_type = EXT_COPY_NONE;
else if (strcasecmp(arg, "copy") == 0)
*copy_type = EXT_COPY_ADD;
else if (strcasecmp(arg, "copyall") == 0)
*copy_type = EXT_COPY_ALL;
else
return 0;
return 1;
}
int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
{
STACK_OF(X509_EXTENSION) *exts = NULL;
X509_EXTENSION *ext, *tmpext;
ASN1_OBJECT *obj;
int i, idx, ret = 0;
if (!x || !req || (copy_type == EXT_COPY_NONE))
return 1;
exts = X509_REQ_get_extensions(req);
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
ext = sk_X509_EXTENSION_value(exts, i);
obj = X509_EXTENSION_get_object(ext);
idx = X509_get_ext_by_OBJ(x, obj, -1);
/* Does extension exist? */
if (idx != -1) {
/* If normal copy don't override existing extension */
if (copy_type == EXT_COPY_ADD)
continue;
/* Delete all extensions of same type */
do {
tmpext = X509_get_ext(x, idx);
X509_delete_ext(x, idx);
X509_EXTENSION_free(tmpext);
idx = X509_get_ext_by_OBJ(x, obj, -1);
} while (idx != -1);
}
if (!X509_add_ext(x, ext, -1))
goto end;
}
ret = 1;
end:
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
return ret;
}
static int set_multi_opts(unsigned long *flags, const char *arg,
const NAME_EX_TBL * in_tbl)
{
STACK_OF(CONF_VALUE) *vals;
CONF_VALUE *val;
int i, ret = 1;
if (!arg)
return 0;
vals = X509V3_parse_list(arg);
for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
val = sk_CONF_VALUE_value(vals, i);
if (!set_table_opts(flags, val->name, in_tbl))
ret = 0;
}
sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
return ret;
}
static int set_table_opts(unsigned long *flags, const char *arg,
const NAME_EX_TBL * in_tbl)
{
char c;
const NAME_EX_TBL *ptbl;
c = arg[0];
if (c == '-') {
c = 0;
arg++;
} else if (c == '+') {
c = 1;
arg++;
} else {
c = 1;
}
for (ptbl = in_tbl; ptbl->name; ptbl++) {
if (strcasecmp(arg, ptbl->name) == 0) {
*flags &= ~ptbl->mask;
if (c)
*flags |= ptbl->flag;
else
*flags &= ~ptbl->flag;
return 1;
}
}
return 0;
}
void print_name(BIO *out, const char *title, X509_NAME *nm,
unsigned long lflags)
{
char *buf;
char mline = 0;
int indent = 0;
if (title)
BIO_puts(out, title);
if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mline = 1;
indent = 4;
}
if (lflags == XN_FLAG_COMPAT) {
buf = X509_NAME_oneline(nm, 0, 0);
BIO_puts(out, buf);
BIO_puts(out, "\n");
OPENSSL_free(buf);
} else {
if (mline)
BIO_puts(out, "\n");
X509_NAME_print_ex(out, nm, indent, lflags);
BIO_puts(out, "\n");
}
}
void print_bignum_var(BIO *out, const BIGNUM *in, const char *var,
int len, unsigned char *buffer)
{
BIO_printf(out, " static unsigned char %s_%d[] = {", var, len);
if (BN_is_zero(in)) {
BIO_printf(out, "\n 0x00");
} else {
int i, l;
l = BN_bn2bin(in, buffer);
for (i = 0; i < l; i++) {
BIO_printf(out, (i % 10) == 0 ? "\n " : " ");
if (i < l - 1)
BIO_printf(out, "0x%02X,", buffer[i]);
else
BIO_printf(out, "0x%02X", buffer[i]);
}
}
BIO_printf(out, "\n };\n");
}
void print_array(BIO *out, const char* title, int len, const unsigned char* d)
{
int i;
BIO_printf(out, "unsigned char %s[%d] = {", title, len);
for (i = 0; i < len; i++) {
if ((i % 10) == 0)
BIO_printf(out, "\n ");
if (i < len - 1)
BIO_printf(out, "0x%02X, ", d[i]);
else
BIO_printf(out, "0x%02X", d[i]);
}
BIO_printf(out, "\n};\n");
}
X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, int noCApath)
{
X509_STORE *store = X509_STORE_new();
X509_LOOKUP *lookup;
if (store == NULL)
goto end;
if (CAfile != NULL || !noCAfile) {
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
if (lookup == NULL)
goto end;
if (CAfile) {
if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
BIO_printf(bio_err, "Error loading file %s\n", CAfile);
goto end;
}
} else {
X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
}
}
if (CApath != NULL || !noCApath) {
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
if (lookup == NULL)
goto end;
if (CApath) {
if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) {
BIO_printf(bio_err, "Error loading directory %s\n", CApath);
goto end;
}
} else {
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
}
}
ERR_clear_error();
return store;
end:
X509_STORE_free(store);
return NULL;
}
#ifndef OPENSSL_NO_ENGINE
/* Try to load an engine in a shareable library */
static ENGINE *try_load_engine(const char *engine)
{
ENGINE *e = ENGINE_by_id("dynamic");
if (e) {
if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
|| !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
ENGINE_free(e);
e = NULL;
}
}
return e;
}
#endif
ENGINE *setup_engine(const char *engine, int debug)
{
ENGINE *e = NULL;
#ifndef OPENSSL_NO_ENGINE
if (engine != NULL) {
if (strcmp(engine, "auto") == 0) {
BIO_printf(bio_err, "enabling auto ENGINE support\n");
ENGINE_register_all_complete();
return NULL;
}
if ((e = ENGINE_by_id(engine)) == NULL
&& (e = try_load_engine(engine)) == NULL) {
BIO_printf(bio_err, "invalid engine \"%s\"\n", engine);
ERR_print_errors(bio_err);
return NULL;
}
if (debug) {
ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0);
}
ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1);
if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
BIO_printf(bio_err, "can't use that engine\n");
ERR_print_errors(bio_err);
ENGINE_free(e);
return NULL;
}
BIO_printf(bio_err, "engine \"%s\" set.\n", ENGINE_get_id(e));
}
#endif
return e;
}
void release_engine(ENGINE *e)
{
#ifndef OPENSSL_NO_ENGINE
if (e != NULL)
/* Free our "structural" reference. */
ENGINE_free(e);
#endif
}
static unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
{
const char *n;
n = a[DB_serial];
while (*n == '0')
n++;
return OPENSSL_LH_strhash(n);
}
static int index_serial_cmp(const OPENSSL_CSTRING *a,
const OPENSSL_CSTRING *b)
{
const char *aa, *bb;
for (aa = a[DB_serial]; *aa == '0'; aa++) ;
for (bb = b[DB_serial]; *bb == '0'; bb++) ;
return strcmp(aa, bb);
}
static int index_name_qual(char **a)
{
return (a[0][0] == 'V');
}
static unsigned long index_name_hash(const OPENSSL_CSTRING *a)
{
return OPENSSL_LH_strhash(a[DB_name]);
}
int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
{
return strcmp(a[DB_name], b[DB_name]);
}
static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
#undef BSIZE
#define BSIZE 256
BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai)
{
BIO *in = NULL;
BIGNUM *ret = NULL;
char buf[1024];
ASN1_INTEGER *ai = NULL;
ai = ASN1_INTEGER_new();
if (ai == NULL)
goto err;
in = BIO_new_file(serialfile, "r");
if (in == NULL) {
if (!create) {
perror(serialfile);
goto err;
}
ERR_clear_error();
ret = BN_new();
if (ret == NULL || !rand_serial(ret, ai))
BIO_printf(bio_err, "Out of memory\n");
} else {
if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
BIO_printf(bio_err, "unable to load number from %s\n",
serialfile);
goto err;
}
ret = ASN1_INTEGER_to_BN(ai, NULL);
if (ret == NULL) {
BIO_printf(bio_err,
"error converting number from bin to BIGNUM\n");
goto err;
}
}
if (ret && retai) {
*retai = ai;
ai = NULL;
}
err:
BIO_free(in);
ASN1_INTEGER_free(ai);
return ret;
}
int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial,
ASN1_INTEGER **retai)
{
char buf[1][BSIZE];
BIO *out = NULL;
int ret = 0;
ASN1_INTEGER *ai = NULL;
int j;
if (suffix == NULL)
j = strlen(serialfile);
else
j = strlen(serialfile) + strlen(suffix) + 1;
if (j >= BSIZE) {
BIO_printf(bio_err, "file name too long\n");
goto err;
}
if (suffix == NULL)
OPENSSL_strlcpy(buf[0], serialfile, BSIZE);
else {
#ifndef OPENSSL_SYS_VMS
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix);
#else
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix);
#endif
}
out = BIO_new_file(buf[0], "w");
if (out == NULL) {
ERR_print_errors(bio_err);
goto err;
}
if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
BIO_printf(bio_err, "error converting serial to ASN.1 format\n");
goto err;
}
i2a_ASN1_INTEGER(out, ai);
BIO_puts(out, "\n");
ret = 1;
if (retai) {
*retai = ai;
ai = NULL;
}
err:
BIO_free_all(out);
ASN1_INTEGER_free(ai);
return ret;
}
int rotate_serial(const char *serialfile, const char *new_suffix,
const char *old_suffix)
{
char buf[2][BSIZE];
int i, j;
i = strlen(serialfile) + strlen(old_suffix);
j = strlen(serialfile) + strlen(new_suffix);
if (i > j)
j = i;
if (j + 1 >= BSIZE) {
BIO_printf(bio_err, "file name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix);
#else
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix);
#endif
if (rename(serialfile, buf[1]) < 0 && errno != ENOENT
#ifdef ENOTDIR
&& errno != ENOTDIR
#endif
) {
BIO_printf(bio_err,
"unable to rename %s to %s\n", serialfile, buf[1]);
perror("reason");
goto err;
}
if (rename(buf[0], serialfile) < 0) {
BIO_printf(bio_err,
"unable to rename %s to %s\n", buf[0], serialfile);
perror("reason");
rename(buf[1], serialfile);
goto err;
}
return 1;
err:
return 0;
}
int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
{
BIGNUM *btmp;
int ret = 0;
btmp = b == NULL ? BN_new() : b;
if (btmp == NULL)
return 0;
if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
goto error;
if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
goto error;
ret = 1;
error:
if (btmp != b)
BN_free(btmp);
return ret;
}
CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
{
CA_DB *retdb = NULL;
TXT_DB *tmpdb = NULL;
BIO *in;
CONF *dbattr_conf = NULL;
char buf[BSIZE];
#ifndef OPENSSL_NO_POSIX_IO
FILE *dbfp;
struct stat dbst;
#endif
in = BIO_new_file(dbfile, "r");
if (in == NULL) {
ERR_print_errors(bio_err);
goto err;
}
#ifndef OPENSSL_NO_POSIX_IO
BIO_get_fp(in, &dbfp);
if (fstat(fileno(dbfp), &dbst) == -1) {
SYSerr(SYS_F_FSTAT, errno);
ERR_add_error_data(3, "fstat('", dbfile, "')");
ERR_print_errors(bio_err);
goto err;
}
#endif
if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
goto err;
#ifndef OPENSSL_SYS_VMS
BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile);
#else
BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile);
#endif
dbattr_conf = app_load_config(buf);
retdb = app_malloc(sizeof(*retdb), "new DB");
retdb->db = tmpdb;
tmpdb = NULL;
if (db_attr)
retdb->attributes = *db_attr;
else {
retdb->attributes.unique_subject = 1;
}
if (dbattr_conf) {
char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
if (p) {
retdb->attributes.unique_subject = parse_yesno(p, 1);
}
}
retdb->dbfname = OPENSSL_strdup(dbfile);
#ifndef OPENSSL_NO_POSIX_IO
retdb->dbst = dbst;
#endif
err:
NCONF_free(dbattr_conf);
TXT_DB_free(tmpdb);
BIO_free_all(in);
return retdb;
}
/*
* Returns > 0 on success, <= 0 on error
*/
int index_index(CA_DB *db)
{
if (!TXT_DB_create_index(db->db, DB_serial, NULL,
LHASH_HASH_FN(index_serial),
LHASH_COMP_FN(index_serial))) {
BIO_printf(bio_err,
"error creating serial number index:(%ld,%ld,%ld)\n",
db->db->error, db->db->arg1, db->db->arg2);
return 0;
}
if (db->attributes.unique_subject
&& !TXT_DB_create_index(db->db, DB_name, index_name_qual,
LHASH_HASH_FN(index_name),
LHASH_COMP_FN(index_name))) {
BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n",
db->db->error, db->db->arg1, db->db->arg2);
return 0;
}
return 1;
}
int save_index(const char *dbfile, const char *suffix, CA_DB *db)
{
char buf[3][BSIZE];
BIO *out;
int j;
j = strlen(dbfile) + strlen(suffix);
if (j + 6 >= BSIZE) {
BIO_printf(bio_err, "file name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix);
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix);
#else
j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix);
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix);
#endif
out = BIO_new_file(buf[0], "w");
if (out == NULL) {
perror(dbfile);
BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
goto err;
}
j = TXT_DB_write(out, db->db);
BIO_free(out);
if (j <= 0)
goto err;
out = BIO_new_file(buf[1], "w");
if (out == NULL) {
perror(buf[2]);
BIO_printf(bio_err, "unable to open '%s'\n", buf[2]);
goto err;
}
BIO_printf(out, "unique_subject = %s\n",
db->attributes.unique_subject ? "yes" : "no");
BIO_free(out);
return 1;
err:
return 0;
}
int rotate_index(const char *dbfile, const char *new_suffix,
const char *old_suffix)
{
char buf[5][BSIZE];
int i, j;
i = strlen(dbfile) + strlen(old_suffix);
j = strlen(dbfile) + strlen(new_suffix);
if (i > j)
j = i;
if (j + 6 >= BSIZE) {
BIO_printf(bio_err, "file name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile);
j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix);
j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix);
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix);
#else
j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile);
j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix);
j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix);
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix);
#endif
if (rename(dbfile, buf[1]) < 0 && errno != ENOENT
#ifdef ENOTDIR
&& errno != ENOTDIR
#endif
) {
BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]);
perror("reason");
goto err;
}
if (rename(buf[0], dbfile) < 0) {
BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile);
perror("reason");
rename(buf[1], dbfile);
goto err;
}
if (rename(buf[4], buf[3]) < 0 && errno != ENOENT
#ifdef ENOTDIR
&& errno != ENOTDIR
#endif
) {
BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]);
perror("reason");
rename(dbfile, buf[0]);
rename(buf[1], dbfile);
goto err;
}
if (rename(buf[2], buf[4]) < 0) {
BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]);
perror("reason");
rename(buf[3], buf[4]);
rename(dbfile, buf[0]);
rename(buf[1], dbfile);
goto err;
}
return 1;
err:
return 0;
}
void free_index(CA_DB *db)
{
if (db) {
TXT_DB_free(db->db);
OPENSSL_free(db->dbfname);
OPENSSL_free(db);
}
}
int parse_yesno(const char *str, int def)
{
if (str) {
switch (*str) {
case 'f': /* false */
case 'F': /* FALSE */
case 'n': /* no */
case 'N': /* NO */
case '0': /* 0 */
return 0;
case 't': /* true */
case 'T': /* TRUE */
case 'y': /* yes */
case 'Y': /* YES */
case '1': /* 1 */
return 1;
}
}
return def;
}
/*
* name is expected to be in the format /type0=value0/type1=value1/type2=...
* where characters may be escaped by \
*/
X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
{
int nextismulti = 0;
char *work;
X509_NAME *n;
if (*cp++ != '/') {
BIO_printf(bio_err,
"name is expected to be in the format "
"/type0=value0/type1=value1/type2=... where characters may "
"be escaped by \\. This name is not in that format: '%s'\n",
--cp);
return NULL;
}
n = X509_NAME_new();
if (n == NULL)
return NULL;
work = OPENSSL_strdup(cp);
if (work == NULL)
goto err;
while (*cp) {
char *bp = work;
char *typestr = bp;
unsigned char *valstr;
int nid;
int ismulti = nextismulti;
nextismulti = 0;
/* Collect the type */
while (*cp && *cp != '=')
*bp++ = *cp++;
if (*cp == '\0') {
BIO_printf(bio_err,
"%s: Hit end of string before finding the equals.\n",
opt_getprog());
goto err;
}
*bp++ = '\0';
++cp;
/* Collect the value. */
valstr = (unsigned char *)bp;
for (; *cp && *cp != '/'; *bp++ = *cp++) {
if (canmulti && *cp == '+') {
nextismulti = 1;
break;
}
if (*cp == '\\' && *++cp == '\0') {
BIO_printf(bio_err,
"%s: escape character at end of string\n",
opt_getprog());
goto err;
}
}
*bp++ = '\0';
/* If not at EOS (must be + or /), move forward. */
if (*cp)
++cp;
/* Parse */
nid = OBJ_txt2nid(typestr);
if (nid == NID_undef) {
BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n",
opt_getprog(), typestr);
continue;
}
+ if (*valstr == '\0') {
+ BIO_printf(bio_err,
+ "%s: No value provided for Subject Attribute %s, skipped\n",
+ opt_getprog(), typestr);
+ continue;
+ }
if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
valstr, strlen((char *)valstr),
-1, ismulti ? -1 : 0))
goto err;
}
OPENSSL_free(work);
return n;
err:
X509_NAME_free(n);
OPENSSL_free(work);
return NULL;
}
/*
* Read whole contents of a BIO into an allocated memory buffer and return
* it.
*/
int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
{
BIO *mem;
int len, ret;
unsigned char tbuf[1024];
mem = BIO_new(BIO_s_mem());
if (mem == NULL)
return -1;
for (;;) {
if ((maxlen != -1) && maxlen < 1024)
len = maxlen;
else
len = 1024;
len = BIO_read(in, tbuf, len);
if (len < 0) {
BIO_free(mem);
return -1;
}
if (len == 0)
break;
if (BIO_write(mem, tbuf, len) != len) {
BIO_free(mem);
return -1;
}
maxlen -= len;
if (maxlen == 0)
break;
}
ret = BIO_get_mem_data(mem, (char **)out);
BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
BIO_free(mem);
return ret;
}
int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
{
int rv;
char *stmp, *vtmp = NULL;
stmp = OPENSSL_strdup(value);
if (!stmp)
return -1;
vtmp = strchr(stmp, ':');
if (vtmp) {
*vtmp = 0;
vtmp++;
}
rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
OPENSSL_free(stmp);
return rv;
}
static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes)
{
X509_POLICY_NODE *node;
int i;
BIO_printf(bio_err, "%s Policies:", name);
if (nodes) {
BIO_puts(bio_err, "\n");
for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
node = sk_X509_POLICY_NODE_value(nodes, i);
X509_POLICY_NODE_print(bio_err, node, 2);
}
} else {
BIO_puts(bio_err, " <empty>\n");
}
}
void policies_print(X509_STORE_CTX *ctx)
{
X509_POLICY_TREE *tree;
int explicit_policy;
tree = X509_STORE_CTX_get0_policy_tree(ctx);
explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
BIO_printf(bio_err, "Require explicit Policy: %s\n",
explicit_policy ? "True" : "False");
nodes_print("Authority", X509_policy_tree_get0_policies(tree));
nodes_print("User", X509_policy_tree_get0_user_policies(tree));
}
/*-
* next_protos_parse parses a comma separated list of strings into a string
* in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
* outlen: (output) set to the length of the resulting buffer on success.
* err: (maybe NULL) on failure, an error message line is written to this BIO.
* in: a NUL terminated string like "abc,def,ghi"
*
* returns: a malloc'd buffer or NULL on failure.
*/
unsigned char *next_protos_parse(size_t *outlen, const char *in)
{
size_t len;
unsigned char *out;
size_t i, start = 0;
len = strlen(in);
if (len >= 65535)
return NULL;
out = app_malloc(strlen(in) + 1, "NPN buffer");
for (i = 0; i <= len; ++i) {
if (i == len || in[i] == ',') {
if (i - start > 255) {
OPENSSL_free(out);
return NULL;
}
out[start] = (unsigned char)(i - start);
start = i + 1;
} else {
out[i + 1] = in[i];
}
}
*outlen = len + 1;
return out;
}
void print_cert_checks(BIO *bio, X509 *x,
const char *checkhost,
const char *checkemail, const char *checkip)
{
if (x == NULL)
return;
if (checkhost) {
BIO_printf(bio, "Hostname %s does%s match certificate\n",
checkhost,
X509_check_host(x, checkhost, 0, 0, NULL) == 1
? "" : " NOT");
}
if (checkemail) {
BIO_printf(bio, "Email %s does%s match certificate\n",
checkemail, X509_check_email(x, checkemail, 0, 0)
? "" : " NOT");
}
if (checkip) {
BIO_printf(bio, "IP %s does%s match certificate\n",
checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT");
}
}
/* Get first http URL from a DIST_POINT structure */
static const char *get_dp_url(DIST_POINT *dp)
{
GENERAL_NAMES *gens;
GENERAL_NAME *gen;
int i, gtype;
ASN1_STRING *uri;
if (!dp->distpoint || dp->distpoint->type != 0)
return NULL;
gens = dp->distpoint->name.fullname;
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
gen = sk_GENERAL_NAME_value(gens, i);
uri = GENERAL_NAME_get0_value(gen, &gtype);
if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) {
const char *uptr = (const char *)ASN1_STRING_get0_data(uri);
if (strncmp(uptr, "http://", 7) == 0)
return uptr;
}
}
return NULL;
}
/*
* Look through a CRLDP structure and attempt to find an http URL to
* downloads a CRL from.
*/
static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
{
int i;
const char *urlptr = NULL;
for (i = 0; i < sk_DIST_POINT_num(crldp); i++) {
DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
urlptr = get_dp_url(dp);
if (urlptr)
return load_crl(urlptr, FORMAT_HTTP);
}
return NULL;
}
/*
* Example of downloading CRLs from CRLDP: not usable for real world as it
* always downloads, doesn't support non-blocking I/O and doesn't cache
* anything.
*/
static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm)
{
X509 *x;
STACK_OF(X509_CRL) *crls = NULL;
X509_CRL *crl;
STACK_OF(DIST_POINT) *crldp;
crls = sk_X509_CRL_new_null();
if (!crls)
return NULL;
x = X509_STORE_CTX_get_current_cert(ctx);
crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
crl = load_crl_crldp(crldp);
sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
if (!crl) {
sk_X509_CRL_free(crls);
return NULL;
}
sk_X509_CRL_push(crls, crl);
/* Try to download delta CRL */
crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL);
crl = load_crl_crldp(crldp);
sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
if (crl)
sk_X509_CRL_push(crls, crl);
return crls;
}
void store_setup_crl_download(X509_STORE *st)
{
X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
}
/*
* Platform-specific sections
*/
#if defined(_WIN32)
# ifdef fileno
# undef fileno
# define fileno(a) (int)_fileno(a)
# endif
# include <windows.h>
# include <tchar.h>
static int WIN32_rename(const char *from, const char *to)
{
TCHAR *tfrom = NULL, *tto;
DWORD err;
int ret = 0;
if (sizeof(TCHAR) == 1) {
tfrom = (TCHAR *)from;
tto = (TCHAR *)to;
} else { /* UNICODE path */
size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1;
tfrom = malloc(sizeof(*tfrom) * (flen + tlen));
if (tfrom == NULL)
goto err;
tto = tfrom + flen;
# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen))
# endif
for (i = 0; i < flen; i++)
tfrom[i] = (TCHAR)from[i];
# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen))
# endif
for (i = 0; i < tlen; i++)
tto[i] = (TCHAR)to[i];
}
if (MoveFile(tfrom, tto))
goto ok;
err = GetLastError();
if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) {
if (DeleteFile(tto) && MoveFile(tfrom, tto))
goto ok;
err = GetLastError();
}
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
errno = ENOENT;
else if (err == ERROR_ACCESS_DENIED)
errno = EACCES;
else
errno = EINVAL; /* we could map more codes... */
err:
ret = -1;
ok:
if (tfrom != NULL && tfrom != (TCHAR *)from)
free(tfrom);
return ret;
}
#endif
/* app_tminterval section */
#if defined(_WIN32)
double app_tminterval(int stop, int usertime)
{
FILETIME now;
double ret = 0;
static ULARGE_INTEGER tmstart;
static int warning = 1;
# ifdef _WIN32_WINNT
static HANDLE proc = NULL;
if (proc == NULL) {
if (check_winnt())
proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
GetCurrentProcessId());
if (proc == NULL)
proc = (HANDLE) - 1;
}
if (usertime && proc != (HANDLE) - 1) {
FILETIME junk;
GetProcessTimes(proc, &junk, &junk, &junk, &now);
} else
# endif
{
SYSTEMTIME systime;
if (usertime && warning) {
BIO_printf(bio_err, "To get meaningful results, run "
"this program on idle system.\n");
warning = 0;
}
GetSystemTime(&systime);
SystemTimeToFileTime(&systime, &now);
}
if (stop == TM_START) {
tmstart.u.LowPart = now.dwLowDateTime;
tmstart.u.HighPart = now.dwHighDateTime;
} else {
ULARGE_INTEGER tmstop;
tmstop.u.LowPart = now.dwLowDateTime;
tmstop.u.HighPart = now.dwHighDateTime;
ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7;
}
return ret;
}
#elif defined(OPENSSL_SYSTEM_VXWORKS)
# include <time.h>
double app_tminterval(int stop, int usertime)
{
double ret = 0;
# ifdef CLOCK_REALTIME
static struct timespec tmstart;
struct timespec now;
# else
static unsigned long tmstart;
unsigned long now;
# endif
static int warning = 1;
if (usertime && warning) {
BIO_printf(bio_err, "To get meaningful results, run "
"this program on idle system.\n");
warning = 0;
}
# ifdef CLOCK_REALTIME
clock_gettime(CLOCK_REALTIME, &now);
if (stop == TM_START)
tmstart = now;
else
ret = ((now.tv_sec + now.tv_nsec * 1e-9)
- (tmstart.tv_sec + tmstart.tv_nsec * 1e-9));
# else
now = tickGet();
if (stop == TM_START)
tmstart = now;
else
ret = (now - tmstart) / (double)sysClkRateGet();
# endif
return ret;
}
#elif defined(OPENSSL_SYSTEM_VMS)
# include <time.h>
# include <times.h>
double app_tminterval(int stop, int usertime)
{
static clock_t tmstart;
double ret = 0;
clock_t now;
# ifdef __TMS
struct tms rus;
now = times(&rus);
if (usertime)
now = rus.tms_utime;
# else
if (usertime)
now = clock(); /* sum of user and kernel times */
else {
struct timeval tv;
gettimeofday(&tv, NULL);
now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK +
(unsigned long long)tv.tv_usec * (1000000 / CLK_TCK)
);
}
# endif
if (stop == TM_START)
tmstart = now;
else
ret = (now - tmstart) / (double)(CLK_TCK);
return ret;
}
#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
# include <sys/times.h>
double app_tminterval(int stop, int usertime)
{
double ret = 0;
struct tms rus;
clock_t now = times(&rus);
static clock_t tmstart;
if (usertime)
now = rus.tms_utime;
if (stop == TM_START) {
tmstart = now;
} else {
long int tck = sysconf(_SC_CLK_TCK);
ret = (now - tmstart) / (double)tck;
}
return ret;
}
#else
# include <sys/time.h>
# include <sys/resource.h>
double app_tminterval(int stop, int usertime)
{
double ret = 0;
struct rusage rus;
struct timeval now;
static struct timeval tmstart;
if (usertime)
getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime;
else
gettimeofday(&now, NULL);
if (stop == TM_START)
tmstart = now;
else
ret = ((now.tv_sec + now.tv_usec * 1e-6)
- (tmstart.tv_sec + tmstart.tv_usec * 1e-6));
return ret;
}
#endif
int app_access(const char* name, int flag)
{
#ifdef _WIN32
return _access(name, flag);
#else
return access(name, flag);
#endif
}
/* app_isdir section */
#ifdef _WIN32
int app_isdir(const char *name)
{
DWORD attr;
# if defined(UNICODE) || defined(_UNICODE)
size_t i, len_0 = strlen(name) + 1;
WCHAR tempname[MAX_PATH];
if (len_0 > MAX_PATH)
return -1;
# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH))
# endif
for (i = 0; i < len_0; i++)
tempname[i] = (WCHAR)name[i];
attr = GetFileAttributes(tempname);
# else
attr = GetFileAttributes(name);
# endif
if (attr == INVALID_FILE_ATTRIBUTES)
return -1;
return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0);
}
#else
# include <sys/stat.h>
# ifndef S_ISDIR
# if defined(_S_IFMT) && defined(_S_IFDIR)
# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR)
# else
# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
# endif
# endif
int app_isdir(const char *name)
{
# if defined(S_ISDIR)
struct stat st;
if (stat(name, &st) == 0)
return S_ISDIR(st.st_mode);
else
return -1;
# else
return -1;
# endif
}
#endif
/* raw_read|write section */
#if defined(__VMS)
# include "vms_term_sock.h"
static int stdin_sock = -1;
static void close_stdin_sock(void)
{
TerminalSocket (TERM_SOCK_DELETE, &stdin_sock);
}
int fileno_stdin(void)
{
if (stdin_sock == -1) {
TerminalSocket(TERM_SOCK_CREATE, &stdin_sock);
atexit(close_stdin_sock);
}
return stdin_sock;
}
#else
int fileno_stdin(void)
{
return fileno(stdin);
}
#endif
int fileno_stdout(void)
{
return fileno(stdout);
}
#if defined(_WIN32) && defined(STD_INPUT_HANDLE)
int raw_read_stdin(void *buf, int siz)
{
DWORD n;
if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL))
return n;
else
return -1;
}
#elif defined(__VMS)
# include <sys/socket.h>
int raw_read_stdin(void *buf, int siz)
{
return recv(fileno_stdin(), buf, siz, 0);
}
#else
int raw_read_stdin(void *buf, int siz)
{
return read(fileno_stdin(), buf, siz);
}
#endif
#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
int raw_write_stdout(const void *buf, int siz)
{
DWORD n;
if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL))
return n;
else
return -1;
}
#else
int raw_write_stdout(const void *buf, int siz)
{
return write(fileno_stdout(), buf, siz);
}
#endif
/*
* Centralized handling if input and output files with format specification
* The format is meant to show what the input and output is supposed to be,
* and is therefore a show of intent more than anything else. However, it
* does impact behavior on some platform, such as differentiating between
* text and binary input/output on non-Unix platforms
*/
static int istext(int format)
{
return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT;
}
BIO *dup_bio_in(int format)
{
return BIO_new_fp(stdin,
BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
}
static BIO_METHOD *prefix_method = NULL;
BIO *dup_bio_out(int format)
{
BIO *b = BIO_new_fp(stdout,
BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
void *prefix = NULL;
#ifdef OPENSSL_SYS_VMS
if (istext(format))
b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
#endif
if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
if (prefix_method == NULL)
prefix_method = apps_bf_prefix();
b = BIO_push(BIO_new(prefix_method), b);
BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix);
}
return b;
}
BIO *dup_bio_err(int format)
{
BIO *b = BIO_new_fp(stderr,
BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
#ifdef OPENSSL_SYS_VMS
if (istext(format))
b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
#endif
return b;
}
void destroy_prefix_method(void)
{
BIO_meth_free(prefix_method);
prefix_method = NULL;
}
void unbuffer(FILE *fp)
{
/*
* 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
setbuf(fp, NULL);
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma environment restore
#endif
}
static const char *modestr(char mode, int format)
{
OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w');
switch (mode) {
case 'a':
return istext(format) ? "a" : "ab";
case 'r':
return istext(format) ? "r" : "rb";
case 'w':
return istext(format) ? "w" : "wb";
}
/* The assert above should make sure we never reach this point */
return NULL;
}
static const char *modeverb(char mode)
{
switch (mode) {
case 'a':
return "appending";
case 'r':
return "reading";
case 'w':
return "writing";
}
return "(doing something)";
}
/*
* Open a file for writing, owner-read-only.
*/
BIO *bio_open_owner(const char *filename, int format, int private)
{
FILE *fp = NULL;
BIO *b = NULL;
int fd = -1, bflags, mode, textmode;
if (!private || filename == NULL || strcmp(filename, "-") == 0)
return bio_open_default(filename, 'w', format);
mode = O_WRONLY;
#ifdef O_CREAT
mode |= O_CREAT;
#endif
#ifdef O_TRUNC
mode |= O_TRUNC;
#endif
textmode = istext(format);
if (!textmode) {
#ifdef O_BINARY
mode |= O_BINARY;
#elif defined(_O_BINARY)
mode |= _O_BINARY;
#endif
}
#ifdef OPENSSL_SYS_VMS
/* VMS doesn't have O_BINARY, it just doesn't make sense. But,
* it still needs to know that we're going binary, or fdopen()
* will fail with "invalid argument"... so we tell VMS what the
* context is.
*/
if (!textmode)
fd = open(filename, mode, 0600, "ctx=bin");
else
#endif
fd = open(filename, mode, 0600);
if (fd < 0)
goto err;
fp = fdopen(fd, modestr('w', format));
if (fp == NULL)
goto err;
bflags = BIO_CLOSE;
if (textmode)
bflags |= BIO_FP_TEXT;
b = BIO_new_fp(fp, bflags);
if (b)
return b;
err:
BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n",
opt_getprog(), filename, strerror(errno));
ERR_print_errors(bio_err);
/* If we have fp, then fdopen took over fd, so don't close both. */
if (fp)
fclose(fp);
else if (fd >= 0)
close(fd);
return NULL;
}
static BIO *bio_open_default_(const char *filename, char mode, int format,
int quiet)
{
BIO *ret;
if (filename == NULL || strcmp(filename, "-") == 0) {
ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format);
if (quiet) {
ERR_clear_error();
return ret;
}
if (ret != NULL)
return ret;
BIO_printf(bio_err,
"Can't open %s, %s\n",
mode == 'r' ? "stdin" : "stdout", strerror(errno));
} else {
ret = BIO_new_file(filename, modestr(mode, format));
if (quiet) {
ERR_clear_error();
return ret;
}
if (ret != NULL)
return ret;
BIO_printf(bio_err,
"Can't open %s for %s, %s\n",
filename, modeverb(mode), strerror(errno));
}
ERR_print_errors(bio_err);
return NULL;
}
BIO *bio_open_default(const char *filename, char mode, int format)
{
return bio_open_default_(filename, mode, format, 0);
}
BIO *bio_open_default_quiet(const char *filename, char mode, int format)
{
return bio_open_default_(filename, mode, format, 1);
}
void wait_for_async(SSL *s)
{
/* On Windows select only works for sockets, so we simply don't wait */
#ifndef OPENSSL_SYS_WINDOWS
int width = 0;
fd_set asyncfds;
OSSL_ASYNC_FD *fds;
size_t numfds;
size_t i;
if (!SSL_get_all_async_fds(s, NULL, &numfds))
return;
if (numfds == 0)
return;
fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds");
if (!SSL_get_all_async_fds(s, fds, &numfds)) {
OPENSSL_free(fds);
return;
}
FD_ZERO(&asyncfds);
for (i = 0; i < numfds; i++) {
if (width <= (int)fds[i])
width = (int)fds[i] + 1;
openssl_fdset((int)fds[i], &asyncfds);
}
select(width, (void *)&asyncfds, NULL, NULL, NULL);
OPENSSL_free(fds);
#endif
}
/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */
#if defined(OPENSSL_SYS_MSDOS)
int has_stdin_waiting(void)
{
# if defined(OPENSSL_SYS_WINDOWS)
HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE);
DWORD events = 0;
INPUT_RECORD inputrec;
DWORD insize = 1;
BOOL peeked;
if (inhand == INVALID_HANDLE_VALUE) {
return 0;
}
peeked = PeekConsoleInput(inhand, &inputrec, insize, &events);
if (!peeked) {
/* Probably redirected input? _kbhit() does not work in this case */
if (!feof(stdin)) {
return 1;
}
return 0;
}
# endif
return _kbhit();
}
#endif
/* Corrupt a signature by modifying final byte */
void corrupt_signature(const ASN1_STRING *signature)
{
unsigned char *s = signature->data;
s[signature->length - 1] ^= 0x1;
}
int set_cert_times(X509 *x, const char *startdate, const char *enddate,
int days)
{
if (startdate == NULL || strcmp(startdate, "today") == 0) {
if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL)
return 0;
} else {
if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate))
return 0;
}
if (enddate == NULL) {
if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL)
== NULL)
return 0;
} else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) {
return 0;
}
return 1;
}
void make_uppercase(char *string)
{
int i;
for (i = 0; string[i] != '\0'; i++)
string[i] = toupper((unsigned char)string[i]);
}
diff --git a/apps/apps.h b/apps/apps.h
index 5b98d27500ce..d9eb650eb211 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -1,634 +1,634 @@
/*
* Copyright 1995-2018 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_APPS_H
# define HEADER_APPS_H
# include "e_os.h" /* struct timeval for DTLS */
# include "internal/nelem.h"
# include <assert.h>
# include <sys/types.h>
# ifndef OPENSSL_NO_POSIX_IO
# include <sys/stat.h>
# include <fcntl.h>
# endif
# include <openssl/e_os2.h>
# include <openssl/ossl_typ.h>
# include <openssl/bio.h>
# include <openssl/x509.h>
# include <openssl/conf.h>
# include <openssl/txt_db.h>
# include <openssl/engine.h>
# include <openssl/ocsp.h>
# include <signal.h>
# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE)
# define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
# else
# define openssl_fdset(a,b) FD_SET(a, b)
# endif
/*
* quick macro when you need to pass an unsigned char instead of a char.
* this is true for some implementations of the is*() functions, for
* example.
*/
#define _UC(c) ((unsigned char)(c))
void app_RAND_load_conf(CONF *c, const char *section);
void app_RAND_write(void);
extern char *default_config_file;
extern BIO *bio_in;
extern BIO *bio_out;
extern BIO *bio_err;
extern const unsigned char tls13_aes128gcmsha256_id[];
extern const unsigned char tls13_aes256gcmsha384_id[];
extern BIO_ADDR *ourpeer;
BIO_METHOD *apps_bf_prefix(void);
/*
* The control used to set the prefix with BIO_ctrl()
* We make it high enough so the chance of ever clashing with the BIO library
* remains unlikely for the foreseeable future and beyond.
*/
#define PREFIX_CTRL_SET_PREFIX (1 << 15)
/*
* apps_bf_prefix() returns a dynamically created BIO_METHOD, which we
* need to destroy at some point. When created internally, it's stored
* in an internal pointer which can be freed with the following function
*/
void destroy_prefix_method(void);
BIO *dup_bio_in(int format);
BIO *dup_bio_out(int format);
BIO *dup_bio_err(int format);
BIO *bio_open_owner(const char *filename, int format, int private);
BIO *bio_open_default(const char *filename, char mode, int format);
BIO *bio_open_default_quiet(const char *filename, char mode, int format);
CONF *app_load_config_bio(BIO *in, const char *filename);
CONF *app_load_config(const char *filename);
CONF *app_load_config_quiet(const char *filename);
int app_load_modules(const CONF *config);
void unbuffer(FILE *fp);
void wait_for_async(SSL *s);
# if defined(OPENSSL_SYS_MSDOS)
int has_stdin_waiting(void);
# endif
void corrupt_signature(const ASN1_STRING *signature);
int set_cert_times(X509 *x, const char *startdate, const char *enddate,
int days);
/*
* Common verification options.
*/
# define OPT_V_ENUM \
OPT_V__FIRST=2000, \
OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \
OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \
OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \
OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \
OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \
OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \
OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \
OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \
OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \
OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \
OPT_V__LAST
# define OPT_V_OPTIONS \
{ "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \
{ "purpose", OPT_V_PURPOSE, 's', \
"certificate chain purpose"}, \
{ "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \
{ "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \
"chain depth limit" }, \
{ "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \
"chain authentication security level" }, \
{ "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \
{ "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \
"expected peer hostname" }, \
{ "verify_email", OPT_V_VERIFY_EMAIL, 's', \
"expected peer email" }, \
{ "verify_ip", OPT_V_VERIFY_IP, 's', \
"expected peer IP address" }, \
{ "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \
"permit unhandled critical extensions"}, \
{ "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \
{ "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \
{ "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \
{ "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \
{ "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \
"set policy variable require-explicit-policy"}, \
{ "inhibit_any", OPT_V_INHIBIT_ANY, '-', \
"set policy variable inhibit-any-policy"}, \
{ "inhibit_map", OPT_V_INHIBIT_MAP, '-', \
"set policy variable inhibit-policy-mapping"}, \
{ "x509_strict", OPT_V_X509_STRICT, '-', \
"disable certificate compatibility work-arounds"}, \
{ "extended_crl", OPT_V_EXTENDED_CRL, '-', \
"enable extended CRL features"}, \
{ "use_deltas", OPT_V_USE_DELTAS, '-', \
"use delta CRLs"}, \
{ "policy_print", OPT_V_POLICY_PRINT, '-', \
"print policy processing diagnostics"}, \
{ "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \
"check root CA self-signatures"}, \
{ "trusted_first", OPT_V_TRUSTED_FIRST, '-', \
"search trust store first (default)" }, \
{ "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \
{ "suiteB_128", OPT_V_SUITEB_128, '-', \
"Suite B 128-bit mode allowing 192-bit algorithms"}, \
{ "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \
{ "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \
"accept chains anchored by intermediate trust-store CAs"}, \
{ "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \
{ "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \
{ "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" }
# define OPT_V_CASES \
OPT_V__FIRST: case OPT_V__LAST: break; \
case OPT_V_POLICY: \
case OPT_V_PURPOSE: \
case OPT_V_VERIFY_NAME: \
case OPT_V_VERIFY_DEPTH: \
case OPT_V_VERIFY_AUTH_LEVEL: \
case OPT_V_ATTIME: \
case OPT_V_VERIFY_HOSTNAME: \
case OPT_V_VERIFY_EMAIL: \
case OPT_V_VERIFY_IP: \
case OPT_V_IGNORE_CRITICAL: \
case OPT_V_ISSUER_CHECKS: \
case OPT_V_CRL_CHECK: \
case OPT_V_CRL_CHECK_ALL: \
case OPT_V_POLICY_CHECK: \
case OPT_V_EXPLICIT_POLICY: \
case OPT_V_INHIBIT_ANY: \
case OPT_V_INHIBIT_MAP: \
case OPT_V_X509_STRICT: \
case OPT_V_EXTENDED_CRL: \
case OPT_V_USE_DELTAS: \
case OPT_V_POLICY_PRINT: \
case OPT_V_CHECK_SS_SIG: \
case OPT_V_TRUSTED_FIRST: \
case OPT_V_SUITEB_128_ONLY: \
case OPT_V_SUITEB_128: \
case OPT_V_SUITEB_192: \
case OPT_V_PARTIAL_CHAIN: \
case OPT_V_NO_ALT_CHAINS: \
case OPT_V_NO_CHECK_TIME: \
case OPT_V_ALLOW_PROXY_CERTS
/*
* Common "extended validation" options.
*/
# define OPT_X_ENUM \
OPT_X__FIRST=1000, \
OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \
OPT_X_CERTFORM, OPT_X_KEYFORM, \
OPT_X__LAST
# define OPT_X_OPTIONS \
{ "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \
{ "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \
{ "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \
{ "xchain_build", OPT_X_CHAIN_BUILD, '-', \
"build certificate chain for the extended certificates"}, \
{ "xcertform", OPT_X_CERTFORM, 'F', \
"format of Extended certificate (PEM or DER) PEM default " }, \
{ "xkeyform", OPT_X_KEYFORM, 'F', \
"format of Extended certificate's key (PEM or DER) PEM default"}
# define OPT_X_CASES \
OPT_X__FIRST: case OPT_X__LAST: break; \
case OPT_X_KEY: \
case OPT_X_CERT: \
case OPT_X_CHAIN: \
case OPT_X_CHAIN_BUILD: \
case OPT_X_CERTFORM: \
case OPT_X_KEYFORM
/*
* Common SSL options.
* Any changes here must be coordinated with ../ssl/ssl_conf.c
*/
# define OPT_S_ENUM \
OPT_S__FIRST=3000, \
OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \
OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \
OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \
OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \
OPT_S_PRIORITIZE_CHACHA, \
OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \
OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \
OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \
OPT_S_MINPROTO, OPT_S_MAXPROTO, \
OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST
# define OPT_S_OPTIONS \
{"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \
{"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \
{"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \
{"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \
{"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \
{"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \
{"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \
{"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \
{"no_ticket", OPT_S_NOTICKET, '-', \
"Disable use of TLS session tickets"}, \
{"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \
{"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \
"Enable use of legacy renegotiation (dangerous)"}, \
{"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \
"Disable all renegotiation."}, \
{"legacy_server_connect", OPT_S_LEGACYCONN, '-', \
"Allow initial connection to servers that don't support RI"}, \
{"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \
"Disallow session resumption on renegotiation"}, \
{"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \
"Disallow initial connection to servers that don't support RI"}, \
{"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \
"In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \
{"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \
"Prioritize ChaCha ciphers when preferred by clients"}, \
{"strict", OPT_S_STRICT, '-', \
"Enforce strict certificate checks as per TLS standard"}, \
{"sigalgs", OPT_S_SIGALGS, 's', \
"Signature algorithms to support (colon-separated list)" }, \
{"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \
"Signature algorithms to support for client certificate" \
" authentication (colon-separated list)" }, \
{"groups", OPT_S_GROUPS, 's', \
"Groups to advertise (colon-separated list)" }, \
{"curves", OPT_S_CURVES, 's', \
"Groups to advertise (colon-separated list)" }, \
{"named_curve", OPT_S_NAMEDCURVE, 's', \
"Elliptic curve used for ECDHE (server-side only)" }, \
{"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \
{"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \
{"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \
{"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \
{"record_padding", OPT_S_RECORD_PADDING, 's', \
"Block size to pad TLS 1.3 records to."}, \
{"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \
"Perform all sorts of protocol violations for testing purposes"}, \
{"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \
"Disable TLSv1.3 middlebox compat mode" }
# define OPT_S_CASES \
OPT_S__FIRST: case OPT_S__LAST: break; \
case OPT_S_NOSSL3: \
case OPT_S_NOTLS1: \
case OPT_S_NOTLS1_1: \
case OPT_S_NOTLS1_2: \
case OPT_S_NOTLS1_3: \
case OPT_S_BUGS: \
case OPT_S_NO_COMP: \
case OPT_S_COMP: \
case OPT_S_NOTICKET: \
case OPT_S_SERVERPREF: \
case OPT_S_LEGACYRENEG: \
case OPT_S_LEGACYCONN: \
case OPT_S_ONRESUMP: \
case OPT_S_NOLEGACYCONN: \
case OPT_S_ALLOW_NO_DHE_KEX: \
case OPT_S_PRIORITIZE_CHACHA: \
case OPT_S_STRICT: \
case OPT_S_SIGALGS: \
case OPT_S_CLIENTSIGALGS: \
case OPT_S_GROUPS: \
case OPT_S_CURVES: \
case OPT_S_NAMEDCURVE: \
case OPT_S_CIPHER: \
case OPT_S_CIPHERSUITES: \
case OPT_S_RECORD_PADDING: \
case OPT_S_NO_RENEGOTIATION: \
case OPT_S_MINPROTO: \
case OPT_S_MAXPROTO: \
case OPT_S_DEBUGBROKE: \
case OPT_S_NO_MIDDLEBOX
#define IS_NO_PROT_FLAG(o) \
(o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \
|| o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3)
/*
* Random state options.
*/
# define OPT_R_ENUM \
OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST
# define OPT_R_OPTIONS \
{"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \
{"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"}
# define OPT_R_CASES \
OPT_R__FIRST: case OPT_R__LAST: break; \
case OPT_R_RAND: case OPT_R_WRITERAND
/*
* Option parsing.
*/
extern const char OPT_HELP_STR[];
extern const char OPT_MORE_STR[];
typedef struct options_st {
const char *name;
int retval;
/*
* value type: - no value (also the value zero), n number, p positive
* number, u unsigned, l long, s string, < input file, > output file,
* f any format, F der/pem format, E der/pem/engine format identifier.
* l, n and u include zero; p does not.
*/
int valtype;
const char *helpstr;
} OPTIONS;
/*
* A string/int pairing; widely use for option value lookup, hence the
* name OPT_PAIR. But that name is misleading in s_cb.c, so we also use
* the "generic" name STRINT_PAIR.
*/
typedef struct string_int_pair_st {
const char *name;
int retval;
} OPT_PAIR, STRINT_PAIR;
/* Flags to pass into opt_format; see FORMAT_xxx, below. */
# define OPT_FMT_PEMDER (1L << 1)
# define OPT_FMT_PKCS12 (1L << 2)
# define OPT_FMT_SMIME (1L << 3)
# define OPT_FMT_ENGINE (1L << 4)
# define OPT_FMT_MSBLOB (1L << 5)
-# define OPT_FMT_NETSCAPE (1L << 6)
+/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */
# define OPT_FMT_NSS (1L << 7)
# define OPT_FMT_TEXT (1L << 8)
# define OPT_FMT_HTTP (1L << 9)
# define OPT_FMT_PVK (1L << 10)
# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE)
# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME)
# define OPT_FMT_ANY ( \
OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \
- OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NETSCAPE | \
- OPT_FMT_NSS | OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK)
+ OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \
+ OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK)
char *opt_progname(const char *argv0);
char *opt_getprog(void);
char *opt_init(int ac, char **av, const OPTIONS * o);
int opt_next(void);
int opt_format(const char *s, unsigned long flags, int *result);
int opt_int(const char *arg, int *result);
int opt_ulong(const char *arg, unsigned long *result);
int opt_long(const char *arg, long *result);
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
defined(INTMAX_MAX) && defined(UINTMAX_MAX)
int opt_imax(const char *arg, intmax_t *result);
int opt_umax(const char *arg, uintmax_t *result);
#else
# define opt_imax opt_long
# define opt_umax opt_ulong
# define intmax_t long
# define uintmax_t unsigned long
#endif
int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result);
int opt_cipher(const char *name, const EVP_CIPHER **cipherp);
int opt_md(const char *name, const EVP_MD **mdp);
char *opt_arg(void);
char *opt_flag(void);
char *opt_unknown(void);
char **opt_rest(void);
int opt_num_rest(void);
int opt_verify(int i, X509_VERIFY_PARAM *vpm);
int opt_rand(int i);
void opt_help(const OPTIONS * list);
int opt_format_error(const char *s, unsigned long flags);
typedef struct args_st {
int size;
int argc;
char **argv;
} ARGS;
/*
* VMS C only for now, implemented in vms_decc_init.c
* If other C compilers forget to terminate argv with NULL, this function
* can be re-used.
*/
char **copy_argv(int *argc, char *argv[]);
/*
* Win32-specific argv initialization that splits OS-supplied UNICODE
* command line string to array of UTF8-encoded strings.
*/
void win32_utf8argv(int *argc, char **argv[]);
# define PW_MIN_LENGTH 4
typedef struct pw_cb_data {
const void *password;
const char *prompt_info;
} PW_CB_DATA;
int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data);
int setup_ui_method(void);
void destroy_ui_method(void);
const UI_METHOD *get_ui_method(void);
int chopup_args(ARGS *arg, char *buf);
# ifdef HEADER_X509_H
int dump_cert_text(BIO *out, X509 *x);
void print_name(BIO *out, const char *title, X509_NAME *nm,
unsigned long lflags);
# endif
void print_bignum_var(BIO *, const BIGNUM *, const char*,
int, unsigned char *);
void print_array(BIO *, const char *, int, const unsigned char *);
int set_nameopt(const char *arg);
unsigned long get_nameopt(void);
int set_cert_ex(unsigned long *flags, const char *arg);
int set_name_ex(unsigned long *flags, const char *arg);
int set_ext_copy(int *copy_type, const char *arg);
int copy_extensions(X509 *x, X509_REQ *req, int copy_type);
int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2);
int add_oid_section(CONF *conf);
X509 *load_cert(const char *file, int format, const char *cert_descrip);
X509_CRL *load_crl(const char *infile, int format);
EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *key_descrip);
EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *key_descrip);
int load_certs(const char *file, STACK_OF(X509) **certs, int format,
const char *pass, const char *cert_descrip);
int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
const char *pass, const char *cert_descrip);
X509_STORE *setup_verify(const char *CAfile, const char *CApath,
int noCAfile, int noCApath);
__owur int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath, int noCAfile,
int noCApath);
#ifndef OPENSSL_NO_CT
/*
* Sets the file to load the Certificate Transparency log list from.
* If path is NULL, loads from the default file path.
* Returns 1 on success, 0 otherwise.
*/
__owur int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path);
#endif
ENGINE *setup_engine(const char *engine, int debug);
void release_engine(ENGINE *e);
# ifndef OPENSSL_NO_OCSP
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);
# endif
/* Functions defined in ca.c and also used in ocsp.c */
int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
ASN1_GENERALIZEDTIME **pinvtm, const char *str);
# define DB_type 0
# define DB_exp_date 1
# define DB_rev_date 2
# define DB_serial 3 /* index - unique */
# define DB_file 4
# define DB_name 5 /* index - unique when active and not
* disabled */
# define DB_NUMBER 6
# define DB_TYPE_REV 'R' /* Revoked */
# define DB_TYPE_EXP 'E' /* Expired */
# define DB_TYPE_VAL 'V' /* Valid ; inserted with: ca ... -valid */
# define DB_TYPE_SUSP 'S' /* Suspended */
typedef struct db_attr_st {
int unique_subject;
} DB_ATTR;
typedef struct ca_db_st {
DB_ATTR attributes;
TXT_DB *db;
char *dbfname;
# ifndef OPENSSL_NO_POSIX_IO
struct stat dbst;
# endif
} CA_DB;
void* app_malloc(int sz, const char *what);
BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai);
int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial,
ASN1_INTEGER **retai);
int rotate_serial(const char *serialfile, const char *new_suffix,
const char *old_suffix);
int rand_serial(BIGNUM *b, ASN1_INTEGER *ai);
CA_DB *load_index(const char *dbfile, DB_ATTR *dbattr);
int index_index(CA_DB *db);
int save_index(const char *dbfile, const char *suffix, CA_DB *db);
int rotate_index(const char *dbfile, const char *new_suffix,
const char *old_suffix);
void free_index(CA_DB *db);
# define index_name_cmp_noconst(a, b) \
index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \
(const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b))
int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
int parse_yesno(const char *str, int def);
X509_NAME *parse_name(const char *str, long chtype, int multirdn);
void policies_print(X509_STORE_CTX *ctx);
int bio_to_mem(unsigned char **out, int maxlen, BIO *in);
int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value);
int init_gen_str(EVP_PKEY_CTX **pctx,
const char *algname, ENGINE *e, int do_param);
int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
STACK_OF(OPENSSL_STRING) *sigopts);
int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
STACK_OF(OPENSSL_STRING) *sigopts);
int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
STACK_OF(OPENSSL_STRING) *sigopts);
extern char *psk_key;
unsigned char *next_protos_parse(size_t *outlen, const char *in);
void print_cert_checks(BIO *bio, X509 *x,
const char *checkhost,
const char *checkemail, const char *checkip);
void store_setup_crl_download(X509_STORE *st);
/* See OPT_FMT_xxx, above. */
/* On some platforms, it's important to distinguish between text and binary
* files. On some, there might even be specific file formats for different
* contents. The FORMAT_xxx macros are meant to express an intent with the
* file being read or created.
*/
# define B_FORMAT_TEXT 0x8000
# define FORMAT_UNDEF 0
# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */
# define FORMAT_BINARY 2 /* Generic binary */
# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */
# define FORMAT_ASN1 4 /* ASN.1/DER */
# define FORMAT_PEM (5 | B_FORMAT_TEXT)
# define FORMAT_PKCS12 6
# define FORMAT_SMIME (7 | B_FORMAT_TEXT)
# define FORMAT_ENGINE 8 /* Not really a file format */
# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPubicKey format */
# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */
# define FORMAT_MSBLOB 11 /* MS Key blob format */
# define FORMAT_PVK 12 /* MS PVK file format */
# define FORMAT_HTTP 13 /* Download using HTTP */
# define FORMAT_NSS 14 /* NSS keylog format */
# define EXT_COPY_NONE 0
# define EXT_COPY_ADD 1
# define EXT_COPY_ALL 2
# define NETSCAPE_CERT_HDR "certificate"
# define APP_PASS_LEN 1024
/*
* IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits
* so that the first bit will never be one, so that the DER encoding
* rules won't force a leading octet.
*/
# define SERIAL_RAND_BITS 159
int app_isdir(const char *);
int app_access(const char *, int flag);
int fileno_stdin(void);
int fileno_stdout(void);
int raw_read_stdin(void *, int);
int raw_write_stdout(const void *, int);
# define TM_START 0
# define TM_STOP 1
double app_tminterval(int stop, int usertime);
void make_uppercase(char *string);
typedef struct verify_options_st {
int depth;
int quiet;
int error;
int return_error;
} VERIFY_CB_ARGS;
extern VERIFY_CB_ARGS verify_args;
#endif
diff --git a/apps/ca.c b/apps/ca.c
index 48f7cd197387..69207c0662ed 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -1,2605 +1,2606 @@
/*
* Copyright 1995-2018 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 <ctype.h>
#include <sys/types.h>
#include <openssl/conf.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/txt_db.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/ocsp.h>
#include <openssl/pem.h>
#ifndef W_OK
# ifdef OPENSSL_SYS_VMS
# include <unistd.h>
# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS)
# include <sys/file.h>
# endif
#endif
#include "apps.h"
#include "progs.h"
#ifndef W_OK
# define F_OK 0
# define W_OK 2
# define R_OK 4
#endif
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
#define BASE_SECTION "ca"
#define ENV_DEFAULT_CA "default_ca"
#define STRING_MASK "string_mask"
#define UTF8_IN "utf8"
#define ENV_NEW_CERTS_DIR "new_certs_dir"
#define ENV_CERTIFICATE "certificate"
#define ENV_SERIAL "serial"
#define ENV_RAND_SERIAL "rand_serial"
#define ENV_CRLNUMBER "crlnumber"
#define ENV_PRIVATE_KEY "private_key"
#define ENV_DEFAULT_DAYS "default_days"
#define ENV_DEFAULT_STARTDATE "default_startdate"
#define ENV_DEFAULT_ENDDATE "default_enddate"
#define ENV_DEFAULT_CRL_DAYS "default_crl_days"
#define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
#define ENV_DEFAULT_MD "default_md"
#define ENV_DEFAULT_EMAIL_DN "email_in_dn"
#define ENV_PRESERVE "preserve"
#define ENV_POLICY "policy"
#define ENV_EXTENSIONS "x509_extensions"
#define ENV_CRLEXT "crl_extensions"
#define ENV_MSIE_HACK "msie_hack"
#define ENV_NAMEOPT "name_opt"
#define ENV_CERTOPT "cert_opt"
#define ENV_EXTCOPY "copy_extensions"
#define ENV_UNIQUE_SUBJECT "unique_subject"
#define ENV_DATABASE "database"
/* Additional revocation information types */
typedef enum {
REV_VALID = -1, /* Valid (not-revoked) status */
REV_NONE = 0, /* No additional information */
REV_CRL_REASON = 1, /* Value is CRL reason code */
REV_HOLD = 2, /* Value is hold instruction */
REV_KEY_COMPROMISE = 3, /* Value is cert key compromise time */
REV_CA_COMPROMISE = 4 /* Value is CA key compromise time */
} REVINFO_TYPE;
static char *lookup_conf(const CONF *conf, const char *group, const char *tag);
static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate,
long days, int batch, const char *ext_sect, CONF *conf,
int verbose, unsigned long certopt, unsigned long nameopt,
int default_op, int ext_copy, int selfsign);
static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate, long days, int batch, const char *ext_sect,
CONF *conf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy);
static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
X509 *x509, const EVP_MD *dgst,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate, long days, const char *ext_sect, CONF *conf,
int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy);
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
const char *subj, unsigned long chtype, int multirdn,
int email_dn, const char *startdate, const char *enddate, long days,
int batch, int verbose, X509_REQ *req, const char *ext_sect,
CONF *conf, unsigned long certopt, unsigned long nameopt,
int default_op, int ext_copy, int selfsign);
static int get_certificate_status(const char *ser_status, CA_DB *db);
static int do_updatedb(CA_DB *db);
static int check_time_format(const char *str);
static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type,
const char *extval);
static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg);
static int make_revoked(X509_REVOKED *rev, const char *str);
static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str);
static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
static CONF *extconf = NULL;
static int preserve = 0;
static int msie_hack = 0;
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_ENGINE, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SUBJ, OPT_UTF8,
OPT_CREATE_SERIAL, OPT_MULTIVALUE_RDN, OPT_STARTDATE, OPT_ENDDATE,
OPT_DAYS, OPT_MD, OPT_POLICY, OPT_KEYFILE, OPT_KEYFORM, OPT_PASSIN,
OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR,
OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN,
OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID,
OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS,
OPT_RAND_SERIAL,
OPT_R_ENUM,
/* Do not change the order here; see related case statements below */
OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE
} OPTION_CHOICE;
const OPTIONS ca_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"verbose", OPT_VERBOSE, '-', "Verbose output during processing"},
{"config", OPT_CONFIG, 's', "A config file"},
{"name", OPT_NAME, 's', "The particular CA definition to use"},
{"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"},
{"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
{"create_serial", OPT_CREATE_SERIAL, '-',
"If reading serial fails, create a new random serial"},
{"rand_serial", OPT_RAND_SERIAL, '-',
"Always create a random serial; do not store it"},
{"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
"Enable support for multivalued RDNs"},
{"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"},
{"enddate", OPT_ENDDATE, 's',
"YYMMDDHHMMSSZ cert notAfter (overrides -days)"},
{"days", OPT_DAYS, 'p', "Number of days to certify the cert for"},
{"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"},
{"policy", OPT_POLICY, 's', "The CA 'policy' to support"},
{"keyfile", OPT_KEYFILE, 's', "Private key"},
{"keyform", OPT_KEYFORM, 'f', "Private key file format (PEM or ENGINE)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"},
{"cert", OPT_CERT, '<', "The CA cert"},
{"selfsign", OPT_SELFSIGN, '-',
"Sign a cert with the key associated with it"},
{"in", OPT_IN, '<', "The input PEM encoded cert request(s)"},
{"out", OPT_OUT, '>', "Where to put the output file(s)"},
{"outdir", OPT_OUTDIR, '/', "Where to put output cert"},
{"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
{"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"},
{"batch", OPT_BATCH, '-', "Don't ask questions"},
{"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"},
{"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"},
{"gencrl", OPT_GENCRL, '-', "Generate a new CRL"},
{"msie_hack", OPT_MSIE_HACK, '-',
"msie modifications to handle all those universal strings"},
{"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"},
{"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"},
{"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"},
{"infiles", OPT_INFILES, '-', "The last argument, requests to process"},
{"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"},
{"spkac", OPT_SPKAC, '<',
"File contains DN and signed public key and challenge"},
{"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"},
{"valid", OPT_VALID, 's',
"Add a Valid(not-revoked) DB entry about a cert (given in file)"},
{"extensions", OPT_EXTENSIONS, 's',
"Extension section (override value in config file)"},
{"extfile", OPT_EXTFILE, '<',
"Configuration file with X509v3 extensions to add"},
{"status", OPT_STATUS, 's', "Shows cert status given the serial number"},
{"updatedb", OPT_UPDATEDB, '-', "Updates db for expired cert"},
{"crlexts", OPT_CRLEXTS, 's',
"CRL extension section (override value in config file)"},
{"crl_reason", OPT_CRL_REASON, 's', "revocation reason"},
{"crl_hold", OPT_CRL_HOLD, 's',
"the hold instruction, an OID. Sets revocation reason to certificateHold"},
{"crl_compromise", OPT_CRL_COMPROMISE, 's',
"sets compromise time to val and the revocation reason to keyCompromise"},
{"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's',
"sets compromise time to val and the revocation reason to CACompromise"},
OPT_R_OPTIONS,
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{NULL}
};
int ca_main(int argc, char **argv)
{
CONF *conf = NULL;
ENGINE *e = NULL;
BIGNUM *crlnumber = NULL, *serial = NULL;
EVP_PKEY *pkey = NULL;
BIO *in = NULL, *out = NULL, *Sout = NULL;
ASN1_INTEGER *tmpser;
ASN1_TIME *tmptm;
CA_DB *db = NULL;
DB_ATTR db_attr;
STACK_OF(CONF_VALUE) *attribs = NULL;
STACK_OF(OPENSSL_STRING) *sigopts = NULL;
STACK_OF(X509) *cert_sk = NULL;
X509_CRL *crl = NULL;
const EVP_MD *dgst = NULL;
char *configfile = default_config_file, *section = NULL;
char *md = NULL, *policy = NULL, *keyfile = NULL;
char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL;
const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL;
const char *extensions = NULL, *extfile = NULL, *passinarg = NULL;
char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL;
const char *serialfile = NULL, *subj = NULL;
char *prog, *startdate = NULL, *enddate = NULL;
char *dbfile = NULL, *f;
char new_cert[PATH_MAX];
char tmp[10 + 1] = "\0";
char *const *pp;
const char *p;
size_t outdirlen = 0;
int create_ser = 0, free_key = 0, total = 0, total_done = 0;
int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE;
int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0;
int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0;
int rand_ser = 0, i, j, selfsign = 0, def_nid, def_ret;
long crldays = 0, crlhours = 0, crlsec = 0, days = 0;
unsigned long chtype = MBSTRING_ASC, certopt = 0;
X509 *x509 = NULL, *x509p = NULL, *x = NULL;
REVINFO_TYPE rev_type = REV_NONE;
X509_REVOKED *r = NULL;
OPTION_CHOICE o;
prog = opt_init(argc, argv, ca_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(ca_options);
ret = 0;
goto end;
case OPT_IN:
req = 1;
infile = opt_arg();
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_VERBOSE:
verbose = 1;
break;
case OPT_CONFIG:
configfile = opt_arg();
break;
case OPT_NAME:
section = opt_arg();
break;
case OPT_SUBJ:
subj = opt_arg();
/* preserve=1; */
break;
case OPT_UTF8:
chtype = MBSTRING_UTF8;
break;
case OPT_RAND_SERIAL:
rand_ser = 1;
break;
case OPT_CREATE_SERIAL:
create_ser = 1;
break;
case OPT_MULTIVALUE_RDN:
multirdn = 1;
break;
case OPT_STARTDATE:
startdate = opt_arg();
break;
case OPT_ENDDATE:
enddate = opt_arg();
break;
case OPT_DAYS:
days = atoi(opt_arg());
break;
case OPT_MD:
md = opt_arg();
break;
case OPT_POLICY:
policy = opt_arg();
break;
case OPT_KEYFILE:
keyfile = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_KEY:
key = opt_arg();
break;
case OPT_CERT:
certfile = opt_arg();
break;
case OPT_SELFSIGN:
selfsign = 1;
break;
case OPT_OUTDIR:
outdir = opt_arg();
break;
case OPT_SIGOPT:
if (sigopts == NULL)
sigopts = sk_OPENSSL_STRING_new_null();
if (sigopts == NULL || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto end;
break;
case OPT_NOTEXT:
notext = 1;
break;
case OPT_BATCH:
batch = 1;
break;
case OPT_PRESERVEDN:
preserve = 1;
break;
case OPT_NOEMAILDN:
email_dn = 0;
break;
case OPT_GENCRL:
gencrl = 1;
break;
case OPT_MSIE_HACK:
msie_hack = 1;
break;
case OPT_CRLDAYS:
crldays = atol(opt_arg());
break;
case OPT_CRLHOURS:
crlhours = atol(opt_arg());
break;
case OPT_CRLSEC:
crlsec = atol(opt_arg());
break;
case OPT_INFILES:
req = 1;
goto end_of_options;
case OPT_SS_CERT:
ss_cert_file = opt_arg();
req = 1;
break;
case OPT_SPKAC:
spkac_file = opt_arg();
req = 1;
break;
case OPT_REVOKE:
infile = opt_arg();
dorevoke = 1;
break;
case OPT_VALID:
infile = opt_arg();
dorevoke = 2;
break;
case OPT_EXTENSIONS:
extensions = opt_arg();
break;
case OPT_EXTFILE:
extfile = opt_arg();
break;
case OPT_STATUS:
ser_status = opt_arg();
break;
case OPT_UPDATEDB:
doupdatedb = 1;
break;
case OPT_CRLEXTS:
crl_ext = opt_arg();
break;
case OPT_CRL_REASON: /* := REV_CRL_REASON */
case OPT_CRL_HOLD:
case OPT_CRL_COMPROMISE:
case OPT_CRL_CA_COMPROMISE:
rev_arg = opt_arg();
rev_type = (o - OPT_CRL_REASON) + REV_CRL_REASON;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
}
}
end_of_options:
argc = opt_num_rest();
argv = opt_rest();
BIO_printf(bio_err, "Using configuration from %s\n", configfile);
if ((conf = app_load_config(configfile)) == NULL)
goto end;
if (configfile != default_config_file && !app_load_modules(conf))
goto end;
/* Lets get the config section we are using */
if (section == NULL
&& (section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_CA)) == NULL)
goto end;
p = NCONF_get_string(conf, NULL, "oid_file");
if (p == NULL)
ERR_clear_error();
if (p != NULL) {
BIO *oid_bio = BIO_new_file(p, "r");
if (oid_bio == NULL) {
ERR_clear_error();
} else {
OBJ_create_objects(oid_bio);
BIO_free(oid_bio);
}
}
if (!add_oid_section(conf)) {
ERR_print_errors(bio_err);
goto end;
}
app_RAND_load_conf(conf, BASE_SECTION);
f = NCONF_get_string(conf, section, STRING_MASK);
if (f == NULL)
ERR_clear_error();
if (f != NULL && !ASN1_STRING_set_default_mask_asc(f)) {
BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
goto end;
}
if (chtype != MBSTRING_UTF8) {
f = NCONF_get_string(conf, section, UTF8_IN);
if (f == NULL)
ERR_clear_error();
else if (strcmp(f, "yes") == 0)
chtype = MBSTRING_UTF8;
}
db_attr.unique_subject = 1;
p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
if (p != NULL)
db_attr.unique_subject = parse_yesno(p, 1);
else
ERR_clear_error();
/*****************************************************************/
/* report status of cert with serial number given on command line */
if (ser_status) {
dbfile = lookup_conf(conf, section, ENV_DATABASE);
if (dbfile == NULL)
goto end;
db = load_index(dbfile, &db_attr);
if (db == NULL)
goto end;
if (index_index(db) <= 0)
goto end;
if (get_certificate_status(ser_status, db) != 1)
BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status);
goto end;
}
/*****************************************************************/
/* we definitely need a private key, so let's get it */
if (keyfile == NULL
&& (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL)
goto end;
if (key == NULL) {
free_key = 1;
if (!app_passwd(passinarg, NULL, &key, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
}
pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key");
if (key != NULL)
OPENSSL_cleanse(key, strlen(key));
if (pkey == NULL)
/* load_key() has already printed an appropriate message */
goto end;
/*****************************************************************/
/* we need a certificate */
if (!selfsign || spkac_file || ss_cert_file || gencrl) {
if (certfile == NULL
&& (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL)
goto end;
x509 = load_cert(certfile, FORMAT_PEM, "CA certificate");
if (x509 == NULL)
goto end;
if (!X509_check_private_key(x509, pkey)) {
BIO_printf(bio_err,
"CA certificate and CA private key do not match\n");
goto end;
}
}
if (!selfsign)
x509p = x509;
f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE);
if (f == NULL)
ERR_clear_error();
if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
preserve = 1;
f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK);
if (f == NULL)
ERR_clear_error();
if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
msie_hack = 1;
f = NCONF_get_string(conf, section, ENV_NAMEOPT);
if (f != NULL) {
if (!set_nameopt(f)) {
BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
goto end;
}
default_op = 0;
}
f = NCONF_get_string(conf, section, ENV_CERTOPT);
if (f != NULL) {
if (!set_cert_ex(&certopt, f)) {
BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
goto end;
}
default_op = 0;
} else {
ERR_clear_error();
}
f = NCONF_get_string(conf, section, ENV_EXTCOPY);
if (f != NULL) {
if (!set_ext_copy(&ext_copy, f)) {
BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
goto end;
}
} else {
ERR_clear_error();
}
/*****************************************************************/
/* lookup where to write new certificates */
if ((outdir == NULL) && (req)) {
outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR);
if (outdir == NULL) {
BIO_printf(bio_err,
"there needs to be defined a directory for new certificate to be placed in\n");
goto end;
}
#ifndef OPENSSL_SYS_VMS
/*
* outdir is a directory spec, but access() for VMS demands a
* filename. We could use the DEC C routine to convert the
- * directory syntax to Unixly, and give that to app_isdir,
+ * directory syntax to Unix, and give that to app_isdir,
* but for now the fopen will catch the error if it's not a
* directory
*/
if (app_isdir(outdir) <= 0) {
BIO_printf(bio_err, "%s: %s is not a directory\n", prog, outdir);
perror(outdir);
goto end;
}
#endif
}
/*****************************************************************/
/* we need to load the database file */
dbfile = lookup_conf(conf, section, ENV_DATABASE);
if (dbfile == NULL)
goto end;
db = load_index(dbfile, &db_attr);
if (db == NULL)
goto end;
/* Lets check some fields */
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) {
BIO_printf(bio_err,
"entry %d: not revoked yet, but has a revocation date\n",
i + 1);
goto end;
}
if ((pp[DB_type][0] == DB_TYPE_REV) &&
!make_revoked(NULL, pp[DB_rev_date])) {
BIO_printf(bio_err, " in entry %d\n", i + 1);
goto end;
}
if (!check_time_format((char *)pp[DB_exp_date])) {
BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1);
goto end;
}
p = pp[DB_serial];
j = strlen(p);
if (*p == '-') {
p++;
j--;
}
if ((j & 1) || (j < 2)) {
BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n",
i + 1, j);
goto end;
}
for ( ; *p; p++) {
if (!isxdigit(_UC(*p))) {
BIO_printf(bio_err,
"entry %d: bad char 0%o '%c' in serial number\n",
i + 1, *p, *p);
goto end;
}
}
}
if (verbose) {
TXT_DB_write(bio_out, db->db);
BIO_printf(bio_err, "%d entries loaded from the database\n",
sk_OPENSSL_PSTRING_num(db->db->data));
BIO_printf(bio_err, "generating index\n");
}
if (index_index(db) <= 0)
goto end;
/*****************************************************************/
/* Update the db file for expired certificates */
if (doupdatedb) {
if (verbose)
BIO_printf(bio_err, "Updating %s ...\n", dbfile);
i = do_updatedb(db);
if (i == -1) {
BIO_printf(bio_err, "Malloc failure\n");
goto end;
} else if (i == 0) {
if (verbose)
BIO_printf(bio_err, "No entries found to mark expired\n");
} else {
if (!save_index(dbfile, "new", db))
goto end;
if (!rotate_index(dbfile, "new", "old"))
goto end;
if (verbose)
BIO_printf(bio_err, "Done. %d entries marked as expired\n", i);
}
}
/*****************************************************************/
/* Read extensions config file */
if (extfile) {
if ((extconf = app_load_config(extfile)) == NULL) {
ret = 1;
goto end;
}
if (verbose)
BIO_printf(bio_err, "Successfully loaded extensions file %s\n",
extfile);
/* We can have sections in the ext file */
if (extensions == NULL) {
extensions = NCONF_get_string(extconf, "default", "extensions");
if (extensions == NULL)
extensions = "default";
}
}
/*****************************************************************/
if (req || gencrl) {
if (spkac_file != NULL) {
output_der = 1;
batch = 1;
}
}
def_ret = EVP_PKEY_get_default_digest_nid(pkey, &def_nid);
/*
* EVP_PKEY_get_default_digest_nid() returns 2 if the digest is
* mandatory for this algorithm.
*/
if (def_ret == 2 && def_nid == NID_undef) {
/* The signing algorithm requires there to be no digest */
dgst = EVP_md_null();
} else if (md == NULL
&& (md = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) {
goto end;
} else {
if (strcmp(md, "default") == 0) {
if (def_ret <= 0) {
BIO_puts(bio_err, "no default digest\n");
goto end;
}
md = (char *)OBJ_nid2sn(def_nid);
}
if (!opt_md(md, &dgst))
goto end;
}
if (req) {
if (email_dn == 1) {
char *tmp_email_dn = NULL;
tmp_email_dn = NCONF_get_string(conf, section, ENV_DEFAULT_EMAIL_DN);
if (tmp_email_dn != NULL && strcmp(tmp_email_dn, "no") == 0)
email_dn = 0;
}
if (verbose)
BIO_printf(bio_err, "message digest is %s\n",
OBJ_nid2ln(EVP_MD_type(dgst)));
if (policy == NULL
&& (policy = lookup_conf(conf, section, ENV_POLICY)) == NULL)
goto end;
if (verbose)
BIO_printf(bio_err, "policy is %s\n", policy);
if (NCONF_get_string(conf, section, ENV_RAND_SERIAL) != NULL) {
rand_ser = 1;
} else {
serialfile = lookup_conf(conf, section, ENV_SERIAL);
if (serialfile == NULL)
goto end;
}
if (extconf == NULL) {
/*
* no '-extfile' option, so we look for extensions in the main
* configuration file
*/
if (extensions == NULL) {
extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS);
if (extensions == NULL)
ERR_clear_error();
}
if (extensions != NULL) {
/* Check syntax of file */
X509V3_CTX ctx;
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, conf);
if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) {
BIO_printf(bio_err,
"Error Loading extension section %s\n",
extensions);
ret = 1;
goto end;
}
}
}
if (startdate == NULL) {
startdate = NCONF_get_string(conf, section, ENV_DEFAULT_STARTDATE);
if (startdate == NULL)
ERR_clear_error();
}
if (startdate != NULL && !ASN1_TIME_set_string_X509(NULL, startdate)) {
BIO_printf(bio_err,
"start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
goto end;
}
if (startdate == NULL)
startdate = "today";
if (enddate == NULL) {
enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE);
if (enddate == NULL)
ERR_clear_error();
}
if (enddate != NULL && !ASN1_TIME_set_string_X509(NULL, enddate)) {
BIO_printf(bio_err,
"end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
goto end;
}
if (days == 0) {
if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days))
days = 0;
}
if (enddate == NULL && days == 0) {
BIO_printf(bio_err, "cannot lookup how many days to certify for\n");
goto end;
}
if (rand_ser) {
if ((serial = BN_new()) == NULL || !rand_serial(serial, NULL)) {
BIO_printf(bio_err, "error generating serial number\n");
goto end;
}
} else {
if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
BIO_printf(bio_err, "error while loading serial number\n");
goto end;
}
if (verbose) {
if (BN_is_zero(serial)) {
BIO_printf(bio_err, "next serial number is 00\n");
} else {
if ((f = BN_bn2hex(serial)) == NULL)
goto end;
BIO_printf(bio_err, "next serial number is %s\n", f);
OPENSSL_free(f);
}
}
}
if ((attribs = NCONF_get_section(conf, policy)) == NULL) {
BIO_printf(bio_err, "unable to find 'section' for %s\n", policy);
goto end;
}
if ((cert_sk = sk_X509_new_null()) == NULL) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
if (spkac_file != NULL) {
total++;
j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts,
attribs, db, serial, subj, chtype, multirdn,
email_dn, startdate, enddate, days, extensions,
conf, verbose, certopt, get_nameopt(), default_op,
ext_copy);
if (j < 0)
goto end;
if (j > 0) {
total_done++;
BIO_printf(bio_err, "\n");
if (!BN_add_word(serial, 1))
goto end;
if (!sk_X509_push(cert_sk, x)) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
}
}
if (ss_cert_file != NULL) {
total++;
j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts,
attribs,
db, serial, subj, chtype, multirdn, email_dn,
startdate, enddate, days, batch, extensions,
conf, verbose, certopt, get_nameopt(), default_op,
ext_copy);
if (j < 0)
goto end;
if (j > 0) {
total_done++;
BIO_printf(bio_err, "\n");
if (!BN_add_word(serial, 1))
goto end;
if (!sk_X509_push(cert_sk, x)) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
}
}
if (infile != NULL) {
total++;
j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db,
serial, subj, chtype, multirdn, email_dn, startdate,
enddate, days, batch, extensions, conf, verbose,
certopt, get_nameopt(), default_op, ext_copy, selfsign);
if (j < 0)
goto end;
if (j > 0) {
total_done++;
BIO_printf(bio_err, "\n");
if (!BN_add_word(serial, 1))
goto end;
if (!sk_X509_push(cert_sk, x)) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
}
}
for (i = 0; i < argc; i++) {
total++;
j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db,
serial, subj, chtype, multirdn, email_dn, startdate,
enddate, days, batch, extensions, conf, verbose,
certopt, get_nameopt(), default_op, ext_copy, selfsign);
if (j < 0)
goto end;
if (j > 0) {
total_done++;
BIO_printf(bio_err, "\n");
if (!BN_add_word(serial, 1)) {
X509_free(x);
goto end;
}
if (!sk_X509_push(cert_sk, x)) {
BIO_printf(bio_err, "Memory allocation failure\n");
X509_free(x);
goto end;
}
}
}
/*
* we have a stack of newly certified certificates and a data base
* and serial number that need updating
*/
if (sk_X509_num(cert_sk) > 0) {
if (!batch) {
BIO_printf(bio_err,
"\n%d out of %d certificate requests certified, commit? [y/n]",
total_done, total);
(void)BIO_flush(bio_err);
tmp[0] = '\0';
if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
BIO_printf(bio_err, "CERTIFICATION CANCELED: I/O error\n");
ret = 0;
goto end;
}
if (tmp[0] != 'y' && tmp[0] != 'Y') {
BIO_printf(bio_err, "CERTIFICATION CANCELED\n");
ret = 0;
goto end;
}
}
BIO_printf(bio_err, "Write out database with %d new entries\n",
sk_X509_num(cert_sk));
- if (!rand_ser
+ if (serialfile != NULL
&& !save_serial(serialfile, "new", serial, NULL))
goto end;
if (!save_index(dbfile, "new", db))
goto end;
}
outdirlen = OPENSSL_strlcpy(new_cert, outdir, sizeof(new_cert));
#ifndef OPENSSL_SYS_VMS
outdirlen = OPENSSL_strlcat(new_cert, "/", sizeof(new_cert));
#endif
if (verbose)
BIO_printf(bio_err, "writing new certificates\n");
for (i = 0; i < sk_X509_num(cert_sk); i++) {
BIO *Cout = NULL;
X509 *xi = sk_X509_value(cert_sk, i);
ASN1_INTEGER *serialNumber = X509_get_serialNumber(xi);
const unsigned char *psn = ASN1_STRING_get0_data(serialNumber);
const int snl = ASN1_STRING_length(serialNumber);
const int filen_len = 2 * (snl > 0 ? snl : 1) + sizeof(".pem");
char *n = new_cert + outdirlen;
if (outdirlen + filen_len > PATH_MAX) {
BIO_printf(bio_err, "certificate file name too long\n");
goto end;
}
if (snl > 0) {
static const char HEX_DIGITS[] = "0123456789ABCDEF";
for (j = 0; j < snl; j++, psn++) {
*n++ = HEX_DIGITS[*psn >> 4];
*n++ = HEX_DIGITS[*psn & 0x0F];
}
} else {
*(n++) = '0';
*(n++) = '0';
}
*(n++) = '.';
*(n++) = 'p';
*(n++) = 'e';
*(n++) = 'm';
*n = '\0'; /* closing new_cert */
if (verbose)
BIO_printf(bio_err, "writing %s\n", new_cert);
Sout = bio_open_default(outfile, 'w',
output_der ? FORMAT_ASN1 : FORMAT_TEXT);
if (Sout == NULL)
goto end;
Cout = BIO_new_file(new_cert, "w");
if (Cout == NULL) {
perror(new_cert);
goto end;
}
write_new_certificate(Cout, xi, 0, notext);
write_new_certificate(Sout, xi, output_der, notext);
BIO_free_all(Cout);
BIO_free_all(Sout);
Sout = NULL;
}
if (sk_X509_num(cert_sk)) {
/* Rename the database and the serial file */
- if (!rotate_serial(serialfile, "new", "old"))
+ if (serialfile != NULL
+ && !rotate_serial(serialfile, "new", "old"))
goto end;
if (!rotate_index(dbfile, "new", "old"))
goto end;
BIO_printf(bio_err, "Data Base Updated\n");
}
}
/*****************************************************************/
if (gencrl) {
int crl_v2 = 0;
if (crl_ext == NULL) {
crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT);
if (crl_ext == NULL)
ERR_clear_error();
}
if (crl_ext != NULL) {
/* Check syntax of file */
X509V3_CTX ctx;
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, conf);
if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) {
BIO_printf(bio_err,
"Error Loading CRL extension section %s\n", crl_ext);
ret = 1;
goto end;
}
}
if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER))
!= NULL)
if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) {
BIO_printf(bio_err, "error while loading CRL number\n");
goto end;
}
if (!crldays && !crlhours && !crlsec) {
if (!NCONF_get_number(conf, section,
ENV_DEFAULT_CRL_DAYS, &crldays))
crldays = 0;
if (!NCONF_get_number(conf, section,
ENV_DEFAULT_CRL_HOURS, &crlhours))
crlhours = 0;
ERR_clear_error();
}
if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) {
BIO_printf(bio_err,
"cannot lookup how long until the next CRL is issued\n");
goto end;
}
if (verbose)
BIO_printf(bio_err, "making CRL\n");
if ((crl = X509_CRL_new()) == NULL)
goto end;
if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509)))
goto end;
tmptm = ASN1_TIME_new();
if (tmptm == NULL
|| X509_gmtime_adj(tmptm, 0) == NULL
|| !X509_CRL_set1_lastUpdate(crl, tmptm)
|| X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec,
NULL) == NULL) {
BIO_puts(bio_err, "error setting CRL nextUpdate\n");
ASN1_TIME_free(tmptm);
goto end;
}
X509_CRL_set1_nextUpdate(crl, tmptm);
ASN1_TIME_free(tmptm);
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
if (pp[DB_type][0] == DB_TYPE_REV) {
if ((r = X509_REVOKED_new()) == NULL)
goto end;
j = make_revoked(r, pp[DB_rev_date]);
if (!j)
goto end;
if (j == 2)
crl_v2 = 1;
if (!BN_hex2bn(&serial, pp[DB_serial]))
goto end;
tmpser = BN_to_ASN1_INTEGER(serial, NULL);
BN_free(serial);
serial = NULL;
if (!tmpser)
goto end;
X509_REVOKED_set_serialNumber(r, tmpser);
ASN1_INTEGER_free(tmpser);
X509_CRL_add0_revoked(crl, r);
}
}
/*
* sort the data so it will be written in serial number order
*/
X509_CRL_sort(crl);
/* we now have a CRL */
if (verbose)
BIO_printf(bio_err, "signing CRL\n");
/* Add any extensions asked for */
if (crl_ext != NULL || crlnumberfile != NULL) {
X509V3_CTX crlctx;
X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
X509V3_set_nconf(&crlctx, conf);
if (crl_ext != NULL)
if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
goto end;
if (crlnumberfile != NULL) {
tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
if (!tmpser)
goto end;
X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0);
ASN1_INTEGER_free(tmpser);
crl_v2 = 1;
if (!BN_add_word(crlnumber, 1))
goto end;
}
}
if (crl_ext != NULL || crl_v2) {
if (!X509_CRL_set_version(crl, 1))
goto end; /* version 2 CRL */
}
/* we have a CRL number that need updating */
- if (crlnumberfile != NULL)
- if (!rand_ser
- && !save_serial(crlnumberfile, "new", crlnumber, NULL))
- goto end;
+ if (crlnumberfile != NULL
+ && !save_serial(crlnumberfile, "new", crlnumber, NULL))
+ goto end;
BN_free(crlnumber);
crlnumber = NULL;
if (!do_X509_CRL_sign(crl, pkey, dgst, sigopts))
goto end;
Sout = bio_open_default(outfile, 'w',
output_der ? FORMAT_ASN1 : FORMAT_TEXT);
if (Sout == NULL)
goto end;
PEM_write_bio_X509_CRL(Sout, crl);
- if (crlnumberfile != NULL) /* Rename the crlnumber file */
- if (!rotate_serial(crlnumberfile, "new", "old"))
- goto end;
+ /* Rename the crlnumber file */
+ if (crlnumberfile != NULL
+ && !rotate_serial(crlnumberfile, "new", "old"))
+ goto end;
}
/*****************************************************************/
if (dorevoke) {
if (infile == NULL) {
BIO_printf(bio_err, "no input files\n");
goto end;
} else {
X509 *revcert;
revcert = load_cert(infile, FORMAT_PEM, infile);
if (revcert == NULL)
goto end;
if (dorevoke == 2)
rev_type = REV_VALID;
j = do_revoke(revcert, db, rev_type, rev_arg);
if (j <= 0)
goto end;
X509_free(revcert);
if (!save_index(dbfile, "new", db))
goto end;
if (!rotate_index(dbfile, "new", "old"))
goto end;
BIO_printf(bio_err, "Data Base Updated\n");
}
}
ret = 0;
end:
if (ret)
ERR_print_errors(bio_err);
BIO_free_all(Sout);
BIO_free_all(out);
BIO_free_all(in);
sk_X509_pop_free(cert_sk, X509_free);
if (free_key)
OPENSSL_free(key);
BN_free(serial);
BN_free(crlnumber);
free_index(db);
sk_OPENSSL_STRING_free(sigopts);
EVP_PKEY_free(pkey);
X509_free(x509);
X509_CRL_free(crl);
NCONF_free(conf);
NCONF_free(extconf);
release_engine(e);
return ret;
}
static char *lookup_conf(const CONF *conf, const char *section, const char *tag)
{
char *entry = NCONF_get_string(conf, section, tag);
if (entry == NULL)
BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag);
return entry;
}
static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate,
long days, int batch, const char *ext_sect, CONF *lconf,
int verbose, unsigned long certopt, unsigned long nameopt,
int default_op, int ext_copy, int selfsign)
{
X509_REQ *req = NULL;
BIO *in = NULL;
EVP_PKEY *pktmp = NULL;
int ok = -1, i;
in = BIO_new_file(infile, "r");
if (in == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) {
BIO_printf(bio_err, "Error reading certificate request in %s\n",
infile);
goto end;
}
if (verbose)
X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT);
BIO_printf(bio_err, "Check that the request matches the signature\n");
if (selfsign && !X509_REQ_check_private_key(req, pkey)) {
BIO_printf(bio_err,
"Certificate request and CA private key do not match\n");
ok = 0;
goto end;
}
if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) {
BIO_printf(bio_err, "error unpacking public key\n");
goto end;
}
i = X509_REQ_verify(req, pktmp);
pktmp = NULL;
if (i < 0) {
ok = 0;
BIO_printf(bio_err, "Signature verification problems....\n");
ERR_print_errors(bio_err);
goto end;
}
if (i == 0) {
ok = 0;
BIO_printf(bio_err,
"Signature did not match the certificate request\n");
ERR_print_errors(bio_err);
goto end;
} else {
BIO_printf(bio_err, "Signature ok\n");
}
ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
chtype, multirdn, email_dn, startdate, enddate, days, batch,
verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
ext_copy, selfsign);
end:
X509_REQ_free(req);
BIO_free(in);
return ok;
}
static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate, long days, int batch, const char *ext_sect,
CONF *lconf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy)
{
X509 *req = NULL;
X509_REQ *rreq = NULL;
EVP_PKEY *pktmp = NULL;
int ok = -1, i;
if ((req = load_cert(infile, FORMAT_PEM, infile)) == NULL)
goto end;
if (verbose)
X509_print(bio_err, req);
BIO_printf(bio_err, "Check that the request matches the signature\n");
if ((pktmp = X509_get0_pubkey(req)) == NULL) {
BIO_printf(bio_err, "error unpacking public key\n");
goto end;
}
i = X509_verify(req, pktmp);
if (i < 0) {
ok = 0;
BIO_printf(bio_err, "Signature verification problems....\n");
goto end;
}
if (i == 0) {
ok = 0;
BIO_printf(bio_err, "Signature did not match the certificate\n");
goto end;
} else {
BIO_printf(bio_err, "Signature ok\n");
}
if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL)
goto end;
ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
chtype, multirdn, email_dn, startdate, enddate, days, batch,
verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op,
ext_copy, 0);
end:
X509_REQ_free(rreq);
X509_free(req);
return ok;
}
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
const char *subj, unsigned long chtype, int multirdn,
int email_dn, const char *startdate, const char *enddate, long days,
int batch, int verbose, X509_REQ *req, const char *ext_sect,
CONF *lconf, unsigned long certopt, unsigned long nameopt,
int default_op, int ext_copy, int selfsign)
{
X509_NAME *name = NULL, *CAname = NULL, *subject = NULL;
const ASN1_TIME *tm;
ASN1_STRING *str, *str2;
ASN1_OBJECT *obj;
X509 *ret = NULL;
X509_NAME_ENTRY *ne, *tne;
EVP_PKEY *pktmp;
int ok = -1, i, j, last, nid;
const char *p;
CONF_VALUE *cv;
OPENSSL_STRING row[DB_NUMBER];
OPENSSL_STRING *irow = NULL;
OPENSSL_STRING *rrow = NULL;
char buf[25];
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
if (subj) {
X509_NAME *n = parse_name(subj, chtype, multirdn);
if (!n) {
ERR_print_errors(bio_err);
goto end;
}
X509_REQ_set_subject_name(req, n);
X509_NAME_free(n);
}
if (default_op)
BIO_printf(bio_err, "The Subject's Distinguished Name is as follows\n");
name = X509_REQ_get_subject_name(req);
for (i = 0; i < X509_NAME_entry_count(name); i++) {
ne = X509_NAME_get_entry(name, i);
str = X509_NAME_ENTRY_get_data(ne);
obj = X509_NAME_ENTRY_get_object(ne);
nid = OBJ_obj2nid(obj);
if (msie_hack) {
/* assume all type should be strings */
if (str->type == V_ASN1_UNIVERSALSTRING)
ASN1_UNIVERSALSTRING_to_string(str);
if (str->type == V_ASN1_IA5STRING && nid != NID_pkcs9_emailAddress)
str->type = V_ASN1_T61STRING;
if (nid == NID_pkcs9_emailAddress
&& str->type == V_ASN1_PRINTABLESTRING)
str->type = V_ASN1_IA5STRING;
}
/* If no EMAIL is wanted in the subject */
if (nid == NID_pkcs9_emailAddress && !email_dn)
continue;
/* check some things */
if (nid == NID_pkcs9_emailAddress && str->type != V_ASN1_IA5STRING) {
BIO_printf(bio_err,
"\nemailAddress type needs to be of type IA5STRING\n");
goto end;
}
if (str->type != V_ASN1_BMPSTRING && str->type != V_ASN1_UTF8STRING) {
j = ASN1_PRINTABLE_type(str->data, str->length);
if ((j == V_ASN1_T61STRING && str->type != V_ASN1_T61STRING) ||
(j == V_ASN1_IA5STRING && str->type == V_ASN1_PRINTABLESTRING))
{
BIO_printf(bio_err,
"\nThe string contains characters that are illegal for the ASN.1 type\n");
goto end;
}
}
if (default_op)
old_entry_print(obj, str);
}
/* Ok, now we check the 'policy' stuff. */
if ((subject = X509_NAME_new()) == NULL) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
/* take a copy of the issuer name before we mess with it. */
if (selfsign)
CAname = X509_NAME_dup(name);
else
CAname = X509_NAME_dup(X509_get_subject_name(x509));
if (CAname == NULL)
goto end;
str = str2 = NULL;
for (i = 0; i < sk_CONF_VALUE_num(policy); i++) {
cv = sk_CONF_VALUE_value(policy, i); /* get the object id */
if ((j = OBJ_txt2nid(cv->name)) == NID_undef) {
BIO_printf(bio_err,
"%s:unknown object type in 'policy' configuration\n",
cv->name);
goto end;
}
obj = OBJ_nid2obj(j);
last = -1;
for (;;) {
X509_NAME_ENTRY *push = NULL;
/* lookup the object in the supplied name list */
j = X509_NAME_get_index_by_OBJ(name, obj, last);
if (j < 0) {
if (last != -1)
break;
tne = NULL;
} else {
tne = X509_NAME_get_entry(name, j);
}
last = j;
/* depending on the 'policy', decide what to do. */
if (strcmp(cv->value, "optional") == 0) {
if (tne != NULL)
push = tne;
} else if (strcmp(cv->value, "supplied") == 0) {
if (tne == NULL) {
BIO_printf(bio_err,
"The %s field needed to be supplied and was missing\n",
cv->name);
goto end;
} else {
push = tne;
}
} else if (strcmp(cv->value, "match") == 0) {
int last2;
if (tne == NULL) {
BIO_printf(bio_err,
"The mandatory %s field was missing\n",
cv->name);
goto end;
}
last2 = -1;
again2:
j = X509_NAME_get_index_by_OBJ(CAname, obj, last2);
if ((j < 0) && (last2 == -1)) {
BIO_printf(bio_err,
"The %s field does not exist in the CA certificate,\n"
"the 'policy' is misconfigured\n", cv->name);
goto end;
}
if (j >= 0) {
push = X509_NAME_get_entry(CAname, j);
str = X509_NAME_ENTRY_get_data(tne);
str2 = X509_NAME_ENTRY_get_data(push);
last2 = j;
if (ASN1_STRING_cmp(str, str2) != 0)
goto again2;
}
if (j < 0) {
BIO_printf(bio_err,
"The %s field is different between\n"
"CA certificate (%s) and the request (%s)\n",
cv->name,
((str2 == NULL) ? "NULL" : (char *)str2->data),
((str == NULL) ? "NULL" : (char *)str->data));
goto end;
}
} else {
BIO_printf(bio_err,
"%s:invalid type in 'policy' configuration\n",
cv->value);
goto end;
}
if (push != NULL) {
if (!X509_NAME_add_entry(subject, push, -1, 0)) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
}
if (j < 0)
break;
}
}
if (preserve) {
X509_NAME_free(subject);
/* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
subject = X509_NAME_dup(name);
if (subject == NULL)
goto end;
}
/* We are now totally happy, lets make and sign the certificate */
if (verbose)
BIO_printf(bio_err,
"Everything appears to be ok, creating and signing the certificate\n");
if ((ret = X509_new()) == NULL)
goto end;
#ifdef X509_V3
/* Make it an X509 v3 certificate. */
if (!X509_set_version(ret, 2))
goto end;
#endif
if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL)
goto end;
if (selfsign) {
if (!X509_set_issuer_name(ret, subject))
goto end;
} else {
if (!X509_set_issuer_name(ret, X509_get_subject_name(x509)))
goto end;
}
if (!set_cert_times(ret, startdate, enddate, days))
goto end;
if (enddate != NULL) {
int tdays;
if (!ASN1_TIME_diff(&tdays, NULL, NULL, X509_get0_notAfter(ret)))
goto end;
days = tdays;
}
if (!X509_set_subject_name(ret, subject))
goto end;
pktmp = X509_REQ_get0_pubkey(req);
i = X509_set_pubkey(ret, pktmp);
if (!i)
goto end;
/* Lets add the extensions, if there are any */
if (ext_sect) {
X509V3_CTX ctx;
/* Initialize the context structure */
if (selfsign)
X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
else
X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
if (extconf != NULL) {
if (verbose)
BIO_printf(bio_err, "Extra configuration file found\n");
/* Use the extconf configuration db LHASH */
X509V3_set_nconf(&ctx, extconf);
/* Test the structure (needed?) */
/* X509V3_set_ctx_test(&ctx); */
/* Adds exts contained in the configuration file */
if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) {
BIO_printf(bio_err,
"ERROR: adding extensions in section %s\n",
ext_sect);
ERR_print_errors(bio_err);
goto end;
}
if (verbose)
BIO_printf(bio_err,
"Successfully added extensions from file.\n");
} else if (ext_sect) {
/* We found extensions to be set from config file */
X509V3_set_nconf(&ctx, lconf);
if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) {
BIO_printf(bio_err,
"ERROR: adding extensions in section %s\n",
ext_sect);
ERR_print_errors(bio_err);
goto end;
}
if (verbose)
BIO_printf(bio_err,
"Successfully added extensions from config\n");
}
}
/* Copy extensions from request (if any) */
if (!copy_extensions(ret, req, ext_copy)) {
BIO_printf(bio_err, "ERROR: adding extensions from request\n");
ERR_print_errors(bio_err);
goto end;
}
{
const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(ret);
if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0)
/* Make it an X509 v3 certificate. */
if (!X509_set_version(ret, 2))
goto end;
}
if (verbose)
BIO_printf(bio_err,
"The subject name appears to be ok, checking data base for clashes\n");
/* Build the correct Subject if no e-mail is wanted in the subject. */
if (!email_dn) {
X509_NAME_ENTRY *tmpne;
X509_NAME *dn_subject;
/*
* Its best to dup the subject DN and then delete any email addresses
* because this retains its structure.
*/
if ((dn_subject = X509_NAME_dup(subject)) == NULL) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
i = -1;
while ((i = X509_NAME_get_index_by_NID(dn_subject,
NID_pkcs9_emailAddress,
i)) >= 0) {
tmpne = X509_NAME_delete_entry(dn_subject, i--);
X509_NAME_ENTRY_free(tmpne);
}
if (!X509_set_subject_name(ret, dn_subject)) {
X509_NAME_free(dn_subject);
goto end;
}
X509_NAME_free(dn_subject);
}
row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0);
if (row[DB_name] == NULL) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
if (BN_is_zero(serial))
row[DB_serial] = OPENSSL_strdup("00");
else
row[DB_serial] = BN_bn2hex(serial);
if (row[DB_serial] == NULL) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
if (row[DB_name][0] == '\0') {
/*
* An empty subject! We'll use the serial number instead. If
* unique_subject is in use then we don't want different entries with
* empty subjects matching each other.
*/
OPENSSL_free(row[DB_name]);
row[DB_name] = OPENSSL_strdup(row[DB_serial]);
if (row[DB_name] == NULL) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
}
if (db->attributes.unique_subject) {
OPENSSL_STRING *crow = row;
rrow = TXT_DB_get_by_index(db->db, DB_name, crow);
if (rrow != NULL) {
BIO_printf(bio_err,
"ERROR:There is already a certificate for %s\n",
row[DB_name]);
}
}
if (rrow == NULL) {
rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
if (rrow != NULL) {
BIO_printf(bio_err,
"ERROR:Serial number %s has already been issued,\n",
row[DB_serial]);
BIO_printf(bio_err,
" check the database/serial_file for corruption\n");
}
}
if (rrow != NULL) {
BIO_printf(bio_err, "The matching entry has the following details\n");
if (rrow[DB_type][0] == DB_TYPE_EXP)
p = "Expired";
else if (rrow[DB_type][0] == DB_TYPE_REV)
p = "Revoked";
else if (rrow[DB_type][0] == DB_TYPE_VAL)
p = "Valid";
else
p = "\ninvalid type, Data base error\n";
BIO_printf(bio_err, "Type :%s\n", p);;
if (rrow[DB_type][0] == DB_TYPE_REV) {
p = rrow[DB_exp_date];
if (p == NULL)
p = "undef";
BIO_printf(bio_err, "Was revoked on:%s\n", p);
}
p = rrow[DB_exp_date];
if (p == NULL)
p = "undef";
BIO_printf(bio_err, "Expires on :%s\n", p);
p = rrow[DB_serial];
if (p == NULL)
p = "undef";
BIO_printf(bio_err, "Serial Number :%s\n", p);
p = rrow[DB_file];
if (p == NULL)
p = "undef";
BIO_printf(bio_err, "File name :%s\n", p);
p = rrow[DB_name];
if (p == NULL)
p = "undef";
BIO_printf(bio_err, "Subject Name :%s\n", p);
ok = -1; /* This is now a 'bad' error. */
goto end;
}
if (!default_op) {
BIO_printf(bio_err, "Certificate Details:\n");
/*
* Never print signature details because signature not present
*/
certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
X509_print_ex(bio_err, ret, nameopt, certopt);
}
BIO_printf(bio_err, "Certificate is to be certified until ");
ASN1_TIME_print(bio_err, X509_get0_notAfter(ret));
if (days)
BIO_printf(bio_err, " (%ld days)", days);
BIO_printf(bio_err, "\n");
if (!batch) {
BIO_printf(bio_err, "Sign the certificate? [y/n]:");
(void)BIO_flush(bio_err);
buf[0] = '\0';
if (fgets(buf, sizeof(buf), stdin) == NULL) {
BIO_printf(bio_err,
"CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
ok = 0;
goto end;
}
if (!(buf[0] == 'y' || buf[0] == 'Y')) {
BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n");
ok = 0;
goto end;
}
}
pktmp = X509_get0_pubkey(ret);
if (EVP_PKEY_missing_parameters(pktmp) &&
!EVP_PKEY_missing_parameters(pkey))
EVP_PKEY_copy_parameters(pktmp, pkey);
if (!do_X509_sign(ret, pkey, dgst, sigopts))
goto end;
/* We now just add it to the database as DB_TYPE_VAL('V') */
row[DB_type] = OPENSSL_strdup("V");
tm = X509_get0_notAfter(ret);
row[DB_exp_date] = app_malloc(tm->length + 1, "row expdate");
memcpy(row[DB_exp_date], tm->data, tm->length);
row[DB_exp_date][tm->length] = '\0';
row[DB_rev_date] = NULL;
row[DB_file] = OPENSSL_strdup("unknown");
if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
(row[DB_file] == NULL) || (row[DB_name] == NULL)) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row space");
for (i = 0; i < DB_NUMBER; i++)
irow[i] = row[i];
irow[DB_NUMBER] = NULL;
if (!TXT_DB_insert(db->db, irow)) {
BIO_printf(bio_err, "failed to update database\n");
BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
goto end;
}
irow = NULL;
ok = 1;
end:
if (ok != 1) {
for (i = 0; i < DB_NUMBER; i++)
OPENSSL_free(row[i]);
}
OPENSSL_free(irow);
X509_NAME_free(CAname);
X509_NAME_free(subject);
if (ok <= 0)
X509_free(ret);
else
*xret = ret;
return ok;
}
static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
{
if (output_der) {
(void)i2d_X509_bio(bp, x);
return;
}
if (!notext)
X509_print(bp, x);
PEM_write_bio_X509(bp, x);
}
static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
X509 *x509, const EVP_MD *dgst,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate, long days, const char *ext_sect,
CONF *lconf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy)
{
STACK_OF(CONF_VALUE) *sk = NULL;
LHASH_OF(CONF_VALUE) *parms = NULL;
X509_REQ *req = NULL;
CONF_VALUE *cv = NULL;
NETSCAPE_SPKI *spki = NULL;
char *type, *buf;
EVP_PKEY *pktmp = NULL;
X509_NAME *n = NULL;
X509_NAME_ENTRY *ne = NULL;
int ok = -1, i, j;
long errline;
int nid;
/*
* Load input file into a hash table. (This is just an easy
* way to read and parse the file, then put it into a convenient
* STACK format).
*/
parms = CONF_load(NULL, infile, &errline);
if (parms == NULL) {
BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile);
ERR_print_errors(bio_err);
goto end;
}
sk = CONF_get_section(parms, "default");
if (sk_CONF_VALUE_num(sk) == 0) {
BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
goto end;
}
/*
* Now create a dummy X509 request structure. We don't actually
* have an X509 request, but we have many of the components
* (a public key, various DN components). The idea is that we
* put these components into the right X509 request structure
* and we can use the same code as if you had a real X509 request.
*/
req = X509_REQ_new();
if (req == NULL) {
ERR_print_errors(bio_err);
goto end;
}
/*
* Build up the subject name set.
*/
n = X509_REQ_get_subject_name(req);
for (i = 0;; i++) {
if (sk_CONF_VALUE_num(sk) <= i)
break;
cv = sk_CONF_VALUE_value(sk, i);
type = cv->name;
/*
* Skip past any leading X. X: X, etc to allow for multiple instances
*/
for (buf = cv->name; *buf; buf++)
if ((*buf == ':') || (*buf == ',') || (*buf == '.')) {
buf++;
if (*buf)
type = buf;
break;
}
buf = cv->value;
if ((nid = OBJ_txt2nid(type)) == NID_undef) {
if (strcmp(type, "SPKAC") == 0) {
spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
if (spki == NULL) {
BIO_printf(bio_err,
"unable to load Netscape SPKAC structure\n");
ERR_print_errors(bio_err);
goto end;
}
}
continue;
}
if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
(unsigned char *)buf, -1, -1, 0))
goto end;
}
if (spki == NULL) {
BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n",
infile);
goto end;
}
/*
* Now extract the key from the SPKI structure.
*/
BIO_printf(bio_err, "Check that the SPKAC request matches the signature\n");
if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) {
BIO_printf(bio_err, "error unpacking SPKAC public key\n");
goto end;
}
j = NETSCAPE_SPKI_verify(spki, pktmp);
if (j <= 0) {
EVP_PKEY_free(pktmp);
BIO_printf(bio_err,
"signature verification failed on SPKAC public key\n");
goto end;
}
BIO_printf(bio_err, "Signature ok\n");
X509_REQ_set_pubkey(req, pktmp);
EVP_PKEY_free(pktmp);
ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
chtype, multirdn, email_dn, startdate, enddate, days, 1,
verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
ext_copy, 0);
end:
X509_REQ_free(req);
CONF_free(parms);
NETSCAPE_SPKI_free(spki);
X509_NAME_ENTRY_free(ne);
return ok;
}
static int check_time_format(const char *str)
{
return ASN1_TIME_set_string(NULL, str);
}
static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type,
const char *value)
{
const ASN1_TIME *tm = NULL;
char *row[DB_NUMBER], **rrow, **irow;
char *rev_str = NULL;
BIGNUM *bn = NULL;
int ok = -1, i;
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0);
bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL);
if (!bn)
goto end;
if (BN_is_zero(bn))
row[DB_serial] = OPENSSL_strdup("00");
else
row[DB_serial] = BN_bn2hex(bn);
BN_free(bn);
if (row[DB_name] != NULL && row[DB_name][0] == '\0') {
/* Entries with empty Subjects actually use the serial number instead */
OPENSSL_free(row[DB_name]);
row[DB_name] = OPENSSL_strdup(row[DB_serial]);
}
if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
/*
* We have to lookup by serial number because name lookup skips revoked
* certs
*/
rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
if (rrow == NULL) {
BIO_printf(bio_err,
"Adding Entry with serial number %s to DB for %s\n",
row[DB_serial], row[DB_name]);
/* We now just add it to the database as DB_TYPE_REV('V') */
row[DB_type] = OPENSSL_strdup("V");
tm = X509_get0_notAfter(x509);
row[DB_exp_date] = app_malloc(tm->length + 1, "row exp_data");
memcpy(row[DB_exp_date], tm->data, tm->length);
row[DB_exp_date][tm->length] = '\0';
row[DB_rev_date] = NULL;
row[DB_file] = OPENSSL_strdup("unknown");
if (row[DB_type] == NULL || row[DB_file] == NULL) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto end;
}
irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row ptr");
for (i = 0; i < DB_NUMBER; i++)
irow[i] = row[i];
irow[DB_NUMBER] = NULL;
if (!TXT_DB_insert(db->db, irow)) {
BIO_printf(bio_err, "failed to update database\n");
BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
OPENSSL_free(irow);
goto end;
}
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
/* Revoke Certificate */
if (rev_type == REV_VALID)
ok = 1;
else
/* Retry revocation after DB insertion */
ok = do_revoke(x509, db, rev_type, value);
goto end;
} else if (index_name_cmp_noconst(row, rrow)) {
BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]);
goto end;
} else if (rev_type == REV_VALID) {
BIO_printf(bio_err, "ERROR:Already present, serial number %s\n",
row[DB_serial]);
goto end;
} else if (rrow[DB_type][0] == DB_TYPE_REV) {
BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n",
row[DB_serial]);
goto end;
} else {
BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]);
rev_str = make_revocation_str(rev_type, value);
if (!rev_str) {
BIO_printf(bio_err, "Error in revocation arguments\n");
goto end;
}
rrow[DB_type][0] = DB_TYPE_REV;
rrow[DB_type][1] = '\0';
rrow[DB_rev_date] = rev_str;
}
ok = 1;
end:
for (i = 0; i < DB_NUMBER; i++)
OPENSSL_free(row[i]);
return ok;
}
static int get_certificate_status(const char *serial, CA_DB *db)
{
char *row[DB_NUMBER], **rrow;
int ok = -1, i;
size_t serial_len = strlen(serial);
/* Free Resources */
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
/* Malloc needed char spaces */
row[DB_serial] = app_malloc(serial_len + 2, "row serial#");
if (serial_len % 2) {
/*
* Set the first char to 0
*/
row[DB_serial][0] = '0';
/* Copy String from serial to row[DB_serial] */
memcpy(row[DB_serial] + 1, serial, serial_len);
row[DB_serial][serial_len + 1] = '\0';
} else {
/* Copy String from serial to row[DB_serial] */
memcpy(row[DB_serial], serial, serial_len);
row[DB_serial][serial_len] = '\0';
}
/* Make it Upper Case */
make_uppercase(row[DB_serial]);
ok = 1;
/* Search for the certificate */
rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
if (rrow == NULL) {
BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]);
ok = -1;
goto end;
} else if (rrow[DB_type][0] == DB_TYPE_VAL) {
BIO_printf(bio_err, "%s=Valid (%c)\n",
row[DB_serial], rrow[DB_type][0]);
goto end;
} else if (rrow[DB_type][0] == DB_TYPE_REV) {
BIO_printf(bio_err, "%s=Revoked (%c)\n",
row[DB_serial], rrow[DB_type][0]);
goto end;
} else if (rrow[DB_type][0] == DB_TYPE_EXP) {
BIO_printf(bio_err, "%s=Expired (%c)\n",
row[DB_serial], rrow[DB_type][0]);
goto end;
} else if (rrow[DB_type][0] == DB_TYPE_SUSP) {
BIO_printf(bio_err, "%s=Suspended (%c)\n",
row[DB_serial], rrow[DB_type][0]);
goto end;
} else {
BIO_printf(bio_err, "%s=Unknown (%c).\n",
row[DB_serial], rrow[DB_type][0]);
ok = -1;
}
end:
for (i = 0; i < DB_NUMBER; i++) {
OPENSSL_free(row[i]);
}
return ok;
}
static int do_updatedb(CA_DB *db)
{
ASN1_UTCTIME *a_tm = NULL;
int i, cnt = 0;
int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
char **rrow, *a_tm_s;
a_tm = ASN1_UTCTIME_new();
if (a_tm == NULL)
return -1;
/* get actual time and make a string */
if (X509_gmtime_adj(a_tm, 0) == NULL) {
ASN1_UTCTIME_free(a_tm);
return -1;
}
a_tm_s = app_malloc(a_tm->length + 1, "time string");
memcpy(a_tm_s, a_tm->data, a_tm->length);
a_tm_s[a_tm->length] = '\0';
if (strncmp(a_tm_s, "49", 2) <= 0)
a_y2k = 1;
else
a_y2k = 0;
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
rrow = sk_OPENSSL_PSTRING_value(db->db->data, i);
if (rrow[DB_type][0] == DB_TYPE_VAL) {
/* ignore entries that are not valid */
if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
db_y2k = 1;
else
db_y2k = 0;
if (db_y2k == a_y2k) {
/* all on the same y2k side */
if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) {
rrow[DB_type][0] = DB_TYPE_EXP;
rrow[DB_type][1] = '\0';
cnt++;
BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
}
} else if (db_y2k < a_y2k) {
rrow[DB_type][0] = DB_TYPE_EXP;
rrow[DB_type][1] = '\0';
cnt++;
BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
}
}
}
ASN1_UTCTIME_free(a_tm);
OPENSSL_free(a_tm_s);
return cnt;
}
static const char *crl_reasons[] = {
/* CRL reason strings */
"unspecified",
"keyCompromise",
"CACompromise",
"affiliationChanged",
"superseded",
"cessationOfOperation",
"certificateHold",
"removeFromCRL",
/* Additional pseudo reasons */
"holdInstruction",
"keyTime",
"CAkeyTime"
};
#define NUM_REASONS OSSL_NELEM(crl_reasons)
/*
* Given revocation information convert to a DB string. The format of the
* string is: revtime[,reason,extra]. Where 'revtime' is the revocation time
* (the current time). 'reason' is the optional CRL reason and 'extra' is any
* additional argument
*/
static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg)
{
char *str;
const char *reason = NULL, *other = NULL;
ASN1_OBJECT *otmp;
ASN1_UTCTIME *revtm = NULL;
int i;
switch (rev_type) {
case REV_NONE:
case REV_VALID:
break;
case REV_CRL_REASON:
for (i = 0; i < 8; i++) {
if (strcasecmp(rev_arg, crl_reasons[i]) == 0) {
reason = crl_reasons[i];
break;
}
}
if (reason == NULL) {
BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
return NULL;
}
break;
case REV_HOLD:
/* Argument is an OID */
otmp = OBJ_txt2obj(rev_arg, 0);
ASN1_OBJECT_free(otmp);
if (otmp == NULL) {
BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
return NULL;
}
reason = "holdInstruction";
other = rev_arg;
break;
case REV_KEY_COMPROMISE:
case REV_CA_COMPROMISE:
/* Argument is the key compromise time */
if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) {
BIO_printf(bio_err,
"Invalid time format %s. Need YYYYMMDDHHMMSSZ\n",
rev_arg);
return NULL;
}
other = rev_arg;
if (rev_type == REV_KEY_COMPROMISE)
reason = "keyTime";
else
reason = "CAkeyTime";
break;
}
revtm = X509_gmtime_adj(NULL, 0);
if (!revtm)
return NULL;
i = revtm->length + 1;
if (reason)
i += strlen(reason) + 1;
if (other)
i += strlen(other) + 1;
str = app_malloc(i, "revocation reason");
OPENSSL_strlcpy(str, (char *)revtm->data, i);
if (reason) {
OPENSSL_strlcat(str, ",", i);
OPENSSL_strlcat(str, reason, i);
}
if (other) {
OPENSSL_strlcat(str, ",", i);
OPENSSL_strlcat(str, other, i);
}
ASN1_UTCTIME_free(revtm);
return str;
}
/*-
* Convert revocation field to X509_REVOKED entry
* return code:
* 0 error
* 1 OK
* 2 OK and some extensions added (i.e. V2 CRL)
*/
static int make_revoked(X509_REVOKED *rev, const char *str)
{
char *tmp = NULL;
int reason_code = -1;
int i, ret = 0;
ASN1_OBJECT *hold = NULL;
ASN1_GENERALIZEDTIME *comp_time = NULL;
ASN1_ENUMERATED *rtmp = NULL;
ASN1_TIME *revDate = NULL;
i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
if (i == 0)
goto end;
if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
goto end;
if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) {
rtmp = ASN1_ENUMERATED_new();
if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code))
goto end;
if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
goto end;
}
if (rev && comp_time) {
if (!X509_REVOKED_add1_ext_i2d
(rev, NID_invalidity_date, comp_time, 0, 0))
goto end;
}
if (rev && hold) {
if (!X509_REVOKED_add1_ext_i2d
(rev, NID_hold_instruction_code, hold, 0, 0))
goto end;
}
if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
ret = 2;
else
ret = 1;
end:
OPENSSL_free(tmp);
ASN1_OBJECT_free(hold);
ASN1_GENERALIZEDTIME_free(comp_time);
ASN1_ENUMERATED_free(rtmp);
ASN1_TIME_free(revDate);
return ret;
}
static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str)
{
char buf[25], *pbuf;
const char *p;
int j;
j = i2a_ASN1_OBJECT(bio_err, obj);
pbuf = buf;
for (j = 22 - j; j > 0; j--)
*(pbuf++) = ' ';
*(pbuf++) = ':';
*(pbuf++) = '\0';
BIO_puts(bio_err, buf);
if (str->type == V_ASN1_PRINTABLESTRING)
BIO_printf(bio_err, "PRINTABLE:'");
else if (str->type == V_ASN1_T61STRING)
BIO_printf(bio_err, "T61STRING:'");
else if (str->type == V_ASN1_IA5STRING)
BIO_printf(bio_err, "IA5STRING:'");
else if (str->type == V_ASN1_UNIVERSALSTRING)
BIO_printf(bio_err, "UNIVERSALSTRING:'");
else
BIO_printf(bio_err, "ASN.1 %2d:'", str->type);
p = (const char *)str->data;
for (j = str->length; j > 0; j--) {
if ((*p >= ' ') && (*p <= '~'))
BIO_printf(bio_err, "%c", *p);
else if (*p & 0x80)
BIO_printf(bio_err, "\\0x%02X", *p);
else if ((unsigned char)*p == 0xf7)
BIO_printf(bio_err, "^?");
else
BIO_printf(bio_err, "^%c", *p + '@');
p++;
}
BIO_printf(bio_err, "'\n");
return 1;
}
int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
ASN1_GENERALIZEDTIME **pinvtm, const char *str)
{
char *tmp;
char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
int reason_code = -1;
int ret = 0;
unsigned int i;
ASN1_OBJECT *hold = NULL;
ASN1_GENERALIZEDTIME *comp_time = NULL;
tmp = OPENSSL_strdup(str);
if (!tmp) {
BIO_printf(bio_err, "memory allocation failure\n");
goto end;
}
p = strchr(tmp, ',');
rtime_str = tmp;
if (p) {
*p = '\0';
p++;
reason_str = p;
p = strchr(p, ',');
if (p) {
*p = '\0';
arg_str = p + 1;
}
}
if (prevtm) {
*prevtm = ASN1_UTCTIME_new();
if (*prevtm == NULL) {
BIO_printf(bio_err, "memory allocation failure\n");
goto end;
}
if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) {
BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
goto end;
}
}
if (reason_str) {
for (i = 0; i < NUM_REASONS; i++) {
if (strcasecmp(reason_str, crl_reasons[i]) == 0) {
reason_code = i;
break;
}
}
if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) {
BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
goto end;
}
if (reason_code == 7) {
reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
} else if (reason_code == 8) { /* Hold instruction */
if (!arg_str) {
BIO_printf(bio_err, "missing hold instruction\n");
goto end;
}
reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
hold = OBJ_txt2obj(arg_str, 0);
if (!hold) {
BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
goto end;
}
if (phold)
*phold = hold;
else
ASN1_OBJECT_free(hold);
} else if ((reason_code == 9) || (reason_code == 10)) {
if (!arg_str) {
BIO_printf(bio_err, "missing compromised time\n");
goto end;
}
comp_time = ASN1_GENERALIZEDTIME_new();
if (comp_time == NULL) {
BIO_printf(bio_err, "memory allocation failure\n");
goto end;
}
if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) {
BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
goto end;
}
if (reason_code == 9)
reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
else
reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
}
}
if (preason)
*preason = reason_code;
if (pinvtm) {
*pinvtm = comp_time;
comp_time = NULL;
}
ret = 1;
end:
OPENSSL_free(tmp);
ASN1_GENERALIZEDTIME_free(comp_time);
return ret;
}
diff --git a/apps/ocsp.c b/apps/ocsp.c
index eb822c2696eb..7fd78624bbcc 100644
--- a/apps/ocsp.c
+++ b/apps/ocsp.c
@@ -1,1591 +1,1593 @@
/*
* Copyright 2001-2018 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>
# if defined(OPENSSL_SYS_UNIX) && !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
/* 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 (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);
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 */
+ OPENSSL_free(kidpids);
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 (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/openssl.cnf b/apps/openssl.cnf
index 7d1a8bb6e7f0..6df2878d5021 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -1,352 +1,350 @@
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#
# Note that you can include other files from the main configuration
# file using the .include directive.
#.include filename
# This definition stops the following lines choking if HOME isn't
# defined.
HOME = .
-RANDFILE = $ENV::HOME/.rnd
# Extra OBJECT IDENTIFIER info:
#oid_file = $ENV::HOME/.oid
oid_section = new_oids
# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions =
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)
[ new_oids ]
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6
# Policies used by the TSA examples.
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
-RANDFILE = $dir/private/.rand # private random number file
x509_extensions = usr_cert # The extensions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
# Extension copying option: use with caution.
# copy_extensions = copy
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert
# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret
# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
# utf8only: only UTF8Strings (PKIX recommendation after 2004).
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
string_mask = utf8only
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd
# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
# SET-ex3 = SET extension number 3
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
# These extensions are added when 'ca' signs a request.
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This is required for TSA certificates.
# extendedKeyUsage = critical,timeStamping
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
# Key usage: this is typical for a CA certificate. However since it will
# prevent it being used as an test self-signed certificate it is best
# left out by default.
# keyUsage = cRLSign, keyCertSign
# Some might want this also
# nsCertType = sslCA, emailCA
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy
# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF
[ crl_ext ]
# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always
[ proxy_cert_ext ]
# These extensions should be added when creating a proxy certificate
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
####################################################################
[ tsa ]
default_tsa = tsa_config1 # the default TSA section
[ tsa_config1 ]
# These are used by the TSA reply generation only.
dir = ./demoCA # TSA root directory
serial = $dir/tsaserial # The current serial number (mandatory)
crypto_device = builtin # OpenSSL engine to use for signing
signer_cert = $dir/tsacert.pem # The TSA signing certificate
# (optional)
certs = $dir/cacert.pem # Certificate chain to include in reply
# (optional)
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
signer_digest = sha256 # Signing digest to use. (Optional)
default_policy = tsa_policy1 # Policy if request did not specify it
# (optional)
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory)
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
clock_precision_digits = 0 # number of digits after dot. (optional)
ordering = yes # Is ordering defined for timestamps?
# (optional, default: no)
tsa_name = yes # Must the TSA name be included in the reply?
# (optional, default: no)
ess_cert_id_chain = no # Must the ESS cert id chain be included?
# (optional, default: no)
ess_cert_id_alg = sha1 # algorithm to compute certificate
# identifier (optional, default: sha1)
diff --git a/apps/opt.c b/apps/opt.c
index cc1418449e29..666856535d5e 100644
--- a/apps/opt.c
+++ b/apps/opt.c
@@ -1,899 +1,898 @@
/*
* Copyright 2015-2018 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 "apps.h"
#include <string.h>
#if !defined(OPENSSL_SYS_MSDOS)
# include OPENSSL_UNISTD
#endif
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <openssl/bio.h>
#include <openssl/x509v3.h>
#define MAX_OPT_HELP_WIDTH 30
const char OPT_HELP_STR[] = "--";
const char OPT_MORE_STR[] = "---";
/* Our state */
static char **argv;
static int argc;
static int opt_index;
static char *arg;
static char *flag;
static char *dunno;
static const OPTIONS *unknown;
static const OPTIONS *opts;
static char prog[40];
/*
* Return the simple name of the program; removing various platform gunk.
*/
#if defined(OPENSSL_SYS_WIN32)
char *opt_progname(const char *argv0)
{
size_t i, n;
const char *p;
char *q;
/* find the last '/', '\' or ':' */
for (p = argv0 + strlen(argv0); --p > argv0;)
if (*p == '/' || *p == '\\' || *p == ':') {
p++;
break;
}
/* Strip off trailing nonsense. */
n = strlen(p);
if (n > 4 &&
(strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0))
n -= 4;
/* Copy over the name, in lowercase. */
if (n > sizeof(prog) - 1)
n = sizeof(prog) - 1;
for (q = prog, i = 0; i < n; i++, p++)
*q++ = tolower((unsigned char)*p);
*q = '\0';
return prog;
}
#elif defined(OPENSSL_SYS_VMS)
char *opt_progname(const char *argv0)
{
const char *p, *q;
/* Find last special character sys:[foo.bar]openssl */
for (p = argv0 + strlen(argv0); --p > argv0;)
if (*p == ':' || *p == ']' || *p == '>') {
p++;
break;
}
q = strrchr(p, '.');
strncpy(prog, p, sizeof(prog) - 1);
prog[sizeof(prog) - 1] = '\0';
if (q != NULL && q - p < sizeof(prog))
prog[q - p] = '\0';
return prog;
}
#else
char *opt_progname(const char *argv0)
{
const char *p;
/* Could use strchr, but this is like the ones above. */
for (p = argv0 + strlen(argv0); --p > argv0;)
if (*p == '/') {
p++;
break;
}
strncpy(prog, p, sizeof(prog) - 1);
prog[sizeof(prog) - 1] = '\0';
return prog;
}
#endif
char *opt_getprog(void)
{
return prog;
}
/* Set up the arg parsing. */
char *opt_init(int ac, char **av, const OPTIONS *o)
{
/* Store state. */
argc = ac;
argv = av;
opt_index = 1;
opts = o;
opt_progname(av[0]);
unknown = NULL;
for (; o->name; ++o) {
#ifndef NDEBUG
const OPTIONS *next;
int duplicated, i;
#endif
if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR)
continue;
#ifndef NDEBUG
i = o->valtype;
/* Make sure options are legit. */
assert(o->name[0] != '-');
assert(o->retval > 0);
switch (i) {
case 0: case '-': case '/': case '<': case '>': case 'E': case 'F':
case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's':
case 'u': case 'c':
break;
default:
assert(0);
}
/* Make sure there are no duplicates. */
for (next = o + 1; next->name; ++next) {
/*
* Some compilers inline strcmp and the assert string is too long.
*/
duplicated = strcmp(o->name, next->name) == 0;
assert(!duplicated);
}
#endif
if (o->name[0] == '\0') {
assert(unknown == NULL);
unknown = o;
assert(unknown->valtype == 0 || unknown->valtype == '-');
}
}
return prog;
}
static OPT_PAIR formats[] = {
{"PEM/DER", OPT_FMT_PEMDER},
{"pkcs12", OPT_FMT_PKCS12},
{"smime", OPT_FMT_SMIME},
{"engine", OPT_FMT_ENGINE},
{"msblob", OPT_FMT_MSBLOB},
- {"netscape", OPT_FMT_NETSCAPE},
{"nss", OPT_FMT_NSS},
{"text", OPT_FMT_TEXT},
{"http", OPT_FMT_HTTP},
{"pvk", OPT_FMT_PVK},
{NULL}
};
/* Print an error message about a failed format parse. */
int opt_format_error(const char *s, unsigned long flags)
{
OPT_PAIR *ap;
if (flags == OPT_FMT_PEMDER) {
BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n",
prog, s);
} else {
BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n",
prog, s);
for (ap = formats; ap->name; ap++)
if (flags & ap->retval)
BIO_printf(bio_err, " %s\n", ap->name);
}
return 0;
}
/* Parse a format string, put it into *result; return 0 on failure, else 1. */
int opt_format(const char *s, unsigned long flags, int *result)
{
switch (*s) {
default:
return 0;
case 'D':
case 'd':
if ((flags & OPT_FMT_PEMDER) == 0)
return opt_format_error(s, flags);
*result = FORMAT_ASN1;
break;
case 'T':
case 't':
if ((flags & OPT_FMT_TEXT) == 0)
return opt_format_error(s, flags);
*result = FORMAT_TEXT;
break;
case 'N':
case 'n':
if ((flags & OPT_FMT_NSS) == 0)
return opt_format_error(s, flags);
if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0)
return opt_format_error(s, flags);
*result = FORMAT_NSS;
break;
case 'S':
case 's':
if ((flags & OPT_FMT_SMIME) == 0)
return opt_format_error(s, flags);
*result = FORMAT_SMIME;
break;
case 'M':
case 'm':
if ((flags & OPT_FMT_MSBLOB) == 0)
return opt_format_error(s, flags);
*result = FORMAT_MSBLOB;
break;
case 'E':
case 'e':
if ((flags & OPT_FMT_ENGINE) == 0)
return opt_format_error(s, flags);
*result = FORMAT_ENGINE;
break;
case 'H':
case 'h':
if ((flags & OPT_FMT_HTTP) == 0)
return opt_format_error(s, flags);
*result = FORMAT_HTTP;
break;
case '1':
if ((flags & OPT_FMT_PKCS12) == 0)
return opt_format_error(s, flags);
*result = FORMAT_PKCS12;
break;
case 'P':
case 'p':
if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) {
if ((flags & OPT_FMT_PEMDER) == 0)
return opt_format_error(s, flags);
*result = FORMAT_PEM;
} else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) {
if ((flags & OPT_FMT_PVK) == 0)
return opt_format_error(s, flags);
*result = FORMAT_PVK;
} else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0
|| strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) {
if ((flags & OPT_FMT_PKCS12) == 0)
return opt_format_error(s, flags);
*result = FORMAT_PKCS12;
} else {
return 0;
}
break;
}
return 1;
}
/* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */
int opt_cipher(const char *name, const EVP_CIPHER **cipherp)
{
*cipherp = EVP_get_cipherbyname(name);
if (*cipherp != NULL)
return 1;
BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
return 0;
}
/*
* Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1.
*/
int opt_md(const char *name, const EVP_MD **mdp)
{
*mdp = EVP_get_digestbyname(name);
if (*mdp != NULL)
return 1;
BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
return 0;
}
/* Look through a list of name/value pairs. */
int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
{
const OPT_PAIR *pp;
for (pp = pairs; pp->name; pp++)
if (strcmp(pp->name, name) == 0) {
*result = pp->retval;
return 1;
}
BIO_printf(bio_err, "%s: Value must be one of:\n", prog);
for (pp = pairs; pp->name; pp++)
BIO_printf(bio_err, "\t%s\n", pp->name);
return 0;
}
/* Parse an int, put it into *result; return 0 on failure, else 1. */
int opt_int(const char *value, int *result)
{
long l;
if (!opt_long(value, &l))
return 0;
*result = (int)l;
if (*result != l) {
BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n",
prog, value);
return 0;
}
return 1;
}
static void opt_number_error(const char *v)
{
size_t i = 0;
struct strstr_pair_st {
char *prefix;
char *name;
} b[] = {
{"0x", "a hexadecimal"},
{"0X", "a hexadecimal"},
{"0", "an octal"}
};
for (i = 0; i < OSSL_NELEM(b); i++) {
if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) {
BIO_printf(bio_err,
"%s: Can't parse \"%s\" as %s number\n",
prog, v, b[i].name);
return;
}
}
BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v);
return;
}
/* Parse a long, put it into *result; return 0 on failure, else 1. */
int opt_long(const char *value, long *result)
{
int oerrno = errno;
long l;
char *endp;
errno = 0;
l = strtol(value, &endp, 0);
if (*endp
|| endp == value
|| ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE)
|| (l == 0 && errno != 0)) {
opt_number_error(value);
errno = oerrno;
return 0;
}
*result = l;
errno = oerrno;
return 1;
}
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
defined(INTMAX_MAX) && defined(UINTMAX_MAX)
/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */
int opt_imax(const char *value, intmax_t *result)
{
int oerrno = errno;
intmax_t m;
char *endp;
errno = 0;
m = strtoimax(value, &endp, 0);
if (*endp
|| endp == value
|| ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE)
|| (m == 0 && errno != 0)) {
opt_number_error(value);
errno = oerrno;
return 0;
}
*result = m;
errno = oerrno;
return 1;
}
/* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */
int opt_umax(const char *value, uintmax_t *result)
{
int oerrno = errno;
uintmax_t m;
char *endp;
errno = 0;
m = strtoumax(value, &endp, 0);
if (*endp
|| endp == value
|| (m == UINTMAX_MAX && errno == ERANGE)
|| (m == 0 && errno != 0)) {
opt_number_error(value);
errno = oerrno;
return 0;
}
*result = m;
errno = oerrno;
return 1;
}
#endif
/*
* Parse an unsigned long, put it into *result; return 0 on failure, else 1.
*/
int opt_ulong(const char *value, unsigned long *result)
{
int oerrno = errno;
char *endptr;
unsigned long l;
errno = 0;
l = strtoul(value, &endptr, 0);
if (*endptr
|| endptr == value
|| ((l == ULONG_MAX) && errno == ERANGE)
|| (l == 0 && errno != 0)) {
opt_number_error(value);
errno = oerrno;
return 0;
}
*result = l;
errno = oerrno;
return 1;
}
/*
* We pass opt as an int but cast it to "enum range" so that all the
* items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch
* in gcc do the right thing.
*/
enum range { OPT_V_ENUM };
int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
{
int i;
ossl_intmax_t t = 0;
ASN1_OBJECT *otmp;
X509_PURPOSE *xptmp;
const X509_VERIFY_PARAM *vtmp;
assert(vpm != NULL);
assert(opt > OPT_V__FIRST);
assert(opt < OPT_V__LAST);
switch ((enum range)opt) {
case OPT_V__FIRST:
case OPT_V__LAST:
return 0;
case OPT_V_POLICY:
otmp = OBJ_txt2obj(opt_arg(), 0);
if (otmp == NULL) {
BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg());
return 0;
}
X509_VERIFY_PARAM_add0_policy(vpm, otmp);
break;
case OPT_V_PURPOSE:
/* purpose name -> purpose index */
i = X509_PURPOSE_get_by_sname(opt_arg());
if (i < 0) {
BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg());
return 0;
}
/* purpose index -> purpose object */
xptmp = X509_PURPOSE_get0(i);
/* purpose object -> purpose value */
i = X509_PURPOSE_get_id(xptmp);
if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) {
BIO_printf(bio_err,
"%s: Internal error setting purpose %s\n",
prog, opt_arg());
return 0;
}
break;
case OPT_V_VERIFY_NAME:
vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
if (vtmp == NULL) {
BIO_printf(bio_err, "%s: Invalid verify name %s\n",
prog, opt_arg());
return 0;
}
X509_VERIFY_PARAM_set1(vpm, vtmp);
break;
case OPT_V_VERIFY_DEPTH:
i = atoi(opt_arg());
if (i >= 0)
X509_VERIFY_PARAM_set_depth(vpm, i);
break;
case OPT_V_VERIFY_AUTH_LEVEL:
i = atoi(opt_arg());
if (i >= 0)
X509_VERIFY_PARAM_set_auth_level(vpm, i);
break;
case OPT_V_ATTIME:
if (!opt_imax(opt_arg(), &t))
return 0;
if (t != (time_t)t) {
BIO_printf(bio_err, "%s: epoch time out of range %s\n",
prog, opt_arg());
return 0;
}
X509_VERIFY_PARAM_set_time(vpm, (time_t)t);
break;
case OPT_V_VERIFY_HOSTNAME:
if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
return 0;
break;
case OPT_V_VERIFY_EMAIL:
if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0))
return 0;
break;
case OPT_V_VERIFY_IP:
if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg()))
return 0;
break;
case OPT_V_IGNORE_CRITICAL:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL);
break;
case OPT_V_ISSUER_CHECKS:
/* NOP, deprecated */
break;
case OPT_V_CRL_CHECK:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK);
break;
case OPT_V_CRL_CHECK_ALL:
X509_VERIFY_PARAM_set_flags(vpm,
X509_V_FLAG_CRL_CHECK |
X509_V_FLAG_CRL_CHECK_ALL);
break;
case OPT_V_POLICY_CHECK:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK);
break;
case OPT_V_EXPLICIT_POLICY:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY);
break;
case OPT_V_INHIBIT_ANY:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY);
break;
case OPT_V_INHIBIT_MAP:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP);
break;
case OPT_V_X509_STRICT:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT);
break;
case OPT_V_EXTENDED_CRL:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT);
break;
case OPT_V_USE_DELTAS:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS);
break;
case OPT_V_POLICY_PRINT:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY);
break;
case OPT_V_CHECK_SS_SIG:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE);
break;
case OPT_V_TRUSTED_FIRST:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST);
break;
case OPT_V_SUITEB_128_ONLY:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY);
break;
case OPT_V_SUITEB_128:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS);
break;
case OPT_V_SUITEB_192:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS);
break;
case OPT_V_PARTIAL_CHAIN:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
break;
case OPT_V_NO_ALT_CHAINS:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS);
break;
case OPT_V_NO_CHECK_TIME:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME);
break;
case OPT_V_ALLOW_PROXY_CERTS:
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS);
break;
}
return 1;
}
/*
* Parse the next flag (and value if specified), return 0 if done, -1 on
* error, otherwise the flag's retval.
*/
int opt_next(void)
{
char *p;
const OPTIONS *o;
int ival;
long lval;
unsigned long ulval;
ossl_intmax_t imval;
ossl_uintmax_t umval;
/* Look at current arg; at end of the list? */
arg = NULL;
p = argv[opt_index];
if (p == NULL)
return 0;
/* If word doesn't start with a -, we're done. */
if (*p != '-')
return 0;
/* Hit "--" ? We're done. */
opt_index++;
if (strcmp(p, "--") == 0)
return 0;
/* Allow -nnn and --nnn */
if (*++p == '-')
p++;
flag = p - 1;
/* If we have --flag=foo, snip it off */
if ((arg = strchr(p, '=')) != NULL)
*arg++ = '\0';
for (o = opts; o->name; ++o) {
/* If not this option, move on to the next one. */
if (strcmp(p, o->name) != 0)
continue;
/* If it doesn't take a value, make sure none was given. */
if (o->valtype == 0 || o->valtype == '-') {
if (arg) {
BIO_printf(bio_err,
"%s: Option -%s does not take a value\n", prog, p);
return -1;
}
return o->retval;
}
/* Want a value; get the next param if =foo not used. */
if (arg == NULL) {
if (argv[opt_index] == NULL) {
BIO_printf(bio_err,
"%s: Option -%s needs a value\n", prog, o->name);
return -1;
}
arg = argv[opt_index++];
}
/* Syntax-check value. */
switch (o->valtype) {
default:
case 's':
/* Just a string. */
break;
case '/':
if (app_isdir(arg) > 0)
break;
BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg);
return -1;
case '<':
/* Input file. */
break;
case '>':
/* Output file. */
break;
case 'p':
case 'n':
if (!opt_int(arg, &ival)
|| (o->valtype == 'p' && ival <= 0)) {
BIO_printf(bio_err,
"%s: Non-positive number \"%s\" for -%s\n",
prog, arg, o->name);
return -1;
}
break;
case 'M':
if (!opt_imax(arg, &imval)) {
BIO_printf(bio_err,
"%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
return -1;
}
break;
case 'U':
if (!opt_umax(arg, &umval)) {
BIO_printf(bio_err,
"%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
return -1;
}
break;
case 'l':
if (!opt_long(arg, &lval)) {
BIO_printf(bio_err,
"%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
return -1;
}
break;
case 'u':
if (!opt_ulong(arg, &ulval)) {
BIO_printf(bio_err,
"%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
return -1;
}
break;
case 'c':
case 'E':
case 'F':
case 'f':
if (opt_format(arg,
o->valtype == 'c' ? OPT_FMT_PDS :
o->valtype == 'E' ? OPT_FMT_PDE :
o->valtype == 'F' ? OPT_FMT_PEMDER
: OPT_FMT_ANY, &ival))
break;
BIO_printf(bio_err,
"%s: Invalid format \"%s\" for -%s\n",
prog, arg, o->name);
return -1;
}
/* Return the flag value. */
return o->retval;
}
if (unknown != NULL) {
dunno = p;
return unknown->retval;
}
BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p);
return -1;
}
/* Return the most recent flag parameter. */
char *opt_arg(void)
{
return arg;
}
/* Return the most recent flag. */
char *opt_flag(void)
{
return flag;
}
/* Return the unknown option. */
char *opt_unknown(void)
{
return dunno;
}
/* Return the rest of the arguments after parsing flags. */
char **opt_rest(void)
{
return &argv[opt_index];
}
/* How many items in remaining args? */
int opt_num_rest(void)
{
int i = 0;
char **pp;
for (pp = opt_rest(); *pp; pp++, i++)
continue;
return i;
}
/* Return a string describing the parameter type. */
static const char *valtype2param(const OPTIONS *o)
{
switch (o->valtype) {
case 0:
case '-':
return "";
case 's':
return "val";
case '/':
return "dir";
case '<':
return "infile";
case '>':
return "outfile";
case 'p':
return "+int";
case 'n':
return "int";
case 'l':
return "long";
case 'u':
return "ulong";
case 'E':
return "PEM|DER|ENGINE";
case 'F':
return "PEM|DER";
case 'f':
return "format";
case 'M':
return "intmax";
case 'U':
return "uintmax";
}
return "parm";
}
void opt_help(const OPTIONS *list)
{
const OPTIONS *o;
int i;
int standard_prolog;
int width = 5;
char start[80 + 1];
char *p;
const char *help;
/* Starts with its own help message? */
standard_prolog = list[0].name != OPT_HELP_STR;
/* Find the widest help. */
for (o = list; o->name; o++) {
if (o->name == OPT_MORE_STR)
continue;
i = 2 + (int)strlen(o->name);
if (o->valtype != '-')
i += 1 + strlen(valtype2param(o));
if (i < MAX_OPT_HELP_WIDTH && i > width)
width = i;
assert(i < (int)sizeof(start));
}
if (standard_prolog)
BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n",
prog);
/* Now let's print. */
for (o = list; o->name; o++) {
help = o->helpstr ? o->helpstr : "(No additional info)";
if (o->name == OPT_HELP_STR) {
BIO_printf(bio_err, help, prog);
continue;
}
/* Pad out prefix */
memset(start, ' ', sizeof(start) - 1);
start[sizeof(start) - 1] = '\0';
if (o->name == OPT_MORE_STR) {
/* Continuation of previous line; pad and print. */
start[width] = '\0';
BIO_printf(bio_err, "%s %s\n", start, help);
continue;
}
/* Build up the "-flag [param]" part. */
p = start;
*p++ = ' ';
*p++ = '-';
if (o->name[0])
p += strlen(strcpy(p, o->name));
else
*p++ = '*';
if (o->valtype != '-') {
*p++ = ' ';
p += strlen(strcpy(p, valtype2param(o)));
}
*p = ' ';
if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
*p = '\0';
BIO_printf(bio_err, "%s\n", start);
memset(start, ' ', sizeof(start));
}
start[width] = '\0';
BIO_printf(bio_err, "%s %s\n", start, help);
}
}
diff --git a/apps/rehash.c b/apps/rehash.c
index de7217cb1003..bb41d3129f9c 100644
--- a/apps/rehash.c
+++ b/apps/rehash.c
@@ -1,512 +1,512 @@
/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2013-2014 Timo Teräs <timo.teras@gmail.com>
+ * Copyright (c) 2013-2014 Timo Teräs <timo.teras@gmail.com>
*
* 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 "apps.h"
#include "progs.h"
#if defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) || \
(defined(__VMS) && defined(__DECC) && __CRTL_VER >= 80300000)
# include <unistd.h>
# include <stdio.h>
# include <limits.h>
# include <errno.h>
# include <string.h>
# include <ctype.h>
# include <sys/stat.h>
/*
* Make sure that the processing of symbol names is treated the same as when
* libcrypto is built. This is done automatically for public headers (see
* include/openssl/__DECC_INCLUDE_PROLOGUE.H and __DECC_INCLUDE_EPILOGUE.H),
* but not for internal headers.
*/
# ifdef __VMS
# pragma names save
# pragma names as_is,shortened
# endif
# include "internal/o_dir.h"
# ifdef __VMS
# pragma names restore
# endif
# include <openssl/evp.h>
# include <openssl/pem.h>
# include <openssl/x509.h>
# ifndef PATH_MAX
# define PATH_MAX 4096
# endif
# ifndef NAME_MAX
# define NAME_MAX 255
# endif
# define MAX_COLLISIONS 256
typedef struct hentry_st {
struct hentry_st *next;
char *filename;
unsigned short old_id;
unsigned char need_symlink;
unsigned char digest[EVP_MAX_MD_SIZE];
} HENTRY;
typedef struct bucket_st {
struct bucket_st *next;
HENTRY *first_entry, *last_entry;
unsigned int hash;
unsigned short type;
unsigned short num_needed;
} BUCKET;
enum Type {
/* Keep in sync with |suffixes|, below. */
TYPE_CERT=0, TYPE_CRL=1
};
enum Hash {
HASH_OLD, HASH_NEW, HASH_BOTH
};
static int evpmdsize;
static const EVP_MD *evpmd;
static int remove_links = 1;
static int verbose = 0;
static BUCKET *hash_table[257];
static const char *suffixes[] = { "", "r" };
static const char *extensions[] = { "pem", "crt", "cer", "crl" };
static void bit_set(unsigned char *set, unsigned int bit)
{
set[bit >> 3] |= 1 << (bit & 0x7);
}
static int bit_isset(unsigned char *set, unsigned int bit)
{
return set[bit >> 3] & (1 << (bit & 0x7));
}
/*
* Process an entry; return number of errors.
*/
static int add_entry(enum Type type, unsigned int hash, const char *filename,
const unsigned char *digest, int need_symlink,
unsigned short old_id)
{
static BUCKET nilbucket;
static HENTRY nilhentry;
BUCKET *bp;
HENTRY *ep, *found = NULL;
unsigned int ndx = (type + hash) % OSSL_NELEM(hash_table);
for (bp = hash_table[ndx]; bp; bp = bp->next)
if (bp->type == type && bp->hash == hash)
break;
if (bp == NULL) {
bp = app_malloc(sizeof(*bp), "hash bucket");
*bp = nilbucket;
bp->next = hash_table[ndx];
bp->type = type;
bp->hash = hash;
hash_table[ndx] = bp;
}
for (ep = bp->first_entry; ep; ep = ep->next) {
if (digest && memcmp(digest, ep->digest, evpmdsize) == 0) {
BIO_printf(bio_err,
"%s: warning: skipping duplicate %s in %s\n",
opt_getprog(),
type == TYPE_CERT ? "certificate" : "CRL", filename);
return 0;
}
if (strcmp(filename, ep->filename) == 0) {
found = ep;
if (digest == NULL)
break;
}
}
ep = found;
if (ep == NULL) {
if (bp->num_needed >= MAX_COLLISIONS) {
BIO_printf(bio_err,
"%s: error: hash table overflow for %s\n",
opt_getprog(), filename);
return 1;
}
ep = app_malloc(sizeof(*ep), "collision bucket");
*ep = nilhentry;
ep->old_id = ~0;
ep->filename = OPENSSL_strdup(filename);
if (bp->last_entry)
bp->last_entry->next = ep;
if (bp->first_entry == NULL)
bp->first_entry = ep;
bp->last_entry = ep;
}
if (old_id < ep->old_id)
ep->old_id = old_id;
if (need_symlink && !ep->need_symlink) {
ep->need_symlink = 1;
bp->num_needed++;
memcpy(ep->digest, digest, evpmdsize);
}
return 0;
}
/*
* Check if a symlink goes to the right spot; return 0 if okay.
* This can be -1 if bad filename, or an error count.
*/
static int handle_symlink(const char *filename, const char *fullpath)
{
unsigned int hash = 0;
int i, type, id;
unsigned char ch;
char linktarget[PATH_MAX], *endptr;
ossl_ssize_t n;
for (i = 0; i < 8; i++) {
ch = filename[i];
if (!isxdigit(ch))
return -1;
hash <<= 4;
hash += OPENSSL_hexchar2int(ch);
}
if (filename[i++] != '.')
return -1;
for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) {
const char *suffix = suffixes[type];
if (strncasecmp(suffix, &filename[i], strlen(suffix)) == 0)
break;
}
i += strlen(suffixes[type]);
id = strtoul(&filename[i], &endptr, 10);
if (*endptr != '\0')
return -1;
n = readlink(fullpath, linktarget, sizeof(linktarget));
if (n < 0 || n >= (int)sizeof(linktarget))
return -1;
linktarget[n] = 0;
return add_entry(type, hash, linktarget, NULL, 0, id);
}
/*
* process a file, return number of errors.
*/
static int do_file(const char *filename, const char *fullpath, enum Hash h)
{
STACK_OF (X509_INFO) *inf = NULL;
X509_INFO *x;
X509_NAME *name = NULL;
BIO *b;
const char *ext;
unsigned char digest[EVP_MAX_MD_SIZE];
int type, errs = 0;
size_t i;
/* Does it end with a recognized extension? */
if ((ext = strrchr(filename, '.')) == NULL)
goto end;
for (i = 0; i < OSSL_NELEM(extensions); i++) {
if (strcasecmp(extensions[i], ext + 1) == 0)
break;
}
if (i >= OSSL_NELEM(extensions))
goto end;
/* Does it have X.509 data in it? */
if ((b = BIO_new_file(fullpath, "r")) == NULL) {
BIO_printf(bio_err, "%s: error: skipping %s, cannot open file\n",
opt_getprog(), filename);
errs++;
goto end;
}
inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
BIO_free(b);
if (inf == NULL)
goto end;
if (sk_X509_INFO_num(inf) != 1) {
BIO_printf(bio_err,
"%s: warning: skipping %s,"
"it does not contain exactly one certificate or CRL\n",
opt_getprog(), filename);
/* This is not an error. */
goto end;
}
x = sk_X509_INFO_value(inf, 0);
if (x->x509 != NULL) {
type = TYPE_CERT;
name = X509_get_subject_name(x->x509);
X509_digest(x->x509, evpmd, digest, NULL);
} else if (x->crl != NULL) {
type = TYPE_CRL;
name = X509_CRL_get_issuer(x->crl);
X509_CRL_digest(x->crl, evpmd, digest, NULL);
} else {
++errs;
goto end;
}
if (name != NULL) {
if ((h == HASH_NEW) || (h == HASH_BOTH))
errs += add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0);
if ((h == HASH_OLD) || (h == HASH_BOTH))
errs += add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0);
}
end:
sk_X509_INFO_pop_free(inf, X509_INFO_free);
return errs;
}
static void str_free(char *s)
{
OPENSSL_free(s);
}
static int ends_with_dirsep(const char *path)
{
if (*path != '\0')
path += strlen(path) - 1;
# if defined __VMS
if (*path == ']' || *path == '>' || *path == ':')
return 1;
# elif defined _WIN32
if (*path == '\\')
return 1;
# endif
return *path == '/';
}
/*
* Process a directory; return number of errors found.
*/
static int do_dir(const char *dirname, enum Hash h)
{
BUCKET *bp, *nextbp;
HENTRY *ep, *nextep;
OPENSSL_DIR_CTX *d = NULL;
struct stat st;
unsigned char idmask[MAX_COLLISIONS / 8];
int n, numfiles, nextid, buflen, errs = 0;
size_t i;
const char *pathsep;
const char *filename;
char *buf, *copy = NULL;
STACK_OF(OPENSSL_STRING) *files = NULL;
if (app_access(dirname, W_OK) < 0) {
BIO_printf(bio_err, "Skipping %s, can't write\n", dirname);
return 1;
}
buflen = strlen(dirname);
pathsep = (buflen && !ends_with_dirsep(dirname)) ? "/": "";
buflen += NAME_MAX + 1 + 1;
buf = app_malloc(buflen, "filename buffer");
if (verbose)
BIO_printf(bio_out, "Doing %s\n", dirname);
if ((files = sk_OPENSSL_STRING_new_null()) == NULL) {
BIO_printf(bio_err, "Skipping %s, out of memory\n", dirname);
errs = 1;
goto err;
}
while ((filename = OPENSSL_DIR_read(&d, dirname)) != NULL) {
if ((copy = OPENSSL_strdup(filename)) == NULL
|| sk_OPENSSL_STRING_push(files, copy) == 0) {
OPENSSL_free(copy);
BIO_puts(bio_err, "out of memory\n");
errs = 1;
goto err;
}
}
OPENSSL_DIR_end(&d);
sk_OPENSSL_STRING_sort(files);
numfiles = sk_OPENSSL_STRING_num(files);
for (n = 0; n < numfiles; ++n) {
filename = sk_OPENSSL_STRING_value(files, n);
if (BIO_snprintf(buf, buflen, "%s%s%s",
dirname, pathsep, filename) >= buflen)
continue;
if (lstat(buf, &st) < 0)
continue;
if (S_ISLNK(st.st_mode) && handle_symlink(filename, buf) == 0)
continue;
errs += do_file(filename, buf, h);
}
for (i = 0; i < OSSL_NELEM(hash_table); i++) {
for (bp = hash_table[i]; bp; bp = nextbp) {
nextbp = bp->next;
nextid = 0;
memset(idmask, 0, (bp->num_needed + 7) / 8);
for (ep = bp->first_entry; ep; ep = ep->next)
if (ep->old_id < bp->num_needed)
bit_set(idmask, ep->old_id);
for (ep = bp->first_entry; ep; ep = nextep) {
nextep = ep->next;
if (ep->old_id < bp->num_needed) {
/* Link exists, and is used as-is */
BIO_snprintf(buf, buflen, "%08x.%s%d", bp->hash,
suffixes[bp->type], ep->old_id);
if (verbose)
BIO_printf(bio_out, "link %s -> %s\n",
ep->filename, buf);
} else if (ep->need_symlink) {
/* New link needed (it may replace something) */
while (bit_isset(idmask, nextid))
nextid++;
BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d",
dirname, pathsep, &n, bp->hash,
suffixes[bp->type], nextid);
if (verbose)
BIO_printf(bio_out, "link %s -> %s\n",
ep->filename, &buf[n]);
if (unlink(buf) < 0 && errno != ENOENT) {
BIO_printf(bio_err,
"%s: Can't unlink %s, %s\n",
opt_getprog(), buf, strerror(errno));
errs++;
}
if (symlink(ep->filename, buf) < 0) {
BIO_printf(bio_err,
"%s: Can't symlink %s, %s\n",
opt_getprog(), ep->filename,
strerror(errno));
errs++;
}
bit_set(idmask, nextid);
} else if (remove_links) {
/* Link to be deleted */
BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d",
dirname, pathsep, &n, bp->hash,
suffixes[bp->type], ep->old_id);
if (verbose)
BIO_printf(bio_out, "unlink %s\n",
&buf[n]);
if (unlink(buf) < 0 && errno != ENOENT) {
BIO_printf(bio_err,
"%s: Can't unlink %s, %s\n",
opt_getprog(), buf, strerror(errno));
errs++;
}
}
OPENSSL_free(ep->filename);
OPENSSL_free(ep);
}
OPENSSL_free(bp);
}
hash_table[i] = NULL;
}
err:
sk_OPENSSL_STRING_pop_free(files, str_free);
OPENSSL_free(buf);
return errs;
}
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE
} OPTION_CHOICE;
const OPTIONS rehash_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert-directory...]\n"},
{OPT_HELP_STR, 1, '-', "Valid options are:\n"},
{"help", OPT_HELP, '-', "Display this summary"},
{"h", OPT_HELP, '-', "Display this summary"},
{"compat", OPT_COMPAT, '-', "Create both new- and old-style hash links"},
{"old", OPT_OLD, '-', "Use old-style hash to generate links"},
{"n", OPT_N, '-', "Do not remove existing links"},
{"v", OPT_VERBOSE, '-', "Verbose output"},
{NULL}
};
int rehash_main(int argc, char **argv)
{
const char *env, *prog;
char *e, *m;
int errs = 0;
OPTION_CHOICE o;
enum Hash h = HASH_NEW;
prog = opt_init(argc, argv, rehash_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(rehash_options);
goto end;
case OPT_COMPAT:
h = HASH_BOTH;
break;
case OPT_OLD:
h = HASH_OLD;
break;
case OPT_N:
remove_links = 0;
break;
case OPT_VERBOSE:
verbose = 1;
break;
}
}
argc = opt_num_rest();
argv = opt_rest();
evpmd = EVP_sha1();
evpmdsize = EVP_MD_size(evpmd);
if (*argv != NULL) {
while (*argv != NULL)
errs += do_dir(*argv++, h);
} else if ((env = getenv(X509_get_default_cert_dir_env())) != NULL) {
char lsc[2] = { LIST_SEPARATOR_CHAR, '\0' };
m = OPENSSL_strdup(env);
for (e = strtok(m, lsc); e != NULL; e = strtok(NULL, lsc))
errs += do_dir(e, h);
OPENSSL_free(m);
} else {
errs += do_dir(X509_get_default_cert_dir(), h);
}
end:
return errs;
}
#else
const OPTIONS rehash_options[] = {
{NULL}
};
int rehash_main(int argc, char **argv)
{
BIO_printf(bio_err, "Not available; use c_rehash script\n");
return 1;
}
#endif /* defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) */
diff --git a/apps/rsa.c b/apps/rsa.c
index 6458b3d9c5aa..fdd02dce3241 100644
--- a/apps/rsa.c
+++ b/apps/rsa.c
@@ -1,313 +1,316 @@
/*
* Copyright 1995-2018 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_RSA
NON_EMPTY_TRANSLATION_UNIT
#else
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
# include "apps.h"
# include "progs.h"
# include <openssl/bio.h>
# include <openssl/err.h>
# include <openssl/rsa.h>
# include <openssl/evp.h>
# include <openssl/x509.h>
# include <openssl/pem.h>
# include <openssl/bn.h>
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN,
OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT,
/* Do not change the order here; see case statements below */
OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER
} OPTION_CHOICE;
const OPTIONS rsa_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'f', "Input format, one of DER NET PEM"},
- {"outform", OPT_OUTFORM, 'f', "Output format, one of DER NET PEM PVK"},
+ {"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"},
+ {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"},
{"in", OPT_IN, 's', "Input file"},
{"out", OPT_OUT, '>', "Output file"},
{"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
{"pubout", OPT_PUBOUT, '-', "Output a public key"},
{"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"},
{"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"},
{"noout", OPT_NOOUT, '-', "Don't print key out"},
{"text", OPT_TEXT, '-', "Print the key in text"},
{"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
{"check", OPT_CHECK, '-', "Verify key consistency"},
{"", OPT_CIPHER, '-', "Any supported cipher"},
# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
{"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"},
{"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"},
{"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"},
# endif
# ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
# endif
{NULL}
};
int rsa_main(int argc, char **argv)
{
ENGINE *e = NULL;
BIO *out = NULL;
RSA *rsa = NULL;
const EVP_CIPHER *enc = NULL;
char *infile = NULL, *outfile = NULL, *prog;
char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
int i, private = 0;
int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0;
int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1;
# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
int pvk_encr = 2;
# endif
OPTION_CHOICE o;
prog = opt_init(argc, argv, rsa_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(rsa_options);
ret = 0;
goto end;
case OPT_INFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
goto opthelp;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUTFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
goto opthelp;
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_PASSOUT:
passoutarg = opt_arg();
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_PUBIN:
pubin = 1;
break;
case OPT_PUBOUT:
pubout = 1;
break;
case OPT_RSAPUBKEY_IN:
pubin = 2;
break;
case OPT_RSAPUBKEY_OUT:
pubout = 2;
break;
case OPT_PVK_STRONG: /* pvk_encr:= 2 */
case OPT_PVK_WEAK: /* pvk_encr:= 1 */
case OPT_PVK_NONE: /* pvk_encr:= 0 */
# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
pvk_encr = (o - OPT_PVK_NONE);
# endif
break;
case OPT_NOOUT:
noout = 1;
break;
case OPT_TEXT:
text = 1;
break;
case OPT_MODULUS:
modulus = 1;
break;
case OPT_CHECK:
check = 1;
break;
case OPT_CIPHER:
if (!opt_cipher(opt_unknown(), &enc))
goto opthelp;
break;
}
}
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
private = (text && !pubin) || (!pubout && !noout) ? 1 : 0;
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
goto end;
}
if (check && pubin) {
BIO_printf(bio_err, "Only private keys can be checked\n");
goto end;
}
{
EVP_PKEY *pkey;
if (pubin) {
int tmpformat = -1;
if (pubin == 2) {
if (informat == FORMAT_PEM)
tmpformat = FORMAT_PEMRSA;
else if (informat == FORMAT_ASN1)
tmpformat = FORMAT_ASN1RSA;
} else {
tmpformat = informat;
}
pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key");
} else {
pkey = load_key(infile, informat, 1, passin, e, "Private Key");
}
if (pkey != NULL)
rsa = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
}
if (rsa == NULL) {
ERR_print_errors(bio_err);
goto end;
}
out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
goto end;
if (text) {
assert(pubin || private);
if (!RSA_print(out, rsa, 0)) {
perror(outfile);
ERR_print_errors(bio_err);
goto end;
}
}
if (modulus) {
const BIGNUM *n;
RSA_get0_key(rsa, &n, NULL, NULL);
BIO_printf(out, "Modulus=");
BN_print(out, n);
BIO_printf(out, "\n");
}
if (check) {
int r = RSA_check_key_ex(rsa, NULL);
if (r == 1) {
BIO_printf(out, "RSA key ok\n");
} else if (r == 0) {
unsigned long err;
while ((err = ERR_peek_error()) != 0 &&
ERR_GET_LIB(err) == ERR_LIB_RSA &&
ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY_EX &&
ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) {
BIO_printf(out, "RSA key error: %s\n",
ERR_reason_error_string(err));
ERR_get_error(); /* remove err from error stack */
}
} else if (r == -1) {
ERR_print_errors(bio_err);
goto end;
}
}
if (noout) {
ret = 0;
goto end;
}
BIO_printf(bio_err, "writing RSA key\n");
if (outformat == FORMAT_ASN1) {
if (pubout || pubin) {
if (pubout == 2)
i = i2d_RSAPublicKey_bio(out, rsa);
else
i = i2d_RSA_PUBKEY_bio(out, rsa);
} else {
assert(private);
i = i2d_RSAPrivateKey_bio(out, rsa);
}
} else if (outformat == FORMAT_PEM) {
if (pubout || pubin) {
if (pubout == 2)
i = PEM_write_bio_RSAPublicKey(out, rsa);
else
i = PEM_write_bio_RSA_PUBKEY(out, rsa);
} else {
assert(private);
i = PEM_write_bio_RSAPrivateKey(out, rsa,
enc, NULL, 0, NULL, passout);
}
# ifndef OPENSSL_NO_DSA
} else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
EVP_PKEY *pk;
pk = EVP_PKEY_new();
+ if (pk == NULL)
+ goto end;
+
EVP_PKEY_set1_RSA(pk, rsa);
if (outformat == FORMAT_PVK) {
if (pubin) {
BIO_printf(bio_err, "PVK form impossible with public key input\n");
EVP_PKEY_free(pk);
goto end;
}
assert(private);
# ifdef OPENSSL_NO_RC4
BIO_printf(bio_err, "PVK format not supported\n");
EVP_PKEY_free(pk);
goto end;
# else
i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
# endif
} else if (pubin || pubout) {
i = i2b_PublicKey_bio(out, pk);
} else {
assert(private);
i = i2b_PrivateKey_bio(out, pk);
}
EVP_PKEY_free(pk);
# endif
} else {
BIO_printf(bio_err, "bad output format specified for outfile\n");
goto end;
}
if (i <= 0) {
BIO_printf(bio_err, "unable to write key\n");
ERR_print_errors(bio_err);
} else {
ret = 0;
}
end:
release_engine(e);
BIO_free_all(out);
RSA_free(rsa);
OPENSSL_free(passin);
OPENSSL_free(passout);
return ret;
}
#endif
diff --git a/apps/s_cb.c b/apps/s_cb.c
index 46b386428461..2d4568f40ccb 100644
--- a/apps/s_cb.c
+++ b/apps/s_cb.c
@@ -1,1480 +1,1481 @@
/*
* Copyright 1995-2018 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 = { 0, 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 >= 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_server_tmp_key(s, &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}
};
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},
{"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;
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);
switch (op) {
case SSL_SECOP_TICKET:
case SSL_SECOP_COMPRESSION:
show_bits = 0;
nm = NULL;
break;
case SSL_SECOP_VERSION:
BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???"));
show_bits = 0;
nm = NULL;
break;
case SSL_SECOP_CA_MD:
case SSL_SECOP_PEER_CA_MD:
cert_md = 1;
break;
}
if (nm != NULL)
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;
}
BIO_puts(sdb->out, OBJ_nid2sn(nid));
if (sname)
BIO_printf(sdb->out, ", algorithm=%s", sname);
else
BIO_printf(sdb->out, ", algid=%d", salg[1]);
break;
}
}
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_server.c b/apps/s_server.c
index e3bb1a672d01..ac7dca607ba4 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -1,3611 +1,3615 @@
/*
* Copyright 1995-2018 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 <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
/* Included before async.h to avoid some warnings */
# include <windows.h>
#endif
#include <openssl/e_os2.h>
#include <openssl/async.h>
#include <openssl/ssl.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 <openssl/bn.h>
#include "apps.h"
#include "progs.h"
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include <openssl/ocsp.h>
#ifndef OPENSSL_NO_DH
# include <openssl/dh.h>
#endif
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_SRP
# include <openssl/srp.h>
#endif
#include "s_apps.h"
#include "timeouts.h"
#ifdef CHARSET_EBCDIC
#include <openssl/ebcdic.h>
#endif
#include "internal/sockets.h"
static int not_resumable_sess_cb(SSL *s, int is_forward_secure);
static int sv_body(int s, int stype, int prot, unsigned char *context);
static int www_body(int s, int stype, int prot, unsigned char *context);
static int rev_body(int s, int stype, int prot, unsigned char *context);
static void close_accept_socket(void);
static int init_ssl_connection(SSL *s);
static void print_stats(BIO *bp, SSL_CTX *ctx);
static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len);
static void init_session_cache_ctx(SSL_CTX *sctx);
static void free_sessions(void);
#ifndef OPENSSL_NO_DH
static DH *load_dh_param(const char *dhfile);
#endif
static void print_connection_info(SSL *con);
static const int bufsize = 16 * 1024;
static int accept_socket = -1;
#define TEST_CERT "server.pem"
#define TEST_CERT2 "server2.pem"
static int s_nbio = 0;
static int s_nbio_test = 0;
static int s_crlf = 0;
static SSL_CTX *ctx = NULL;
static SSL_CTX *ctx2 = NULL;
static int www = 0;
static BIO *bio_s_out = NULL;
static BIO *bio_s_msg = NULL;
static int s_debug = 0;
static int s_tlsextdebug = 0;
static int s_msg = 0;
static int s_quiet = 0;
static int s_ign_eof = 0;
static int s_brief = 0;
static char *keymatexportlabel = NULL;
static int keymatexportlen = 20;
static int async = 0;
static const char *session_id_prefix = NULL;
#ifndef OPENSSL_NO_DTLS
static int enable_timeouts = 0;
static long socket_mtu;
#endif
/*
* We define this but make it always be 0 in no-dtls builds to simplify the
* code.
*/
static int dtlslisten = 0;
static int stateless = 0;
static int early_data = 0;
static SSL_SESSION *psksess = NULL;
static char *psk_identity = "Client_identity";
char *psk_key = NULL; /* by default PSK is not used */
#ifndef OPENSSL_NO_PSK
static unsigned int psk_server_cb(SSL *ssl, const char *identity,
unsigned char *psk,
unsigned int max_psk_len)
{
long key_len = 0;
unsigned char *key;
if (s_debug)
BIO_printf(bio_s_out, "psk_server_cb\n");
if (identity == NULL) {
BIO_printf(bio_err, "Error: client did not send PSK identity\n");
goto out_err;
}
if (s_debug)
BIO_printf(bio_s_out, "identity_len=%d identity=%s\n",
(int)strlen(identity), identity);
/* here we could lookup the given identity e.g. from a database */
if (strcmp(identity, psk_identity) != 0) {
BIO_printf(bio_s_out, "PSK warning: client identity not what we expected"
" (got '%s' expected '%s')\n", identity, psk_identity);
} else {
if (s_debug)
BIO_printf(bio_s_out, "PSK client identity found\n");
}
/* 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 (key_len > (int)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 (s_debug)
BIO_printf(bio_s_out, "fetched PSK len=%ld\n", key_len);
return key_len;
out_err:
if (s_debug)
BIO_printf(bio_err, "Error in PSK server callback\n");
(void)BIO_flush(bio_err);
(void)BIO_flush(bio_s_out);
return 0;
}
#endif
#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01")
#define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02")
static int psk_find_session_cb(SSL *ssl, const unsigned char *identity,
size_t identity_len, SSL_SESSION **sess)
{
SSL_SESSION *tmpsess = NULL;
unsigned char *key;
long key_len;
const SSL_CIPHER *cipher = NULL;
if (strlen(psk_identity) != identity_len
|| memcmp(psk_identity, identity, identity_len) != 0) {
- BIO_printf(bio_s_out,
- "PSK warning: client identity not what we expected"
- " (got '%s' expected '%s')\n", identity, psk_identity);
+ *sess = NULL;
+ return 1;
}
if (psksess != NULL) {
SSL_SESSION_up_ref(psksess);
*sess = psksess;
return 1;
}
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 SHA256 */
cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id);
if (cipher == NULL) {
BIO_printf(bio_err, "Error finding suitable ciphersuite\n");
OPENSSL_free(key);
return 0;
}
tmpsess = SSL_SESSION_new();
if (tmpsess == NULL
|| !SSL_SESSION_set1_master_key(tmpsess, key, key_len)
|| !SSL_SESSION_set_cipher(tmpsess, cipher)
|| !SSL_SESSION_set_protocol_version(tmpsess, SSL_version(ssl))) {
OPENSSL_free(key);
return 0;
}
OPENSSL_free(key);
*sess = tmpsess;
return 1;
}
#ifndef OPENSSL_NO_SRP
/* This is a context that we pass to callbacks */
typedef struct srpsrvparm_st {
char *login;
SRP_VBASE *vb;
SRP_user_pwd *user;
} srpsrvparm;
static srpsrvparm srp_callback_parm;
/*
* This callback pretends to require some asynchronous logic in order to
* obtain a verifier. When the callback is called for a new connection we
* return with a negative value. This will provoke the accept etc to return
* with an LOOKUP_X509. The main logic of the reinvokes the suspended call
* (which would normally occur after a worker has finished) and we set the
* user parameters.
*/
static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
{
srpsrvparm *p = (srpsrvparm *) arg;
int ret = SSL3_AL_FATAL;
if (p->login == NULL && p->user == NULL) {
p->login = SSL_get_srp_username(s);
BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
return -1;
}
if (p->user == NULL) {
BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
goto err;
}
if (SSL_set_srp_server_param
(s, p->user->N, p->user->g, p->user->s, p->user->v,
p->user->info) < 0) {
*ad = SSL_AD_INTERNAL_ERROR;
goto err;
}
BIO_printf(bio_err,
"SRP parameters set: username = \"%s\" info=\"%s\" \n",
p->login, p->user->info);
ret = SSL_ERROR_NONE;
err:
SRP_user_pwd_free(p->user);
p->user = NULL;
p->login = NULL;
return ret;
}
#endif
static int local_argc = 0;
static char **local_argv;
#ifdef CHARSET_EBCDIC
static int ebcdic_new(BIO *bi);
static int ebcdic_free(BIO *a);
static int ebcdic_read(BIO *b, char *out, int outl);
static int ebcdic_write(BIO *b, const char *in, int inl);
static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr);
static int ebcdic_gets(BIO *bp, char *buf, int size);
static int ebcdic_puts(BIO *bp, const char *str);
# define BIO_TYPE_EBCDIC_FILTER (18|0x0200)
static BIO_METHOD *methods_ebcdic = NULL;
/* This struct is "unwarranted chumminess with the compiler." */
typedef struct {
size_t alloced;
char buff[1];
} EBCDIC_OUTBUFF;
static const BIO_METHOD *BIO_f_ebcdic_filter()
{
if (methods_ebcdic == NULL) {
methods_ebcdic = BIO_meth_new(BIO_TYPE_EBCDIC_FILTER,
"EBCDIC/ASCII filter");
if (methods_ebcdic == NULL
|| !BIO_meth_set_write(methods_ebcdic, ebcdic_write)
|| !BIO_meth_set_read(methods_ebcdic, ebcdic_read)
|| !BIO_meth_set_puts(methods_ebcdic, ebcdic_puts)
|| !BIO_meth_set_gets(methods_ebcdic, ebcdic_gets)
|| !BIO_meth_set_ctrl(methods_ebcdic, ebcdic_ctrl)
|| !BIO_meth_set_create(methods_ebcdic, ebcdic_new)
|| !BIO_meth_set_destroy(methods_ebcdic, ebcdic_free))
return NULL;
}
return methods_ebcdic;
}
static int ebcdic_new(BIO *bi)
{
EBCDIC_OUTBUFF *wbuf;
wbuf = app_malloc(sizeof(*wbuf) + 1024, "ebcdic wbuf");
wbuf->alloced = 1024;
wbuf->buff[0] = '\0';
BIO_set_data(bi, wbuf);
BIO_set_init(bi, 1);
return 1;
}
static int ebcdic_free(BIO *a)
{
EBCDIC_OUTBUFF *wbuf;
if (a == NULL)
return 0;
wbuf = BIO_get_data(a);
OPENSSL_free(wbuf);
BIO_set_data(a, NULL);
BIO_set_init(a, 0);
return 1;
}
static int ebcdic_read(BIO *b, char *out, int outl)
{
int ret = 0;
BIO *next = BIO_next(b);
if (out == NULL || outl == 0)
return 0;
if (next == NULL)
return 0;
ret = BIO_read(next, out, outl);
if (ret > 0)
ascii2ebcdic(out, out, ret);
return ret;
}
static int ebcdic_write(BIO *b, const char *in, int inl)
{
EBCDIC_OUTBUFF *wbuf;
BIO *next = BIO_next(b);
int ret = 0;
int num;
if ((in == NULL) || (inl <= 0))
return 0;
if (next == NULL)
return 0;
wbuf = (EBCDIC_OUTBUFF *) BIO_get_data(b);
if (inl > (num = wbuf->alloced)) {
num = num + num; /* double the size */
if (num < inl)
num = inl;
OPENSSL_free(wbuf);
wbuf = app_malloc(sizeof(*wbuf) + num, "grow ebcdic wbuf");
wbuf->alloced = num;
wbuf->buff[0] = '\0';
BIO_set_data(b, wbuf);
}
ebcdic2ascii(wbuf->buff, in, inl);
ret = BIO_write(next, wbuf->buff, inl);
return ret;
}
static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret;
BIO *next = BIO_next(b);
if (next == NULL)
return 0;
switch (cmd) {
case BIO_CTRL_DUP:
ret = 0L;
break;
default:
ret = BIO_ctrl(next, cmd, num, ptr);
break;
}
return ret;
}
static int ebcdic_gets(BIO *bp, char *buf, int size)
{
int i, ret = 0;
BIO *next = BIO_next(bp);
if (next == NULL)
return 0;
/* return(BIO_gets(bp->next_bio,buf,size));*/
for (i = 0; i < size - 1; ++i) {
ret = ebcdic_read(bp, &buf[i], 1);
if (ret <= 0)
break;
else if (buf[i] == '\n') {
++i;
break;
}
}
if (i < size)
buf[i] = '\0';
return (ret < 0 && i == 0) ? ret : i;
}
static int ebcdic_puts(BIO *bp, const char *str)
{
if (BIO_next(bp) == NULL)
return 0;
return ebcdic_write(bp, str, strlen(str));
}
#endif
/* This is a context that we pass to callbacks */
typedef struct tlsextctx_st {
char *servername;
BIO *biodebug;
int extension_error;
} tlsextctx;
static int ssl_servername_cb(SSL *s, int *ad, void *arg)
{
tlsextctx *p = (tlsextctx *) arg;
const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
if (servername != NULL && p->biodebug != NULL) {
const char *cp = servername;
unsigned char uc;
BIO_printf(p->biodebug, "Hostname in TLS extension: \"");
while ((uc = *cp++) != 0)
BIO_printf(p->biodebug,
isascii(uc) && isprint(uc) ? "%c" : "\\x%02x", uc);
BIO_printf(p->biodebug, "\"\n");
}
if (p->servername == NULL)
return SSL_TLSEXT_ERR_NOACK;
if (servername != NULL) {
if (strcasecmp(servername, p->servername))
return p->extension_error;
if (ctx2 != NULL) {
BIO_printf(p->biodebug, "Switching server context.\n");
SSL_set_SSL_CTX(s, ctx2);
}
}
return SSL_TLSEXT_ERR_OK;
}
/* Structure passed to cert status callback */
typedef struct tlsextstatusctx_st {
int timeout;
/* File to load OCSP Response from (or NULL if no file) */
char *respin;
/* Default responder to use */
char *host, *path, *port;
int use_ssl;
int verbose;
} tlsextstatusctx;
static tlsextstatusctx tlscstatp = { -1 };
#ifndef OPENSSL_NO_OCSP
/*
* Helper function to get an OCSP_RESPONSE from a responder. This is a
* simplified version. It examines certificates each time and makes one OCSP
* responder query for each request. A full version would store details such as
* the OCSP certificate IDs and minimise the number of OCSP responses by caching
* them until they were considered "expired".
*/
static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
OCSP_RESPONSE **resp)
{
char *host = NULL, *port = NULL, *path = NULL;
int use_ssl;
STACK_OF(OPENSSL_STRING) *aia = NULL;
X509 *x = NULL;
X509_STORE_CTX *inctx = NULL;
X509_OBJECT *obj;
OCSP_REQUEST *req = NULL;
OCSP_CERTID *id = NULL;
STACK_OF(X509_EXTENSION) *exts;
int ret = SSL_TLSEXT_ERR_NOACK;
int i;
/* Build up OCSP query from server certificate */
x = SSL_get_certificate(s);
aia = X509_get1_ocsp(x);
if (aia != NULL) {
if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
&host, &port, &path, &use_ssl)) {
BIO_puts(bio_err, "cert_status: can't parse AIA URL\n");
goto err;
}
if (srctx->verbose)
BIO_printf(bio_err, "cert_status: AIA URL: %s\n",
sk_OPENSSL_STRING_value(aia, 0));
} else {
if (srctx->host == NULL) {
BIO_puts(bio_err,
"cert_status: no AIA and no default responder URL\n");
goto done;
}
host = srctx->host;
path = srctx->path;
port = srctx->port;
use_ssl = srctx->use_ssl;
}
inctx = X509_STORE_CTX_new();
if (inctx == NULL)
goto err;
if (!X509_STORE_CTX_init(inctx,
SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
NULL, NULL))
goto err;
obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509,
X509_get_issuer_name(x));
if (obj == NULL) {
BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n");
goto done;
}
id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj));
X509_OBJECT_free(obj);
if (id == NULL)
goto err;
req = OCSP_REQUEST_new();
if (req == NULL)
goto err;
if (!OCSP_request_add0_id(req, id))
goto err;
id = NULL;
/* Add any extensions to the request */
SSL_get_tlsext_status_exts(s, &exts);
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
if (!OCSP_REQUEST_add_ext(req, ext, -1))
goto err;
}
*resp = process_responder(req, host, path, port, use_ssl, NULL,
srctx->timeout);
if (*resp == NULL) {
BIO_puts(bio_err, "cert_status: error querying responder\n");
goto done;
}
ret = SSL_TLSEXT_ERR_OK;
goto done;
err:
ret = SSL_TLSEXT_ERR_ALERT_FATAL;
done:
/*
* If we parsed aia we need to free; otherwise they were copied and we
* don't
*/
if (aia != NULL) {
OPENSSL_free(host);
OPENSSL_free(path);
OPENSSL_free(port);
X509_email_free(aia);
}
OCSP_CERTID_free(id);
OCSP_REQUEST_free(req);
X509_STORE_CTX_free(inctx);
return ret;
}
/*
* Certificate Status callback. This is called when a client includes a
* certificate status request extension. The response is either obtained from a
* file, or from an OCSP responder.
*/
static int cert_status_cb(SSL *s, void *arg)
{
tlsextstatusctx *srctx = arg;
OCSP_RESPONSE *resp = NULL;
unsigned char *rspder = NULL;
int rspderlen;
int ret = SSL_TLSEXT_ERR_ALERT_FATAL;
if (srctx->verbose)
BIO_puts(bio_err, "cert_status: callback called\n");
if (srctx->respin != NULL) {
BIO *derbio = bio_open_default(srctx->respin, 'r', FORMAT_ASN1);
if (derbio == NULL) {
BIO_puts(bio_err, "cert_status: Cannot open OCSP response file\n");
goto err;
}
resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
BIO_free(derbio);
if (resp == NULL) {
BIO_puts(bio_err, "cert_status: Error reading OCSP response\n");
goto err;
}
} else {
ret = get_ocsp_resp_from_responder(s, srctx, &resp);
if (ret != SSL_TLSEXT_ERR_OK)
goto err;
}
rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
if (rspderlen <= 0)
goto err;
SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
if (srctx->verbose) {
BIO_puts(bio_err, "cert_status: ocsp response sent:\n");
OCSP_RESPONSE_print(bio_err, resp, 2);
}
ret = SSL_TLSEXT_ERR_OK;
err:
if (ret != SSL_TLSEXT_ERR_OK)
ERR_print_errors(bio_err);
OCSP_RESPONSE_free(resp);
return ret;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
/* This is the context that we pass to next_proto_cb */
typedef struct tlsextnextprotoctx_st {
unsigned char *data;
size_t len;
} tlsextnextprotoctx;
static int next_proto_cb(SSL *s, const unsigned char **data,
unsigned int *len, void *arg)
{
tlsextnextprotoctx *next_proto = arg;
*data = next_proto->data;
*len = next_proto->len;
return SSL_TLSEXT_ERR_OK;
}
#endif /* ndef OPENSSL_NO_NEXTPROTONEG */
/* This the context that we pass to alpn_cb */
typedef struct tlsextalpnctx_st {
unsigned char *data;
size_t len;
} tlsextalpnctx;
static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg)
{
tlsextalpnctx *alpn_ctx = arg;
if (!s_quiet) {
/* We can assume that |in| is syntactically valid. */
unsigned int i;
BIO_printf(bio_s_out, "ALPN protocols advertised by the client: ");
for (i = 0; i < inlen;) {
if (i)
BIO_write(bio_s_out, ", ", 2);
BIO_write(bio_s_out, &in[i + 1], in[i]);
i += in[i] + 1;
}
BIO_write(bio_s_out, "\n", 1);
}
if (SSL_select_next_proto
((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in,
inlen) != OPENSSL_NPN_NEGOTIATED) {
return SSL_TLSEXT_ERR_NOACK;
}
if (!s_quiet) {
BIO_printf(bio_s_out, "ALPN protocols selected: ");
BIO_write(bio_s_out, *out, *outlen);
BIO_write(bio_s_out, "\n", 1);
}
return SSL_TLSEXT_ERR_OK;
}
static int not_resumable_sess_cb(SSL *s, int is_forward_secure)
{
/* disable resumption for sessions with forward secure ciphers */
return is_forward_secure;
}
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE,
OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT,
OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL,
OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM,
OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT,
OPT_DKEYFORM, OPT_DPASS, OPT_DKEY, OPT_DCERT_CHAIN, OPT_NOCERT,
OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE,
OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE,
OPT_VERIFYCAFILE, OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF,
OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE,
OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE,
OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE,
OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE,
OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK,
OPT_PSK_SESS, OPT_SRPVFILE, OPT_SRPUSERSEED, OPT_REV, OPT_WWW,
OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC, OPT_SSL_CONFIG,
OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
OPT_SSL3, 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_LISTEN, OPT_STATELESS,
OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY,
OPT_R_ENUM,
OPT_S_ENUM,
OPT_V_ENUM,
OPT_X_ENUM
} OPTION_CHOICE;
const OPTIONS s_server_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"port", OPT_PORT, 'p',
"TCP/IP port to listen on for connections (default is " PORT ")"},
{"accept", OPT_ACCEPT, 's',
"TCP/IP optional host and port to listen on for connections (default is *:" PORT ")"},
#ifdef AF_UNIX
{"unix", OPT_UNIX, 's', "Unix domain socket to accept on"},
#endif
{"4", OPT_4, '-', "Use IPv4 only"},
{"6", OPT_6, '-', "Use IPv6 only"},
#ifdef AF_UNIX
{"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"},
#endif
{"context", OPT_CONTEXT, 's', "Set session ID context"},
{"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"},
{"Verify", OPT_UPPER_V_VERIFY, 'n',
"Turn on peer certificate verification, must have a cert"},
{"cert", OPT_CERT, '<', "Certificate file to use; default is " TEST_CERT},
{"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
{"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"},
{"serverinfo", OPT_SERVERINFO, 's',
"PEM serverinfo file for certificate"},
{"certform", OPT_CERTFORM, 'F',
"Certificate format (PEM or DER) PEM default"},
{"key", OPT_KEY, 's',
"Private Key if not in -cert; default is " TEST_CERT},
{"keyform", OPT_KEYFORM, 'f',
"Key format (PEM, DER or ENGINE) PEM default"},
{"pass", OPT_PASS, 's', "Private key file pass phrase source"},
{"dcert", OPT_DCERT, '<',
"Second certificate file to use (usually for DSA)"},
{"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
{"dcertform", OPT_DCERTFORM, 'F',
"Second certificate format (PEM or DER) PEM default"},
{"dkey", OPT_DKEY, '<',
"Second private key file to use (usually for DSA)"},
{"dkeyform", OPT_DKEYFORM, 'F',
"Second key format (PEM, DER or ENGINE) PEM default"},
{"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"},
{"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"},
{"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
{"debug", OPT_DEBUG, '-', "Print more output"},
{"msg", OPT_MSG, '-', "Show protocol messages"},
{"msgfile", OPT_MSGFILE, '>',
"File to send output of -msg or -trace, instead of stdout"},
{"state", OPT_STATE, '-', "Print the SSL states"},
{"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
{"CApath", OPT_CAPATH, '/', "PEM format directory 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"},
{"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"},
{"quiet", OPT_QUIET, '-', "No server output"},
{"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-',
"Disable caching and tickets if ephemeral (EC)DH is used"},
{"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
{"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"},
{"servername", OPT_SERVERNAME, 's',
"Servername for HostName TLS extension"},
{"servername_fatal", OPT_SERVERNAME_FATAL, '-',
"mismatch send fatal alert (default warning alert)"},
{"cert2", OPT_CERT2, '<',
"Certificate file to use for servername; default is" TEST_CERT2},
{"key2", OPT_KEY2, '<',
"-Private Key file to use for servername if not in -cert2"},
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
"Hex dump of all TLS extensions received"},
{"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"},
{"id_prefix", OPT_ID_PREFIX, 's',
"Generate SSL/TLS session IDs prefixed by arg"},
OPT_R_OPTIONS,
{"keymatexport", OPT_KEYMATEXPORT, 's',
"Export keying material using label"},
{"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
"Export len bytes of keying material (default 20)"},
{"CRL", OPT_CRL, '<', "CRL file to use"},
{"crl_download", OPT_CRL_DOWNLOAD, '-',
"Download CRL from distribution points"},
{"cert_chain", OPT_CERT_CHAIN, '<',
"certificate chain file in PEM format"},
{"dcert_chain", OPT_DCERT_CHAIN, '<',
"second 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"},
{"no_cache", OPT_NO_CACHE, '-', "Disable session cache"},
{"ext_cache", OPT_EXT_CACHE, '-',
"Disable internal cache, setup and use external cache"},
{"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, '-',
"No verify output except verify errors"},
{"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)"},
{"ign_eof", OPT_IGN_EOF, '-', "ignore input eof (default when -quiet)"},
{"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input eof"},
#ifndef OPENSSL_NO_OCSP
{"status", OPT_STATUS, '-', "Request certificate status from server"},
{"status_verbose", OPT_STATUS_VERBOSE, '-',
"Print more output in certificate status callback"},
{"status_timeout", OPT_STATUS_TIMEOUT, 'n',
"Status request responder timeout"},
{"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"},
{"status_file", OPT_STATUS_FILE, '<',
"File containing DER encoded OCSP Response"},
#endif
#ifndef OPENSSL_NO_SSL_TRACE
{"trace", OPT_TRACE, '-', "trace protocol messages"},
#endif
{"security_debug", OPT_SECURITY_DEBUG, '-',
"Print output from SSL/TLS security framework"},
{"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
"Print more output from SSL/TLS security framework"},
{"brief", OPT_BRIEF, '-',
"Restrict output to brief summary of connection parameters"},
{"rev", OPT_REV, '-',
"act as a simple test server which just sends back with the received text reversed"},
{"async", OPT_ASYNC, '-', "Operate in asynchronous mode"},
{"ssl_config", OPT_SSL_CONFIG, 's',
"Configure SSL_CTX using the configuration 'val'"},
{"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,
{"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
{"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"},
#ifndef OPENSSL_NO_PSK
{"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"},
#endif
{"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
{"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"},
{"srpuserseed", OPT_SRPUSERSEED, 's',
"A seed string for a default user salt"},
#endif
#ifndef OPENSSL_NO_SSL3
{"ssl3", OPT_SSL3, '-', "Just talk SSLv3"},
#endif
#ifndef OPENSSL_NO_TLS1
{"tls1", OPT_TLS1, '-', "Just talk TLSv1"},
#endif
#ifndef OPENSSL_NO_TLS1_1
{"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"},
#endif
#ifndef OPENSSL_NO_TLS1_2
{"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"},
#endif
#ifndef OPENSSL_NO_TLS1_3
{"tls1_3", OPT_TLS1_3, '-', "just talk TLSv1.3"},
#endif
#ifndef OPENSSL_NO_DTLS
{"dtls", OPT_DTLS, '-', "Use any DTLS version"},
{"timeout", OPT_TIMEOUT, '-', "Enable timeouts"},
{"mtu", OPT_MTU, 'p', "Set link layer MTU"},
{"listen", OPT_LISTEN, '-',
"Listen for a DTLS ClientHello with a cookie and then connect"},
#endif
{"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"},
#ifndef OPENSSL_NO_DTLS1
{"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"},
#endif
#ifndef OPENSSL_NO_DTLS1_2
{"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"},
#endif
#ifndef OPENSSL_NO_SCTP
{"sctp", OPT_SCTP, '-', "Use SCTP"},
#endif
#ifndef OPENSSL_NO_DH
{"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
{"nextprotoneg", OPT_NEXTPROTONEG, 's',
"Set the advertised protocols for the NPN extension (comma-separated list)"},
#endif
#ifndef OPENSSL_NO_SRTP
{"use_srtp", OPT_SRTP_PROFILES, 's',
"Offer SRTP key management with a colon-separated profile list"},
#endif
{"alpn", OPT_ALPN, 's',
"Set the advertised protocols for the ALPN extension (comma-separated list)"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
{"max_early_data", OPT_MAX_EARLY, 'n',
"The maximum number of bytes of early data as advertised in tickets"},
{"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n',
"The maximum number of bytes of early data (hard limit)"},
{"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"},
{"num_tickets", OPT_S_NUM_TICKETS, 'n',
"The number of TLSv1.3 session tickets that a server will automatically issue" },
{"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"},
{"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"},
{NULL, OPT_EOF, 0, NULL}
};
#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)
int s_server_main(int argc, char *argv[])
{
ENGINE *engine = NULL;
EVP_PKEY *s_key = NULL, *s_dkey = NULL;
SSL_CONF_CTX *cctx = NULL;
const SSL_METHOD *meth = TLS_server_method();
SSL_EXCERT *exc = NULL;
STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL;
STACK_OF(X509_CRL) *crls = NULL;
X509 *s_cert = NULL, *s_dcert = NULL;
X509_VERIFY_PARAM *vpm = NULL;
const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL;
char *dpassarg = NULL, *dpass = NULL;
char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
char *crl_file = NULL, *prog;
#ifdef AF_UNIX
int unlink_unix_path = 0;
#endif
do_server_cb server_cb;
int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0;
#ifndef OPENSSL_NO_DH
char *dhfile = NULL;
int no_dhe = 0;
#endif
int nocert = 0, ret = 1;
int noCApath = 0, noCAfile = 0;
int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM;
int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
int rev = 0, naccept = -1, sdebug = 0;
int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
int state = 0, crl_format = FORMAT_PEM, crl_download = 0;
char *host = NULL;
char *port = BUF_strdup(PORT);
unsigned char *context = NULL;
OPTION_CHOICE o;
EVP_PKEY *s_key2 = NULL;
X509 *s_cert2 = NULL;
tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING };
const char *ssl_config = NULL;
int read_buf_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
const char *next_proto_neg_in = NULL;
tlsextnextprotoctx next_proto = { NULL, 0 };
#endif
const char *alpn_in = NULL;
tlsextalpnctx alpn_ctx = { NULL, 0 };
#ifndef OPENSSL_NO_PSK
/* by default do not send a PSK identity hint */
char *psk_identity_hint = NULL;
#endif
char *p;
#ifndef OPENSSL_NO_SRP
char *srpuserseed = NULL;
char *srp_verifier_file = NULL;
#endif
#ifndef OPENSSL_NO_SRTP
char *srtp_profiles = NULL;
#endif
int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0;
int s_server_verify = SSL_VERIFY_NONE;
int s_server_session_id_context = 1; /* anything will do */
const char *s_cert_file = TEST_CERT, *s_key_file = NULL, *s_chain_file = NULL;
const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL;
char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL;
#ifndef OPENSSL_NO_OCSP
int s_tlsextstatus = 0;
#endif
int no_resume_ephemeral = 0;
unsigned int max_send_fragment = 0;
unsigned int split_send_fragment = 0, max_pipelines = 0;
const char *s_serverinfo_file = NULL;
const char *keylog_file = NULL;
int max_early_data = -1, recv_max_early_data = -1;
char *psksessf = NULL;
/* Init of few remaining global variables */
local_argc = argc;
local_argv = argv;
ctx = ctx2 = NULL;
s_nbio = s_nbio_test = 0;
www = 0;
bio_s_out = NULL;
s_debug = 0;
s_msg = 0;
s_quiet = 0;
s_brief = 0;
async = 0;
cctx = SSL_CONF_CTX_new();
vpm = X509_VERIFY_PARAM_new();
if (cctx == NULL || vpm == NULL)
goto end;
SSL_CONF_CTX_set_flags(cctx,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE);
prog = opt_init(argc, argv, s_server_options);
while ((o = opt_next()) != OPT_EOF) {
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_server_options);
ret = 0;
goto end;
case OPT_4:
#ifdef AF_UNIX
if (socket_family == AF_UNIX) {
OPENSSL_free(host); host = NULL;
OPENSSL_free(port); port = NULL;
}
#endif
socket_family = AF_INET;
break;
case OPT_6:
if (1) {
#ifdef AF_INET6
#ifdef AF_UNIX
if (socket_family == AF_UNIX) {
OPENSSL_free(host); host = NULL;
OPENSSL_free(port); port = NULL;
}
#endif
socket_family = AF_INET6;
} else {
#endif
BIO_printf(bio_err, "%s: IPv6 domain sockets unsupported\n", prog);
goto end;
}
break;
case OPT_PORT:
#ifdef AF_UNIX
if (socket_family == AF_UNIX) {
socket_family = AF_UNSPEC;
}
#endif
OPENSSL_free(port); port = NULL;
OPENSSL_free(host); host = NULL;
if (BIO_parse_hostserv(opt_arg(), NULL, &port, BIO_PARSE_PRIO_SERV) < 1) {
BIO_printf(bio_err,
"%s: -port argument malformed or ambiguous\n",
port);
goto end;
}
break;
case OPT_ACCEPT:
#ifdef AF_UNIX
if (socket_family == AF_UNIX) {
socket_family = AF_UNSPEC;
}
#endif
OPENSSL_free(port); port = NULL;
OPENSSL_free(host); host = NULL;
if (BIO_parse_hostserv(opt_arg(), &host, &port, BIO_PARSE_PRIO_SERV) < 1) {
BIO_printf(bio_err,
"%s: -accept argument malformed or ambiguous\n",
port);
goto end;
}
break;
#ifdef AF_UNIX
case OPT_UNIX:
socket_family = AF_UNIX;
OPENSSL_free(host); host = BUF_strdup(opt_arg());
OPENSSL_free(port); port = NULL;
break;
case OPT_UNLINK:
unlink_unix_path = 1;
break;
#endif
case OPT_NACCEPT:
naccept = atol(opt_arg());
break;
case OPT_VERIFY:
s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
verify_args.depth = atoi(opt_arg());
if (!s_quiet)
BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth);
break;
case OPT_UPPER_V_VERIFY:
s_server_verify =
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
SSL_VERIFY_CLIENT_ONCE;
verify_args.depth = atoi(opt_arg());
if (!s_quiet)
BIO_printf(bio_err,
"verify depth is %d, must return a certificate\n",
verify_args.depth);
break;
case OPT_CONTEXT:
context = (unsigned char *)opt_arg();
break;
case OPT_CERT:
s_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_SERVERINFO:
s_serverinfo_file = opt_arg();
break;
case OPT_CERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format))
goto opthelp;
break;
case OPT_KEY:
s_key_file = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_key_format))
goto opthelp;
break;
case OPT_PASS:
passarg = opt_arg();
break;
case OPT_CERT_CHAIN:
s_chain_file = opt_arg();
break;
case OPT_DHPARAM:
#ifndef OPENSSL_NO_DH
dhfile = opt_arg();
#endif
break;
case OPT_DCERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format))
goto opthelp;
break;
case OPT_DCERT:
s_dcert_file = opt_arg();
break;
case OPT_DKEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dkey_format))
goto opthelp;
break;
case OPT_DPASS:
dpassarg = opt_arg();
break;
case OPT_DKEY:
s_dkey_file = opt_arg();
break;
case OPT_DCERT_CHAIN:
s_dchain_file = opt_arg();
break;
case OPT_NOCERT:
nocert = 1;
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_NO_CACHE:
no_cache = 1;
break;
case OPT_EXT_CACHE:
ext_cache = 1;
break;
case OPT_CRLFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format))
goto opthelp;
break;
case OPT_S_CASES:
case OPT_S_NUM_TICKETS:
case OPT_ANTI_REPLAY:
case OPT_NO_ANTI_REPLAY:
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_VERIFY_RET_ERROR:
verify_args.return_error = 1;
break;
case OPT_VERIFY_QUIET:
verify_args.quiet = 1;
break;
case OPT_BUILD_CHAIN:
build_chain = 1;
break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_CHAINCAFILE:
chCAfile = opt_arg();
break;
case OPT_VERIFYCAFILE:
vfyCAfile = opt_arg();
break;
case OPT_NBIO:
s_nbio = 1;
break;
case OPT_NBIO_TEST:
s_nbio = s_nbio_test = 1;
break;
case OPT_IGN_EOF:
s_ign_eof = 1;
break;
case OPT_NO_IGN_EOF:
s_ign_eof = 0;
break;
case OPT_DEBUG:
s_debug = 1;
break;
case OPT_TLSEXTDEBUG:
s_tlsextdebug = 1;
break;
case OPT_STATUS:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
#endif
break;
case OPT_STATUS_VERBOSE:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = tlscstatp.verbose = 1;
#endif
break;
case OPT_STATUS_TIMEOUT:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
tlscstatp.timeout = atoi(opt_arg());
#endif
break;
case OPT_STATUS_URL:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
if (!OCSP_parse_url(opt_arg(),
&tlscstatp.host,
&tlscstatp.port,
&tlscstatp.path, &tlscstatp.use_ssl)) {
BIO_printf(bio_err, "Error parsing URL\n");
goto end;
}
#endif
break;
case OPT_STATUS_FILE:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
tlscstatp.respin = opt_arg();
#endif
break;
case OPT_MSG:
s_msg = 1;
break;
case OPT_MSGFILE:
bio_s_msg = BIO_new_file(opt_arg(), "w");
break;
case OPT_TRACE:
#ifndef OPENSSL_NO_SSL_TRACE
s_msg = 2;
#endif
break;
case OPT_SECURITY_DEBUG:
sdebug = 1;
break;
case OPT_SECURITY_DEBUG_VERBOSE:
sdebug = 2;
break;
case OPT_STATE:
state = 1;
break;
case OPT_CRLF:
s_crlf = 1;
break;
case OPT_QUIET:
s_quiet = 1;
break;
case OPT_BRIEF:
s_quiet = s_brief = verify_args.quiet = 1;
break;
case OPT_NO_DHE:
#ifndef OPENSSL_NO_DH
no_dhe = 1;
#endif
break;
case OPT_NO_RESUME_EPHEMERAL:
no_resume_ephemeral = 1;
break;
case OPT_PSK_IDENTITY:
psk_identity = opt_arg();
break;
case OPT_PSK_HINT:
#ifndef OPENSSL_NO_PSK
psk_identity_hint = opt_arg();
#endif
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", *argv);
goto end;
}
break;
case OPT_PSK_SESS:
psksessf = opt_arg();
break;
case OPT_SRPVFILE:
#ifndef OPENSSL_NO_SRP
srp_verifier_file = opt_arg();
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
#endif
break;
case OPT_SRPUSERSEED:
#ifndef OPENSSL_NO_SRP
srpuserseed = opt_arg();
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
#endif
break;
case OPT_REV:
rev = 1;
break;
case OPT_WWW:
www = 1;
break;
case OPT_UPPER_WWW:
www = 2;
break;
case OPT_HTTP:
www = 3;
break;
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_server_method();
socket_type = SOCK_DGRAM;
#endif
break;
case OPT_DTLS1:
#ifndef OPENSSL_NO_DTLS
meth = DTLS_server_method();
min_version = DTLS1_VERSION;
max_version = DTLS1_VERSION;
socket_type = SOCK_DGRAM;
#endif
break;
case OPT_DTLS1_2:
#ifndef OPENSSL_NO_DTLS
meth = DTLS_server_method();
min_version = DTLS1_2_VERSION;
max_version = DTLS1_2_VERSION;
socket_type = SOCK_DGRAM;
#endif
break;
case OPT_SCTP:
#ifndef OPENSSL_NO_SCTP
protocol = IPPROTO_SCTP;
#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_LISTEN:
#ifndef OPENSSL_NO_DTLS
dtlslisten = 1;
#endif
break;
case OPT_STATELESS:
stateless = 1;
break;
case OPT_ID_PREFIX:
session_id_prefix = opt_arg();
break;
case OPT_ENGINE:
engine = setup_engine(opt_arg(), 1);
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_SERVERNAME:
tlsextcbp.servername = opt_arg();
break;
case OPT_SERVERNAME_FATAL:
tlsextcbp.extension_error = SSL_TLSEXT_ERR_ALERT_FATAL;
break;
case OPT_CERT2:
s_cert_file2 = opt_arg();
break;
case OPT_KEY2:
s_key_file2 = opt_arg();
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_SRTP_PROFILES:
#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_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_MAX_EARLY:
max_early_data = atoi(opt_arg());
if (max_early_data < 0) {
BIO_printf(bio_err, "Invalid value for max_early_data\n");
goto end;
}
break;
case OPT_RECV_MAX_EARLY:
recv_max_early_data = atoi(opt_arg());
if (recv_max_early_data < 0) {
BIO_printf(bio_err, "Invalid value for recv_max_early_data\n");
goto end;
}
break;
case OPT_EARLY_DATA:
early_data = 1;
if (max_early_data == -1)
max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
break;
}
}
argc = opt_num_rest();
argv = opt_rest();
#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
#ifndef OPENSSL_NO_DTLS
if (www && socket_type == SOCK_DGRAM) {
BIO_printf(bio_err, "Can't use -HTTP, -www or -WWW with DTLS\n");
goto end;
}
if (dtlslisten && socket_type != SOCK_DGRAM) {
BIO_printf(bio_err, "Can only use -listen with DTLS\n");
goto end;
}
#endif
if (stateless && socket_type != SOCK_STREAM) {
BIO_printf(bio_err, "Can only use --stateless with TLS\n");
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
+ if (early_data && (www > 0 || rev)) {
+ BIO_printf(bio_err,
+ "Can't use -early_data in combination with -www, -WWW, -HTTP, or -rev\n");
+ goto end;
+ }
#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 (!app_passwd(passarg, dpassarg, &pass, &dpass)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
if (s_key_file == NULL)
s_key_file = s_cert_file;
if (s_key_file2 == NULL)
s_key_file2 = s_cert_file2;
if (!load_excert(&exc))
goto end;
if (nocert == 0) {
s_key = load_key(s_key_file, s_key_format, 0, pass, engine,
"server certificate private key file");
if (s_key == NULL) {
ERR_print_errors(bio_err);
goto end;
}
s_cert = load_cert(s_cert_file, s_cert_format,
"server certificate file");
if (s_cert == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (s_chain_file != NULL) {
if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL,
"server certificate chain"))
goto end;
}
if (tlsextcbp.servername != NULL) {
s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine,
"second server certificate private key file");
if (s_key2 == NULL) {
ERR_print_errors(bio_err);
goto end;
}
s_cert2 = load_cert(s_cert_file2, s_cert_format,
"second server certificate file");
if (s_cert2 == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
}
#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (next_proto_neg_in) {
next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in);
if (next_proto.data == NULL)
goto end;
}
#endif
alpn_ctx.data = NULL;
if (alpn_in) {
alpn_ctx.data = next_protos_parse(&alpn_ctx.len, alpn_in);
if (alpn_ctx.data == NULL)
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 (s_dcert_file != NULL) {
if (s_dkey_file == NULL)
s_dkey_file = s_dcert_file;
s_dkey = load_key(s_dkey_file, s_dkey_format,
0, dpass, engine, "second certificate private key file");
if (s_dkey == NULL) {
ERR_print_errors(bio_err);
goto end;
}
s_dcert = load_cert(s_dcert_file, s_dcert_format,
"second server certificate file");
if (s_dcert == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (s_dchain_file != NULL) {
if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL,
"second server certificate chain"))
goto end;
}
}
if (bio_s_out == NULL) {
if (s_quiet && !s_debug) {
bio_s_out = BIO_new(BIO_s_null());
if (s_msg && bio_s_msg == NULL)
bio_s_msg = dup_bio_out(FORMAT_TEXT);
} else {
if (bio_s_out == NULL)
bio_s_out = dup_bio_out(FORMAT_TEXT);
}
}
#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
if (nocert)
#endif
{
s_cert_file = NULL;
s_key_file = NULL;
s_dcert_file = NULL;
s_dkey_file = NULL;
s_cert_file2 = NULL;
s_key_file2 = NULL;
}
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) {
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;
}
}
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 (session_id_prefix) {
if (strlen(session_id_prefix) >= 32)
BIO_printf(bio_err,
"warning: id_prefix is too long, only one new session will be possible\n");
if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) {
BIO_printf(bio_err, "error setting 'id_prefix'\n");
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
}
SSL_CTX_set_quiet_shutdown(ctx, 1);
if (exc != NULL)
ssl_ctx_set_excert(ctx, exc);
if (state)
SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
if (no_cache)
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
else if (ext_cache)
init_session_cache_ctx(ctx);
else
SSL_CTX_sess_set_cache_size(ctx, 128);
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);
}
#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 (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
ERR_print_errors(bio_err);
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;
}
ssl_ctx_add_crls(ctx, crls, 0);
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 (s_cert2) {
ctx2 = SSL_CTX_new(meth);
if (ctx2 == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (ctx2 != NULL) {
BIO_printf(bio_s_out, "Setting secondary ctx parameters\n");
if (sdebug)
ssl_ctx_security_debug(ctx, sdebug);
if (session_id_prefix) {
if (strlen(session_id_prefix) >= 32)
BIO_printf(bio_err,
"warning: id_prefix is too long, only one new session will be possible\n");
if (!SSL_CTX_set_generate_session_id(ctx2, generate_session_id)) {
BIO_printf(bio_err, "error setting 'id_prefix'\n");
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
}
SSL_CTX_set_quiet_shutdown(ctx2, 1);
if (exc != NULL)
ssl_ctx_set_excert(ctx2, exc);
if (state)
SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback);
if (no_cache)
SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF);
else if (ext_cache)
init_session_cache_ctx(ctx2);
else
SSL_CTX_sess_set_cache_size(ctx2, 128);
if (async)
SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC);
if (!ctx_set_verify_locations(ctx2, CAfile, CApath, noCAfile,
noCApath)) {
ERR_print_errors(bio_err);
goto end;
}
if (vpmtouched && !SSL_CTX_set1_param(ctx2, vpm)) {
BIO_printf(bio_err, "Error setting verify params\n");
ERR_print_errors(bio_err);
goto end;
}
ssl_ctx_add_crls(ctx2, crls, 0);
if (!config_ctx(cctx, ssl_args, ctx2))
goto end;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
if (next_proto.data)
SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb,
&next_proto);
#endif
if (alpn_ctx.data)
SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
#ifndef OPENSSL_NO_DH
if (!no_dhe) {
DH *dh = NULL;
if (dhfile != NULL)
dh = load_dh_param(dhfile);
else if (s_cert_file != NULL)
dh = load_dh_param(s_cert_file);
if (dh != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
} else {
BIO_printf(bio_s_out, "Using default temp DH parameters\n");
}
(void)BIO_flush(bio_s_out);
if (dh == NULL) {
SSL_CTX_set_dh_auto(ctx, 1);
} else if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
DH_free(dh);
goto end;
}
if (ctx2 != NULL) {
if (!dhfile) {
DH *dh2 = load_dh_param(s_cert_file2);
if (dh2 != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
(void)BIO_flush(bio_s_out);
DH_free(dh);
dh = dh2;
}
}
if (dh == NULL) {
SSL_CTX_set_dh_auto(ctx2, 1);
} else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
DH_free(dh);
goto end;
}
}
DH_free(dh);
}
#endif
if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
goto end;
if (s_serverinfo_file != NULL
&& !SSL_CTX_use_serverinfo_file(ctx, s_serverinfo_file)) {
ERR_print_errors(bio_err);
goto end;
}
if (ctx2 != NULL
&& !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain))
goto end;
if (s_dcert != NULL) {
if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain))
goto end;
}
if (no_resume_ephemeral) {
SSL_CTX_set_not_resumable_session_callback(ctx,
not_resumable_sess_cb);
if (ctx2 != NULL)
SSL_CTX_set_not_resumable_session_callback(ctx2,
not_resumable_sess_cb);
}
#ifndef OPENSSL_NO_PSK
if (psk_key != NULL) {
if (s_debug)
BIO_printf(bio_s_out, "PSK key given, setting server callback\n");
SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);
}
if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) {
BIO_printf(bio_err, "error setting PSK identity hint to context\n");
ERR_print_errors(bio_err);
goto end;
}
#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_find_session_callback(ctx, psk_find_session_cb);
SSL_CTX_set_verify(ctx, s_server_verify, verify_callback);
if (!SSL_CTX_set_session_id_context(ctx,
(void *)&s_server_session_id_context,
sizeof(s_server_session_id_context))) {
BIO_printf(bio_err, "error setting session id context\n");
ERR_print_errors(bio_err);
goto end;
}
/* Set DTLS cookie generation and verification callbacks */
SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback);
SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback);
/* Set TLS1.3 cookie generation and verification callbacks */
SSL_CTX_set_stateless_cookie_generate_cb(ctx, generate_stateless_cookie_callback);
SSL_CTX_set_stateless_cookie_verify_cb(ctx, verify_stateless_cookie_callback);
if (ctx2 != NULL) {
SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback);
if (!SSL_CTX_set_session_id_context(ctx2,
(void *)&s_server_session_id_context,
sizeof(s_server_session_id_context))) {
BIO_printf(bio_err, "error setting session id context\n");
ERR_print_errors(bio_err);
goto end;
}
tlsextcbp.biodebug = bio_s_out;
SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp);
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
}
#ifndef OPENSSL_NO_SRP
if (srp_verifier_file != NULL) {
srp_callback_parm.vb = SRP_VBASE_new(srpuserseed);
srp_callback_parm.user = NULL;
srp_callback_parm.login = NULL;
if ((ret =
SRP_VBASE_init(srp_callback_parm.vb,
srp_verifier_file)) != SRP_NO_ERROR) {
BIO_printf(bio_err,
"Cannot initialize SRP verifier file \"%s\":ret=%d\n",
srp_verifier_file, ret);
goto end;
}
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm);
SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
} else
#endif
if (CAfile != NULL) {
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile));
if (ctx2)
SSL_CTX_set_client_CA_list(ctx2, SSL_load_client_CA_file(CAfile));
}
#ifndef OPENSSL_NO_OCSP
if (s_tlsextstatus) {
SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb);
SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp);
if (ctx2) {
SSL_CTX_set_tlsext_status_cb(ctx2, cert_status_cb);
SSL_CTX_set_tlsext_status_arg(ctx2, &tlscstatp);
}
}
#endif
if (set_keylog_file(ctx, keylog_file))
goto end;
if (max_early_data >= 0)
SSL_CTX_set_max_early_data(ctx, max_early_data);
if (recv_max_early_data >= 0)
SSL_CTX_set_recv_max_early_data(ctx, recv_max_early_data);
if (rev)
server_cb = rev_body;
else if (www)
server_cb = www_body;
else
server_cb = sv_body;
#ifdef AF_UNIX
if (socket_family == AF_UNIX
&& unlink_unix_path)
unlink(host);
#endif
do_server(&accept_socket, host, port, socket_family, socket_type, protocol,
server_cb, context, naccept, bio_s_out);
print_stats(bio_s_out, ctx);
ret = 0;
end:
SSL_CTX_free(ctx);
SSL_SESSION_free(psksess);
set_keylog_file(NULL, NULL);
X509_free(s_cert);
sk_X509_CRL_pop_free(crls, X509_CRL_free);
X509_free(s_dcert);
EVP_PKEY_free(s_key);
EVP_PKEY_free(s_dkey);
sk_X509_pop_free(s_chain, X509_free);
sk_X509_pop_free(s_dchain, X509_free);
OPENSSL_free(pass);
OPENSSL_free(dpass);
OPENSSL_free(host);
OPENSSL_free(port);
X509_VERIFY_PARAM_free(vpm);
free_sessions();
OPENSSL_free(tlscstatp.host);
OPENSSL_free(tlscstatp.port);
OPENSSL_free(tlscstatp.path);
SSL_CTX_free(ctx2);
X509_free(s_cert2);
EVP_PKEY_free(s_key2);
#ifndef OPENSSL_NO_NEXTPROTONEG
OPENSSL_free(next_proto.data);
#endif
OPENSSL_free(alpn_ctx.data);
ssl_excert_free(exc);
sk_OPENSSL_STRING_free(ssl_args);
SSL_CONF_CTX_free(cctx);
release_engine(engine);
BIO_free(bio_s_out);
bio_s_out = NULL;
BIO_free(bio_s_msg);
bio_s_msg = NULL;
#ifdef CHARSET_EBCDIC
BIO_meth_free(methods_ebcdic);
#endif
return ret;
}
static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
{
BIO_printf(bio, "%4ld items in the session cache\n",
SSL_CTX_sess_number(ssl_ctx));
BIO_printf(bio, "%4ld client connects (SSL_connect())\n",
SSL_CTX_sess_connect(ssl_ctx));
BIO_printf(bio, "%4ld client renegotiates (SSL_connect())\n",
SSL_CTX_sess_connect_renegotiate(ssl_ctx));
BIO_printf(bio, "%4ld client connects that finished\n",
SSL_CTX_sess_connect_good(ssl_ctx));
BIO_printf(bio, "%4ld server accepts (SSL_accept())\n",
SSL_CTX_sess_accept(ssl_ctx));
BIO_printf(bio, "%4ld server renegotiates (SSL_accept())\n",
SSL_CTX_sess_accept_renegotiate(ssl_ctx));
BIO_printf(bio, "%4ld server accepts that finished\n",
SSL_CTX_sess_accept_good(ssl_ctx));
BIO_printf(bio, "%4ld session cache hits\n", SSL_CTX_sess_hits(ssl_ctx));
BIO_printf(bio, "%4ld session cache misses\n",
SSL_CTX_sess_misses(ssl_ctx));
BIO_printf(bio, "%4ld session cache timeouts\n",
SSL_CTX_sess_timeouts(ssl_ctx));
BIO_printf(bio, "%4ld callback cache hits\n",
SSL_CTX_sess_cb_hits(ssl_ctx));
BIO_printf(bio, "%4ld cache full overflows (%ld allowed)\n",
SSL_CTX_sess_cache_full(ssl_ctx),
SSL_CTX_sess_get_cache_size(ssl_ctx));
}
static int sv_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;
fd_set readfds;
int ret = 1, width;
int k, i;
unsigned long l;
SSL *con = NULL;
BIO *sbio;
struct timeval timeout;
#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS))
struct timeval *timeoutp;
#endif
#ifndef OPENSSL_NO_DTLS
# ifndef OPENSSL_NO_SCTP
int isdtls = (stype == SOCK_DGRAM || prot == IPPROTO_SCTP);
# else
int isdtls = (stype == SOCK_DGRAM);
# endif
#endif
buf = app_malloc(bufsize, "server buffer");
if (s_nbio) {
if (!BIO_socket_nbio(s, 1))
ERR_print_errors(bio_err);
else if (!s_quiet)
BIO_printf(bio_err, "Turned on non blocking io\n");
}
con = SSL_new(ctx);
if (con == NULL) {
ret = -1;
goto err;
}
if (s_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_s_out);
}
if (context != NULL
&& !SSL_set_session_id_context(con, context,
strlen((char *)context))) {
BIO_printf(bio_err, "Error setting session id context\n");
ret = -1;
goto err;
}
if (!SSL_clear(con)) {
BIO_printf(bio_err, "Error clearing SSL connection\n");
ret = -1;
goto err;
}
#ifndef OPENSSL_NO_DTLS
if (isdtls) {
# ifndef OPENSSL_NO_SCTP
if (prot == IPPROTO_SCTP)
sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
else
# endif
sbio = BIO_new_dgram(s, BIO_NOCLOSE);
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));
ret = -1;
BIO_free(sbio);
goto err;
}
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");
ret = -1;
BIO_free(sbio);
goto err;
}
} else
/* want to do MTU discovery */
BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
# ifndef OPENSSL_NO_SCTP
if (prot != IPPROTO_SCTP)
# endif
/* Turn on cookie exchange. Not necessary for SCTP */
SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE);
} else
#endif
sbio = BIO_new_socket(s, BIO_NOCLOSE);
if (sbio == NULL) {
BIO_printf(bio_err, "Unable to create BIO\n");
ERR_print_errors(bio_err);
goto err;
}
if (s_nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
sbio = BIO_push(test, sbio);
}
SSL_set_bio(con, sbio, sbio);
SSL_set_accept_state(con);
/* SSL_set_fd(con,s); */
if (s_debug) {
BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (s_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_s_msg ? bio_s_msg : bio_s_out);
}
if (s_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_s_out);
}
if (early_data) {
int write_header = 1, edret = SSL_READ_EARLY_DATA_ERROR;
size_t readbytes;
while (edret != SSL_READ_EARLY_DATA_FINISH) {
for (;;) {
edret = SSL_read_early_data(con, buf, bufsize, &readbytes);
if (edret != SSL_READ_EARLY_DATA_ERROR)
break;
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 reading early data\n");
ERR_print_errors(bio_err);
goto err;
}
}
if (readbytes > 0) {
if (write_header) {
BIO_printf(bio_s_out, "Early data received:\n");
write_header = 0;
}
raw_write_stdout(buf, (unsigned int)readbytes);
(void)BIO_flush(bio_s_out);
}
}
if (write_header) {
if (SSL_get_early_data_status(con) == SSL_EARLY_DATA_NOT_SENT)
BIO_printf(bio_s_out, "No early data received\n");
else
BIO_printf(bio_s_out, "Early data was rejected\n");
} else {
BIO_printf(bio_s_out, "\nEnd of early data\n");
}
if (SSL_is_init_finished(con))
print_connection_info(con);
}
if (fileno_stdin() > s)
width = fileno_stdin() + 1;
else
width = s + 1;
for (;;) {
int read_from_terminal;
int read_from_sslcon;
read_from_terminal = 0;
read_from_sslcon = SSL_has_pending(con)
|| (async && SSL_waiting_for_async(con));
if (!read_from_sslcon) {
FD_ZERO(&readfds);
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
openssl_fdset(fileno_stdin(), &readfds);
#endif
openssl_fdset(s, &readfds);
/*
* 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 DOS (non-djgpp) and Windows we can't select on stdin:
* only on sockets. As a workaround we timeout the select every
* second and check for any keypress. In a proper Windows
* application we wouldn't do this because it is inefficient.
*/
timeout.tv_sec = 1;
timeout.tv_usec = 0;
i = select(width, (void *)&readfds, NULL, NULL, &timeout);
if (has_stdin_waiting())
read_from_terminal = 1;
if ((i < 0) || (!i && !read_from_terminal))
continue;
#else
if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout))
timeoutp = &timeout;
else
timeoutp = NULL;
i = select(width, (void *)&readfds, NULL, NULL, timeoutp);
if ((SSL_is_dtls(con)) && DTLSv1_handle_timeout(con) > 0)
BIO_printf(bio_err, "TIMEOUT occurred\n");
if (i <= 0)
continue;
if (FD_ISSET(fileno_stdin(), &readfds))
read_from_terminal = 1;
#endif
if (FD_ISSET(s, &readfds))
read_from_sslcon = 1;
}
if (read_from_terminal) {
if (s_crlf) {
int j, lf_num;
i = raw_read_stdin(buf, bufsize / 2);
lf_num = 0;
/* both loops are skipped when i <= 0 */
for (j = 0; j < i; j++)
if (buf[j] == '\n')
lf_num++;
for (j = i - 1; j >= 0; j--) {
buf[j + lf_num] = buf[j];
if (buf[j] == '\n') {
lf_num--;
i++;
buf[j + lf_num] = '\r';
}
}
assert(lf_num == 0);
} else {
i = raw_read_stdin(buf, bufsize);
}
if (!s_quiet && !s_brief) {
if ((i <= 0) || (buf[0] == 'Q')) {
BIO_printf(bio_s_out, "DONE\n");
(void)BIO_flush(bio_s_out);
BIO_closesocket(s);
close_accept_socket();
ret = -11;
goto err;
}
if ((i <= 0) || (buf[0] == 'q')) {
BIO_printf(bio_s_out, "DONE\n");
(void)BIO_flush(bio_s_out);
if (SSL_version(con) != DTLS1_VERSION)
BIO_closesocket(s);
/*
* close_accept_socket(); ret= -11;
*/
goto err;
}
#ifndef OPENSSL_NO_HEARTBEATS
if ((buf[0] == 'B') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
BIO_printf(bio_err, "HEARTBEATING\n");
SSL_heartbeat(con);
i = 0;
continue;
}
#endif
if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_renegotiate(con);
i = SSL_do_handshake(con);
printf("SSL_do_handshake -> %d\n", i);
i = 0; /* 13; */
continue;
}
if ((buf[0] == 'R') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_set_verify(con,
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
NULL);
SSL_renegotiate(con);
i = SSL_do_handshake(con);
printf("SSL_do_handshake -> %d\n", i);
i = 0; /* 13; */
continue;
}
if ((buf[0] == 'K' || buf[0] == 'k')
&& ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_key_update(con, buf[0] == 'K' ?
SSL_KEY_UPDATE_REQUESTED
: SSL_KEY_UPDATE_NOT_REQUESTED);
i = SSL_do_handshake(con);
printf("SSL_do_handshake -> %d\n", i);
i = 0;
continue;
}
if (buf[0] == 'c' && ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_set_verify(con, SSL_VERIFY_PEER, NULL);
i = SSL_verify_client_post_handshake(con);
if (i == 0) {
printf("Failed to initiate request\n");
ERR_print_errors(bio_err);
} else {
i = SSL_do_handshake(con);
printf("SSL_do_handshake -> %d\n", i);
i = 0;
}
continue;
}
if (buf[0] == 'P') {
static const char *str = "Lets print some clear text\n";
BIO_write(SSL_get_wbio(con), str, strlen(str));
}
if (buf[0] == 'S') {
print_stats(bio_s_out, SSL_get_SSL_CTX(con));
}
}
#ifdef CHARSET_EBCDIC
ebcdic2ascii(buf, buf, i);
#endif
l = k = 0;
for (;;) {
/* should do a select for the write */
#ifdef RENEG
static count = 0;
if (++count == 100) {
count = 0;
SSL_renegotiate(con);
}
#endif
k = SSL_write(con, &(buf[l]), (unsigned int)i);
#ifndef OPENSSL_NO_SRP
while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during write\n");
SRP_user_pwd_free(srp_callback_parm.user);
srp_callback_parm.user =
SRP_VBASE_get1_by_user(srp_callback_parm.vb,
srp_callback_parm.login);
if (srp_callback_parm.user)
BIO_printf(bio_s_out, "LOOKUP done %s\n",
srp_callback_parm.user->info);
else
BIO_printf(bio_s_out, "LOOKUP not successful\n");
k = SSL_write(con, &(buf[l]), (unsigned int)i);
}
#endif
switch (SSL_get_error(con, k)) {
case SSL_ERROR_NONE:
break;
case SSL_ERROR_WANT_ASYNC:
BIO_printf(bio_s_out, "Write BLOCK (Async)\n");
(void)BIO_flush(bio_s_out);
wait_for_async(con);
break;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_X509_LOOKUP:
BIO_printf(bio_s_out, "Write BLOCK\n");
(void)BIO_flush(bio_s_out);
break;
case SSL_ERROR_WANT_ASYNC_JOB:
/*
* This shouldn't ever happen in s_server. Treat as an error
*/
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
BIO_printf(bio_s_out, "ERROR\n");
(void)BIO_flush(bio_s_out);
ERR_print_errors(bio_err);
ret = 1;
goto err;
/* break; */
case SSL_ERROR_ZERO_RETURN:
BIO_printf(bio_s_out, "DONE\n");
(void)BIO_flush(bio_s_out);
ret = 1;
goto err;
}
if (k > 0) {
l += k;
i -= k;
}
if (i <= 0)
break;
}
}
if (read_from_sslcon) {
/*
* init_ssl_connection handles all async events itself so if we're
* waiting for async then we shouldn't go back into
* init_ssl_connection
*/
if ((!async || !SSL_waiting_for_async(con))
&& !SSL_is_init_finished(con)) {
i = init_ssl_connection(con);
if (i < 0) {
ret = 0;
goto err;
} else if (i == 0) {
ret = 1;
goto err;
}
} else {
again:
i = SSL_read(con, (char *)buf, bufsize);
#ifndef OPENSSL_NO_SRP
while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
SRP_user_pwd_free(srp_callback_parm.user);
srp_callback_parm.user =
SRP_VBASE_get1_by_user(srp_callback_parm.vb,
srp_callback_parm.login);
if (srp_callback_parm.user)
BIO_printf(bio_s_out, "LOOKUP done %s\n",
srp_callback_parm.user->info);
else
BIO_printf(bio_s_out, "LOOKUP not successful\n");
i = SSL_read(con, (char *)buf, bufsize);
}
#endif
switch (SSL_get_error(con, i)) {
case SSL_ERROR_NONE:
#ifdef CHARSET_EBCDIC
ascii2ebcdic(buf, buf, i);
#endif
raw_write_stdout(buf, (unsigned int)i);
(void)BIO_flush(bio_s_out);
if (SSL_has_pending(con))
goto again;
break;
case SSL_ERROR_WANT_ASYNC:
BIO_printf(bio_s_out, "Read BLOCK (Async)\n");
(void)BIO_flush(bio_s_out);
wait_for_async(con);
break;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_READ:
BIO_printf(bio_s_out, "Read BLOCK\n");
(void)BIO_flush(bio_s_out);
break;
case SSL_ERROR_WANT_ASYNC_JOB:
/*
* This shouldn't ever happen in s_server. Treat as an error
*/
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
BIO_printf(bio_s_out, "ERROR\n");
(void)BIO_flush(bio_s_out);
ERR_print_errors(bio_err);
ret = 1;
goto err;
case SSL_ERROR_ZERO_RETURN:
BIO_printf(bio_s_out, "DONE\n");
(void)BIO_flush(bio_s_out);
ret = 1;
goto err;
}
}
}
}
err:
if (con != NULL) {
BIO_printf(bio_s_out, "shutting down SSL\n");
SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
SSL_free(con);
}
BIO_printf(bio_s_out, "CONNECTION CLOSED\n");
OPENSSL_clear_free(buf, bufsize);
return ret;
}
static void close_accept_socket(void)
{
BIO_printf(bio_err, "shutdown accept socket\n");
if (accept_socket >= 0) {
BIO_closesocket(accept_socket);
}
}
static int is_retryable(SSL *con, int i)
{
int err = SSL_get_error(con, i);
/* If it's not a fatal error, it must be retryable */
return (err != SSL_ERROR_SSL)
&& (err != SSL_ERROR_SYSCALL)
&& (err != SSL_ERROR_ZERO_RETURN);
}
static int init_ssl_connection(SSL *con)
{
int i;
long verify_err;
int retry = 0;
if (dtlslisten || stateless) {
BIO_ADDR *client = NULL;
if (dtlslisten) {
if ((client = BIO_ADDR_new()) == NULL) {
BIO_printf(bio_err, "ERROR - memory\n");
return 0;
}
i = DTLSv1_listen(con, client);
} else {
i = SSL_stateless(con);
}
if (i > 0) {
BIO *wbio;
int fd = -1;
if (dtlslisten) {
wbio = SSL_get_wbio(con);
if (wbio) {
BIO_get_fd(wbio, &fd);
}
if (!wbio || BIO_connect(fd, client, 0) == 0) {
BIO_printf(bio_err, "ERROR - unable to connect\n");
BIO_ADDR_free(client);
return 0;
}
BIO_ADDR_free(client);
dtlslisten = 0;
} else {
stateless = 0;
}
i = SSL_accept(con);
} else {
BIO_ADDR_free(client);
}
} else {
do {
i = SSL_accept(con);
if (i <= 0)
retry = is_retryable(con, i);
#ifdef CERT_CB_TEST_RETRY
{
while (i <= 0
&& SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP
&& SSL_get_state(con) == TLS_ST_SR_CLNT_HELLO) {
BIO_printf(bio_err,
"LOOKUP from certificate callback during accept\n");
i = SSL_accept(con);
if (i <= 0)
retry = is_retryable(con, i);
}
}
#endif
#ifndef OPENSSL_NO_SRP
while (i <= 0
&& SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
srp_callback_parm.login);
SRP_user_pwd_free(srp_callback_parm.user);
srp_callback_parm.user =
SRP_VBASE_get1_by_user(srp_callback_parm.vb,
srp_callback_parm.login);
if (srp_callback_parm.user)
BIO_printf(bio_s_out, "LOOKUP done %s\n",
srp_callback_parm.user->info);
else
BIO_printf(bio_s_out, "LOOKUP not successful\n");
i = SSL_accept(con);
if (i <= 0)
retry = is_retryable(con, i);
}
#endif
} while (i < 0 && SSL_waiting_for_async(con));
}
if (i <= 0) {
if (((dtlslisten || stateless) && i == 0)
|| (!dtlslisten && !stateless && retry)) {
BIO_printf(bio_s_out, "DELAY\n");
return 1;
}
BIO_printf(bio_err, "ERROR\n");
verify_err = SSL_get_verify_result(con);
if (verify_err != X509_V_OK) {
BIO_printf(bio_err, "verify error:%s\n",
X509_verify_cert_error_string(verify_err));
}
/* Always print any error messages */
ERR_print_errors(bio_err);
return 0;
}
print_connection_info(con);
return 1;
}
static void print_connection_info(SSL *con)
{
const char *str;
X509 *peer;
char buf[BUFSIZ];
#if !defined(OPENSSL_NO_NEXTPROTONEG)
const unsigned char *next_proto_neg;
unsigned next_proto_neg_len;
#endif
unsigned char *exportedkeymat;
int i;
if (s_brief)
print_ssl_summary(con);
PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con));
peer = SSL_get_peer_certificate(con);
if (peer != NULL) {
BIO_printf(bio_s_out, "Client certificate\n");
PEM_write_bio_X509(bio_s_out, peer);
dump_cert_text(bio_s_out, peer);
X509_free(peer);
peer = NULL;
}
if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL)
BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
str = SSL_CIPHER_get_name(SSL_get_current_cipher(con));
ssl_print_sigalgs(bio_s_out, con);
#ifndef OPENSSL_NO_EC
ssl_print_point_formats(bio_s_out, con);
ssl_print_groups(bio_s_out, con, 0);
#endif
print_ca_names(bio_s_out, con);
BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)");
#if !defined(OPENSSL_NO_NEXTPROTONEG)
SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len);
if (next_proto_neg) {
BIO_printf(bio_s_out, "NEXTPROTO is ");
BIO_write(bio_s_out, next_proto_neg, next_proto_neg_len);
BIO_printf(bio_s_out, "\n");
}
#endif
#ifndef OPENSSL_NO_SRTP
{
SRTP_PROTECTION_PROFILE *srtp_profile
= SSL_get_selected_srtp_profile(con);
if (srtp_profile)
BIO_printf(bio_s_out, "SRTP Extension negotiated, profile=%s\n",
srtp_profile->name);
}
#endif
if (SSL_session_reused(con))
BIO_printf(bio_s_out, "Reused session-id\n");
BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION))
BIO_printf(bio_s_out, "Renegotiation is DISABLED\n");
if (keymatexportlabel != NULL) {
BIO_printf(bio_s_out, "Keying material exporter:\n");
BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen);
exportedkeymat = app_malloc(keymatexportlen, "export key");
if (!SSL_export_keying_material(con, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
NULL, 0, 0)) {
BIO_printf(bio_s_out, " Error\n");
} else {
BIO_printf(bio_s_out, " Keying material: ");
for (i = 0; i < keymatexportlen; i++)
BIO_printf(bio_s_out, "%02X", exportedkeymat[i]);
BIO_printf(bio_s_out, "\n");
}
OPENSSL_free(exportedkeymat);
}
(void)BIO_flush(bio_s_out);
}
#ifndef OPENSSL_NO_DH
static DH *load_dh_param(const char *dhfile)
{
DH *ret = NULL;
BIO *bio;
if ((bio = BIO_new_file(dhfile, "r")) == NULL)
goto err;
ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
err:
BIO_free(bio);
return ret;
}
#endif
static int www_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;
int ret = 1;
int i, j, k, dot;
SSL *con;
const SSL_CIPHER *c;
BIO *io, *ssl_bio, *sbio;
#ifdef RENEG
int total_bytes = 0;
#endif
int width;
fd_set readfds;
/* Set width for a select call if needed */
width = s + 1;
buf = app_malloc(bufsize, "server www buffer");
io = BIO_new(BIO_f_buffer());
ssl_bio = BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL))
goto err;
if (s_nbio) {
if (!BIO_socket_nbio(s, 1))
ERR_print_errors(bio_err);
else if (!s_quiet)
BIO_printf(bio_err, "Turned on non blocking io\n");
}
/* lets make the output buffer a reasonable size */
if (!BIO_set_write_buffer_size(io, bufsize))
goto err;
if ((con = SSL_new(ctx)) == NULL)
goto err;
if (s_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_s_out);
}
if (context != NULL
&& !SSL_set_session_id_context(con, context,
strlen((char *)context))) {
SSL_free(con);
goto err;
}
sbio = BIO_new_socket(s, BIO_NOCLOSE);
if (s_nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
sbio = BIO_push(test, sbio);
}
SSL_set_bio(con, sbio, sbio);
SSL_set_accept_state(con);
/* No need to free |con| after this. Done by BIO_free(ssl_bio) */
BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
BIO_push(io, ssl_bio);
#ifdef CHARSET_EBCDIC
io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
#endif
if (s_debug) {
BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (s_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_s_msg ? bio_s_msg : bio_s_out);
}
for (;;) {
i = BIO_gets(io, buf, bufsize - 1);
if (i < 0) { /* error */
if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) {
if (!s_quiet)
ERR_print_errors(bio_err);
goto err;
} else {
BIO_printf(bio_s_out, "read R BLOCK\n");
#ifndef OPENSSL_NO_SRP
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
SRP_user_pwd_free(srp_callback_parm.user);
srp_callback_parm.user =
SRP_VBASE_get1_by_user(srp_callback_parm.vb,
srp_callback_parm.login);
if (srp_callback_parm.user)
BIO_printf(bio_s_out, "LOOKUP done %s\n",
srp_callback_parm.user->info);
else
BIO_printf(bio_s_out, "LOOKUP not successful\n");
continue;
}
#endif
#if !defined(OPENSSL_SYS_MSDOS)
sleep(1);
#endif
continue;
}
} else if (i == 0) { /* end of input */
ret = 1;
goto end;
}
/* else we have data */
if (((www == 1) && (strncmp("GET ", buf, 4) == 0)) ||
((www == 2) && (strncmp("GET /stats ", buf, 11) == 0))) {
char *p;
X509 *peer = NULL;
STACK_OF(SSL_CIPHER) *sk;
static const char *space = " ";
if (www == 1 && strncmp("GET /reneg", buf, 10) == 0) {
if (strncmp("GET /renegcert", buf, 14) == 0)
SSL_set_verify(con,
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
NULL);
i = SSL_renegotiate(con);
BIO_printf(bio_s_out, "SSL_renegotiate -> %d\n", i);
/* Send the HelloRequest */
i = SSL_do_handshake(con);
if (i <= 0) {
BIO_printf(bio_s_out, "SSL_do_handshake() Retval %d\n",
SSL_get_error(con, i));
ERR_print_errors(bio_err);
goto err;
}
/* Wait for a ClientHello to come back */
FD_ZERO(&readfds);
openssl_fdset(s, &readfds);
i = select(width, (void *)&readfds, NULL, NULL, NULL);
if (i <= 0 || !FD_ISSET(s, &readfds)) {
BIO_printf(bio_s_out,
"Error waiting for client response\n");
ERR_print_errors(bio_err);
goto err;
}
/*
* We're not actually expecting any data here and we ignore
* any that is sent. This is just to force the handshake that
* we're expecting to come from the client. If they haven't
* sent one there's not much we can do.
*/
BIO_gets(io, buf, bufsize - 1);
}
BIO_puts(io,
"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
BIO_puts(io, "<HTML><BODY BGCOLOR=\"#ffffff\">\n");
BIO_puts(io, "<pre>\n");
/* BIO_puts(io, OpenSSL_version(OPENSSL_VERSION)); */
BIO_puts(io, "\n");
for (i = 0; i < local_argc; i++) {
const char *myp;
for (myp = local_argv[i]; *myp; myp++)
switch (*myp) {
case '<':
BIO_puts(io, "&lt;");
break;
case '>':
BIO_puts(io, "&gt;");
break;
case '&':
BIO_puts(io, "&amp;");
break;
default:
BIO_write(io, myp, 1);
break;
}
BIO_write(io, " ", 1);
}
BIO_puts(io, "\n");
BIO_printf(io,
"Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(con) ?
"" : " NOT");
/*
* The following is evil and should not really be done
*/
BIO_printf(io, "Ciphers supported in s_server binary\n");
sk = SSL_get_ciphers(con);
j = sk_SSL_CIPHER_num(sk);
for (i = 0; i < j; i++) {
c = sk_SSL_CIPHER_value(sk, i);
BIO_printf(io, "%-11s:%-25s ",
SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
if ((((i + 1) % 2) == 0) && (i + 1 != j))
BIO_puts(io, "\n");
}
BIO_puts(io, "\n");
p = SSL_get_shared_ciphers(con, buf, bufsize);
if (p != NULL) {
BIO_printf(io,
"---\nCiphers common between both SSL end points:\n");
j = i = 0;
while (*p) {
if (*p == ':') {
BIO_write(io, space, 26 - j);
i++;
j = 0;
BIO_write(io, ((i % 3) ? " " : "\n"), 1);
} else {
BIO_write(io, p, 1);
j++;
}
p++;
}
BIO_puts(io, "\n");
}
ssl_print_sigalgs(io, con);
#ifndef OPENSSL_NO_EC
ssl_print_groups(io, con, 0);
#endif
print_ca_names(io, con);
BIO_printf(io, (SSL_session_reused(con)
? "---\nReused, " : "---\nNew, "));
c = SSL_get_current_cipher(con);
BIO_printf(io, "%s, Cipher is %s\n",
SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
SSL_SESSION_print(io, SSL_get_session(con));
BIO_printf(io, "---\n");
print_stats(io, SSL_get_SSL_CTX(con));
BIO_printf(io, "---\n");
peer = SSL_get_peer_certificate(con);
if (peer != NULL) {
BIO_printf(io, "Client certificate\n");
X509_print(io, peer);
PEM_write_bio_X509(io, peer);
X509_free(peer);
peer = NULL;
} else {
BIO_puts(io, "no client certificate available\n");
}
BIO_puts(io, "</pre></BODY></HTML>\r\n\r\n");
break;
} else if ((www == 2 || www == 3)
&& (strncmp("GET /", buf, 5) == 0)) {
BIO *file;
char *p, *e;
static const char *text =
"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n";
/* skip the '/' */
p = &(buf[5]);
dot = 1;
for (e = p; *e != '\0'; e++) {
if (e[0] == ' ')
break;
switch (dot) {
case 1:
dot = (e[0] == '.') ? 2 : 0;
break;
case 2:
dot = (e[0] == '.') ? 3 : 0;
break;
case 3:
dot = (e[0] == '/') ? -1 : 0;
break;
}
if (dot == 0)
dot = (e[0] == '/') ? 1 : 0;
}
dot = (dot == 3) || (dot == -1); /* filename contains ".."
* component */
if (*e == '\0') {
BIO_puts(io, text);
BIO_printf(io, "'%s' is an invalid file name\r\n", p);
break;
}
*e = '\0';
if (dot) {
BIO_puts(io, text);
BIO_printf(io, "'%s' contains '..' reference\r\n", p);
break;
}
if (*p == '/') {
BIO_puts(io, text);
BIO_printf(io, "'%s' is an invalid path\r\n", p);
break;
}
/* if a directory, do the index thang */
if (app_isdir(p) > 0) {
BIO_puts(io, text);
BIO_printf(io, "'%s' is a directory\r\n", p);
break;
}
if ((file = BIO_new_file(p, "r")) == NULL) {
BIO_puts(io, text);
BIO_printf(io, "Error opening '%s'\r\n", p);
ERR_print_errors(io);
break;
}
if (!s_quiet)
BIO_printf(bio_err, "FILE:%s\n", p);
if (www == 2) {
i = strlen(p);
if (((i > 5) && (strcmp(&(p[i - 5]), ".html") == 0)) ||
((i > 4) && (strcmp(&(p[i - 4]), ".php") == 0)) ||
((i > 4) && (strcmp(&(p[i - 4]), ".htm") == 0)))
BIO_puts(io,
"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
else
BIO_puts(io,
"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
}
/* send the file */
for (;;) {
i = BIO_read(file, buf, bufsize);
if (i <= 0)
break;
#ifdef RENEG
total_bytes += i;
BIO_printf(bio_err, "%d\n", i);
if (total_bytes > 3 * 1024) {
total_bytes = 0;
BIO_printf(bio_err, "RENEGOTIATE\n");
SSL_renegotiate(con);
}
#endif
for (j = 0; j < i;) {
#ifdef RENEG
static count = 0;
if (++count == 13) {
SSL_renegotiate(con);
}
#endif
k = BIO_write(io, &(buf[j]), i - j);
if (k <= 0) {
if (!BIO_should_retry(io)
&& !SSL_waiting_for_async(con))
goto write_error;
else {
BIO_printf(bio_s_out, "rwrite W BLOCK\n");
}
} else {
j += k;
}
}
}
write_error:
BIO_free(file);
break;
}
}
for (;;) {
i = (int)BIO_flush(io);
if (i <= 0) {
if (!BIO_should_retry(io))
break;
} else
break;
}
end:
/* make sure we re-use sessions */
SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
err:
OPENSSL_free(buf);
BIO_free_all(io);
return ret;
}
static int rev_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;
int i;
int ret = 1;
SSL *con;
BIO *io, *ssl_bio, *sbio;
buf = app_malloc(bufsize, "server rev buffer");
io = BIO_new(BIO_f_buffer());
ssl_bio = BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL))
goto err;
/* lets make the output buffer a reasonable size */
if (!BIO_set_write_buffer_size(io, bufsize))
goto err;
if ((con = SSL_new(ctx)) == NULL)
goto err;
if (s_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_s_out);
}
if (context != NULL
&& !SSL_set_session_id_context(con, context,
strlen((char *)context))) {
SSL_free(con);
ERR_print_errors(bio_err);
goto err;
}
sbio = BIO_new_socket(s, BIO_NOCLOSE);
SSL_set_bio(con, sbio, sbio);
SSL_set_accept_state(con);
/* No need to free |con| after this. Done by BIO_free(ssl_bio) */
BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
BIO_push(io, ssl_bio);
#ifdef CHARSET_EBCDIC
io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
#endif
if (s_debug) {
BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (s_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_s_msg ? bio_s_msg : bio_s_out);
}
for (;;) {
i = BIO_do_handshake(io);
if (i > 0)
break;
if (!BIO_should_retry(io)) {
BIO_puts(bio_err, "CONNECTION FAILURE\n");
ERR_print_errors(bio_err);
goto end;
}
#ifndef OPENSSL_NO_SRP
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during accept\n");
SRP_user_pwd_free(srp_callback_parm.user);
srp_callback_parm.user =
SRP_VBASE_get1_by_user(srp_callback_parm.vb,
srp_callback_parm.login);
if (srp_callback_parm.user)
BIO_printf(bio_s_out, "LOOKUP done %s\n",
srp_callback_parm.user->info);
else
BIO_printf(bio_s_out, "LOOKUP not successful\n");
continue;
}
#endif
}
BIO_printf(bio_err, "CONNECTION ESTABLISHED\n");
print_ssl_summary(con);
for (;;) {
i = BIO_gets(io, buf, bufsize - 1);
if (i < 0) { /* error */
if (!BIO_should_retry(io)) {
if (!s_quiet)
ERR_print_errors(bio_err);
goto err;
} else {
BIO_printf(bio_s_out, "read R BLOCK\n");
#ifndef OPENSSL_NO_SRP
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
SRP_user_pwd_free(srp_callback_parm.user);
srp_callback_parm.user =
SRP_VBASE_get1_by_user(srp_callback_parm.vb,
srp_callback_parm.login);
if (srp_callback_parm.user)
BIO_printf(bio_s_out, "LOOKUP done %s\n",
srp_callback_parm.user->info);
else
BIO_printf(bio_s_out, "LOOKUP not successful\n");
continue;
}
#endif
#if !defined(OPENSSL_SYS_MSDOS)
sleep(1);
#endif
continue;
}
} else if (i == 0) { /* end of input */
ret = 1;
BIO_printf(bio_err, "CONNECTION CLOSED\n");
goto end;
} else {
char *p = buf + i - 1;
while (i && (*p == '\n' || *p == '\r')) {
p--;
i--;
}
if (!s_ign_eof && (i == 5) && (strncmp(buf, "CLOSE", 5) == 0)) {
ret = 1;
BIO_printf(bio_err, "CONNECTION CLOSED\n");
goto end;
}
BUF_reverse((unsigned char *)buf, NULL, i);
buf[i] = '\n';
BIO_write(io, buf, i + 1);
for (;;) {
i = BIO_flush(io);
if (i > 0)
break;
if (!BIO_should_retry(io))
goto end;
}
}
}
end:
/* make sure we re-use sessions */
SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
err:
OPENSSL_free(buf);
BIO_free_all(io);
return ret;
}
#define MAX_SESSION_ID_ATTEMPTS 10
static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len)
{
unsigned int count = 0;
do {
if (RAND_bytes(id, *id_len) <= 0)
return 0;
/*
* 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;
}
/*
* By default s_server uses an in-memory cache which caches SSL_SESSION
* structures without any serialisation. This hides some bugs which only
* become apparent in deployed servers. By implementing a basic external
* session cache some issues can be debugged using s_server.
*/
typedef struct simple_ssl_session_st {
unsigned char *id;
unsigned int idlen;
unsigned char *der;
int derlen;
struct simple_ssl_session_st *next;
} simple_ssl_session;
static simple_ssl_session *first = NULL;
static int add_session(SSL *ssl, SSL_SESSION *session)
{
simple_ssl_session *sess = app_malloc(sizeof(*sess), "get session");
unsigned char *p;
SSL_SESSION_get_id(session, &sess->idlen);
sess->derlen = i2d_SSL_SESSION(session, NULL);
if (sess->derlen < 0) {
BIO_printf(bio_err, "Error encoding session\n");
OPENSSL_free(sess);
return 0;
}
sess->id = OPENSSL_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen);
sess->der = app_malloc(sess->derlen, "get session buffer");
if (!sess->id) {
BIO_printf(bio_err, "Out of memory adding to external cache\n");
OPENSSL_free(sess->id);
OPENSSL_free(sess->der);
OPENSSL_free(sess);
return 0;
}
p = sess->der;
/* Assume it still works. */
if (i2d_SSL_SESSION(session, &p) != sess->derlen) {
BIO_printf(bio_err, "Unexpected session encoding length\n");
OPENSSL_free(sess->id);
OPENSSL_free(sess->der);
OPENSSL_free(sess);
return 0;
}
sess->next = first;
first = sess;
BIO_printf(bio_err, "New session added to external cache\n");
return 0;
}
static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen,
int *do_copy)
{
simple_ssl_session *sess;
*do_copy = 0;
for (sess = first; sess; sess = sess->next) {
if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) {
const unsigned char *p = sess->der;
BIO_printf(bio_err, "Lookup session: cache hit\n");
return d2i_SSL_SESSION(NULL, &p, sess->derlen);
}
}
BIO_printf(bio_err, "Lookup session: cache miss\n");
return NULL;
}
static void del_session(SSL_CTX *sctx, SSL_SESSION *session)
{
simple_ssl_session *sess, *prev = NULL;
const unsigned char *id;
unsigned int idlen;
id = SSL_SESSION_get_id(session, &idlen);
for (sess = first; sess; sess = sess->next) {
if (idlen == sess->idlen && !memcmp(sess->id, id, idlen)) {
if (prev)
prev->next = sess->next;
else
first = sess->next;
OPENSSL_free(sess->id);
OPENSSL_free(sess->der);
OPENSSL_free(sess);
return;
}
prev = sess;
}
}
static void init_session_cache_ctx(SSL_CTX *sctx)
{
SSL_CTX_set_session_cache_mode(sctx,
SSL_SESS_CACHE_NO_INTERNAL |
SSL_SESS_CACHE_SERVER);
SSL_CTX_sess_set_new_cb(sctx, add_session);
SSL_CTX_sess_set_get_cb(sctx, get_session);
SSL_CTX_sess_set_remove_cb(sctx, del_session);
}
static void free_sessions(void)
{
simple_ssl_session *sess, *tsess;
for (sess = first; sess;) {
OPENSSL_free(sess->id);
OPENSSL_free(sess->der);
tsess = sess;
sess = sess->next;
OPENSSL_free(tsess);
}
first = NULL;
}
#endif /* OPENSSL_NO_SOCK */
diff --git a/apps/speed.c b/apps/speed.c
index a4879179e414..40e990408ab9 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -1,3691 +1,3691 @@
/*
* Copyright 1995-2018 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)
# 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
#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},
{"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},
{"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},
{"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},
{"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},
/* 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},
{"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;
}
}
}
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;
}
}
}
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;
}
}
}
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;
}
}
}
/* 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);
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);
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 < EC_NUM; testnum++)
+ 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/apps/x509.c b/apps/x509.c
index d40960c0b93f..81291a9a4f90 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -1,1196 +1,1196 @@
/*
* Copyright 1995-2018 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/bio.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
#undef POSTFIX
#define POSTFIX ".srl"
#define DEF_DAYS 30
static int callb(int ok, X509_STORE_CTX *ctx);
static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
const EVP_MD *digest, CONF *conf, const char *section,
int preserve_dates);
static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
X509 *x, X509 *xca, EVP_PKEY *pkey,
STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile,
int create, int days, int clrext, CONF *conf,
const char *section, ASN1_INTEGER *sno, int reqfile,
int preserve_dates);
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts);
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM,
OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA,
OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY,
OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT,
OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL,
OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH,
OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES,
OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST,
OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST,
OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
OPT_SUBJECT_HASH_OLD,
OPT_ISSUER_HASH_OLD,
OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
OPT_R_ENUM, OPT_EXT
} OPTION_CHOICE;
const OPTIONS x509_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"inform", OPT_INFORM, 'f',
- "Input format - default PEM (one of DER, NET or PEM)"},
+ "Input format - default PEM (one of DER or PEM)"},
{"in", OPT_IN, '<', "Input file - default stdin"},
{"outform", OPT_OUTFORM, 'f',
- "Output format - default PEM (one of DER, NET or PEM)"},
+ "Output format - default PEM (one of DER or PEM)"},
{"out", OPT_OUT, '>', "Output file - default stdout"},
{"keyform", OPT_KEYFORM, 'F', "Private key format - default PEM"},
{"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"},
{"serial", OPT_SERIAL, '-', "Print serial number value"},
{"subject_hash", OPT_HASH, '-', "Print subject hash value"},
{"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
{"hash", OPT_HASH, '-', "Synonym for -subject_hash"},
{"subject", OPT_SUBJECT, '-', "Print subject DN"},
{"issuer", OPT_ISSUER, '-', "Print issuer DN"},
{"email", OPT_EMAIL, '-', "Print email address(es)"},
{"startdate", OPT_STARTDATE, '-', "Set notBefore field"},
{"enddate", OPT_ENDDATE, '-', "Set notAfter field"},
{"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
{"dates", OPT_DATES, '-', "Both Before and After dates"},
{"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
{"pubkey", OPT_PUBKEY, '-', "Output the public key"},
{"fingerprint", OPT_FINGERPRINT, '-',
"Print the certificate fingerprint"},
{"alias", OPT_ALIAS, '-', "Output certificate alias"},
{"noout", OPT_NOOUT, '-', "No output, just status"},
{"nocert", OPT_NOCERT, '-', "No certificate output"},
{"ocspid", OPT_OCSPID, '-',
"Print OCSP hash values for the subject name and public key"},
{"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"},
{"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"},
{"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
{"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"},
{"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
{"addreject", OPT_ADDREJECT, 's',
"Reject certificate for a given purpose"},
{"setalias", OPT_SETALIAS, 's', "Set certificate alias"},
{"days", OPT_DAYS, 'n',
"How long till expiry of a signed certificate - def 30 days"},
{"checkend", OPT_CHECKEND, 'M',
"Check whether the cert expires in the next arg seconds"},
{OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"},
{"signkey", OPT_SIGNKEY, '<', "Self sign cert with arg"},
{"x509toreq", OPT_X509TOREQ, '-',
"Output a certification request object"},
{"req", OPT_REQ, '-', "Input is a certificate request, sign and output"},
{"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"},
{"CAkey", OPT_CAKEY, 's',
"The CA key, must be PEM format; if not in CAfile"},
{"CAcreateserial", OPT_CACREATESERIAL, '-',
"Create serial number file if it does not exist"},
{"CAserial", OPT_CASERIAL, 's', "Serial file"},
{"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
{"text", OPT_TEXT, '-', "Print the certificate in text form"},
{"ext", OPT_EXT, 's', "Print various X509V3 extensions"},
{"C", OPT_C, '-', "Print out C code forms"},
{"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"},
OPT_R_OPTIONS,
{"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"},
{"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
{"certopt", OPT_CERTOPT, 's', "Various certificate text options"},
{"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"},
{"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"},
{"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"},
{"CAform", OPT_CAFORM, 'F', "CA format - default PEM"},
{"CAkeyform", OPT_CAKEYFORM, 'f', "CA key format - default PEM"},
{"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
{"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the Key to put inside certificate"},
{"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"},
{"clrreject", OPT_CLRREJECT, '-',
"Clears all the prohibited or rejected uses of the certificate"},
{"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"},
{"", OPT_MD, '-', "Any supported digest"},
#ifndef OPENSSL_NO_MD5
{"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
"Print old-style (MD5) issuer hash value"},
{"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
"Print old-style (MD5) subject hash value"},
#endif
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"},
{NULL}
};
int x509_main(int argc, char **argv)
{
ASN1_INTEGER *sno = NULL;
ASN1_OBJECT *objtmp = NULL;
BIO *out = NULL;
CONF *extconf = NULL;
EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
STACK_OF(OPENSSL_STRING) *sigopts = NULL;
X509 *x = NULL, *xca = NULL;
X509_REQ *req = NULL, *rq = NULL;
X509_STORE *ctx = NULL;
const EVP_MD *digest = NULL;
char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL;
char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
char *prog;
int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
int fingerprint = 0, reqfile = 0, checkend = 0;
int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0;
int enddate = 0;
time_t checkoffset = 0;
unsigned long certflag = 0;
int preserve_dates = 0;
OPTION_CHOICE o;
ENGINE *e = NULL;
#ifndef OPENSSL_NO_MD5
int subject_hash_old = 0, issuer_hash_old = 0;
#endif
ctx = X509_STORE_new();
if (ctx == NULL)
goto end;
X509_STORE_set_verify_cb(ctx, callb);
prog = opt_init(argc, argv, x509_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(x509_options);
ret = 0;
goto end;
case OPT_INFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
goto opthelp;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUTFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
goto opthelp;
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
goto opthelp;
break;
case OPT_CAFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
goto opthelp;
break;
case OPT_CAKEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
goto opthelp;
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_REQ:
reqfile = 1;
break;
case OPT_SIGOPT:
if (!sigopts)
sigopts = sk_OPENSSL_STRING_new_null();
if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto opthelp;
break;
case OPT_DAYS:
if (preserve_dates)
goto opthelp;
days = atoi(opt_arg());
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_EXTFILE:
extfile = opt_arg();
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_EXTENSIONS:
extsect = opt_arg();
break;
case OPT_SIGNKEY:
keyfile = opt_arg();
sign_flag = ++num;
break;
case OPT_CA:
CAfile = opt_arg();
CA_flag = ++num;
break;
case OPT_CAKEY:
CAkeyfile = opt_arg();
break;
case OPT_CASERIAL:
CAserial = opt_arg();
break;
case OPT_SET_SERIAL:
if (sno != NULL) {
BIO_printf(bio_err, "Serial number supplied twice\n");
goto opthelp;
}
if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
goto opthelp;
break;
case OPT_FORCE_PUBKEY:
fkeyfile = opt_arg();
break;
case OPT_ADDTRUST:
if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
BIO_printf(bio_err,
"%s: Invalid trust object value %s\n",
prog, opt_arg());
goto opthelp;
}
if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
goto end;
sk_ASN1_OBJECT_push(trust, objtmp);
objtmp = NULL;
trustout = 1;
break;
case OPT_ADDREJECT:
if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
BIO_printf(bio_err,
"%s: Invalid reject object value %s\n",
prog, opt_arg());
goto opthelp;
}
if (reject == NULL
&& (reject = sk_ASN1_OBJECT_new_null()) == NULL)
goto end;
sk_ASN1_OBJECT_push(reject, objtmp);
objtmp = NULL;
trustout = 1;
break;
case OPT_SETALIAS:
alias = opt_arg();
trustout = 1;
break;
case OPT_CERTOPT:
if (!set_cert_ex(&certflag, opt_arg()))
goto opthelp;
break;
case OPT_NAMEOPT:
if (!set_nameopt(opt_arg()))
goto opthelp;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_C:
C = ++num;
break;
case OPT_EMAIL:
email = ++num;
break;
case OPT_OCSP_URI:
ocsp_uri = ++num;
break;
case OPT_SERIAL:
serial = ++num;
break;
case OPT_NEXT_SERIAL:
next_serial = ++num;
break;
case OPT_MODULUS:
modulus = ++num;
break;
case OPT_PUBKEY:
pubkey = ++num;
break;
case OPT_X509TOREQ:
x509req = ++num;
break;
case OPT_TEXT:
text = ++num;
break;
case OPT_SUBJECT:
subject = ++num;
break;
case OPT_ISSUER:
issuer = ++num;
break;
case OPT_FINGERPRINT:
fingerprint = ++num;
break;
case OPT_HASH:
subject_hash = ++num;
break;
case OPT_ISSUER_HASH:
issuer_hash = ++num;
break;
case OPT_PURPOSE:
pprint = ++num;
break;
case OPT_STARTDATE:
startdate = ++num;
break;
case OPT_ENDDATE:
enddate = ++num;
break;
case OPT_NOOUT:
noout = ++num;
break;
case OPT_EXT:
ext = ++num;
exts = opt_arg();
break;
case OPT_NOCERT:
nocert = 1;
break;
case OPT_TRUSTOUT:
trustout = 1;
break;
case OPT_CLRTRUST:
clrtrust = ++num;
break;
case OPT_CLRREJECT:
clrreject = ++num;
break;
case OPT_ALIAS:
aliasout = ++num;
break;
case OPT_CACREATESERIAL:
CA_createserial = ++num;
break;
case OPT_CLREXT:
clrext = 1;
break;
case OPT_OCSPID:
ocspid = ++num;
break;
case OPT_BADSIG:
badsig = 1;
break;
#ifndef OPENSSL_NO_MD5
case OPT_SUBJECT_HASH_OLD:
subject_hash_old = ++num;
break;
case OPT_ISSUER_HASH_OLD:
issuer_hash_old = ++num;
break;
#else
case OPT_SUBJECT_HASH_OLD:
case OPT_ISSUER_HASH_OLD:
break;
#endif
case OPT_DATES:
startdate = ++num;
enddate = ++num;
break;
case OPT_CHECKEND:
checkend = 1;
{
intmax_t temp = 0;
if (!opt_imax(opt_arg(), &temp))
goto opthelp;
checkoffset = (time_t)temp;
if ((intmax_t)checkoffset != temp) {
BIO_printf(bio_err, "%s: checkend time out of range %s\n",
prog, opt_arg());
goto opthelp;
}
}
break;
case OPT_CHECKHOST:
checkhost = opt_arg();
break;
case OPT_CHECKEMAIL:
checkemail = opt_arg();
break;
case OPT_CHECKIP:
checkip = opt_arg();
break;
case OPT_PRESERVE_DATES:
if (days != DEF_DAYS)
goto opthelp;
preserve_dates = 1;
break;
case OPT_MD:
if (!opt_md(opt_unknown(), &digest))
goto opthelp;
}
}
argc = opt_num_rest();
argv = opt_rest();
if (argc != 0) {
BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
goto opthelp;
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
if (!X509_STORE_set_default_paths(ctx)) {
ERR_print_errors(bio_err);
goto end;
}
if (fkeyfile != NULL) {
fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
if (fkey == NULL)
goto end;
}
if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
CAkeyfile = CAfile;
} else if ((CA_flag) && (CAkeyfile == NULL)) {
BIO_printf(bio_err,
"need to specify a CAkey if using the CA command\n");
goto end;
}
if (extfile != NULL) {
X509V3_CTX ctx2;
if ((extconf = app_load_config(extfile)) == NULL)
goto end;
if (extsect == NULL) {
extsect = NCONF_get_string(extconf, "default", "extensions");
if (extsect == NULL) {
ERR_clear_error();
extsect = "default";
}
}
X509V3_set_ctx_test(&ctx2);
X509V3_set_nconf(&ctx2, extconf);
if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
BIO_printf(bio_err,
"Error Loading extension section %s\n", extsect);
ERR_print_errors(bio_err);
goto end;
}
}
if (reqfile) {
EVP_PKEY *pkey;
BIO *in;
if (!sign_flag && !CA_flag) {
BIO_printf(bio_err, "We need a private key to sign with\n");
goto end;
}
in = bio_open_default(infile, 'r', informat);
if (in == NULL)
goto end;
req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
BIO_free(in);
if (req == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
BIO_printf(bio_err, "error unpacking public key\n");
goto end;
}
i = X509_REQ_verify(req, pkey);
if (i < 0) {
BIO_printf(bio_err, "Signature verification error\n");
ERR_print_errors(bio_err);
goto end;
}
if (i == 0) {
BIO_printf(bio_err,
"Signature did not match the certificate request\n");
goto end;
} else {
BIO_printf(bio_err, "Signature ok\n");
}
print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
get_nameopt());
if ((x = X509_new()) == NULL)
goto end;
if (sno == NULL) {
sno = ASN1_INTEGER_new();
if (sno == NULL || !rand_serial(NULL, sno))
goto end;
if (!X509_set_serialNumber(x, sno))
goto end;
ASN1_INTEGER_free(sno);
sno = NULL;
} else if (!X509_set_serialNumber(x, sno)) {
goto end;
}
if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
goto end;
if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
goto end;
if (!set_cert_times(x, NULL, NULL, days))
goto end;
if (fkey != NULL) {
X509_set_pubkey(x, fkey);
} else {
pkey = X509_REQ_get0_pubkey(req);
X509_set_pubkey(x, pkey);
}
} else {
x = load_cert(infile, informat, "Certificate");
}
if (x == NULL)
goto end;
if (CA_flag) {
xca = load_cert(CAfile, CAformat, "CA Certificate");
if (xca == NULL)
goto end;
}
out = bio_open_default(outfile, 'w', outformat);
if (out == NULL)
goto end;
if (!noout || text || next_serial)
OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
if (alias)
X509_alias_set1(x, (unsigned char *)alias, -1);
if (clrtrust)
X509_trust_clear(x);
if (clrreject)
X509_reject_clear(x);
if (trust != NULL) {
for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
objtmp = sk_ASN1_OBJECT_value(trust, i);
X509_add1_trust_object(x, objtmp);
}
objtmp = NULL;
}
if (reject != NULL) {
for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
objtmp = sk_ASN1_OBJECT_value(reject, i);
X509_add1_reject_object(x, objtmp);
}
objtmp = NULL;
}
if (badsig) {
const ASN1_BIT_STRING *signature;
X509_get0_signature(&signature, NULL, x);
corrupt_signature(signature);
}
if (num) {
for (i = 1; i <= num; i++) {
if (issuer == i) {
print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt());
} else if (subject == i) {
print_name(out, "subject=",
X509_get_subject_name(x), get_nameopt());
} else if (serial == i) {
BIO_printf(out, "serial=");
i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
BIO_printf(out, "\n");
} else if (next_serial == i) {
ASN1_INTEGER *ser = X509_get_serialNumber(x);
BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL);
if (!bnser)
goto end;
if (!BN_add_word(bnser, 1))
goto end;
ser = BN_to_ASN1_INTEGER(bnser, NULL);
if (!ser)
goto end;
BN_free(bnser);
i2a_ASN1_INTEGER(out, ser);
ASN1_INTEGER_free(ser);
BIO_puts(out, "\n");
} else if ((email == i) || (ocsp_uri == i)) {
int j;
STACK_OF(OPENSSL_STRING) *emlst;
if (email == i)
emlst = X509_get1_email(x);
else
emlst = X509_get1_ocsp(x);
for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
BIO_printf(out, "%s\n",
sk_OPENSSL_STRING_value(emlst, j));
X509_email_free(emlst);
} else if (aliasout == i) {
unsigned char *alstr;
alstr = X509_alias_get0(x, NULL);
if (alstr)
BIO_printf(out, "%s\n", alstr);
else
BIO_puts(out, "<No Alias>\n");
} else if (subject_hash == i) {
BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
}
#ifndef OPENSSL_NO_MD5
else if (subject_hash_old == i) {
BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
}
#endif
else if (issuer_hash == i) {
BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
}
#ifndef OPENSSL_NO_MD5
else if (issuer_hash_old == i) {
BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
}
#endif
else if (pprint == i) {
X509_PURPOSE *ptmp;
int j;
BIO_printf(out, "Certificate purposes:\n");
for (j = 0; j < X509_PURPOSE_get_count(); j++) {
ptmp = X509_PURPOSE_get0(j);
purpose_print(out, x, ptmp);
}
} else if (modulus == i) {
EVP_PKEY *pkey;
pkey = X509_get0_pubkey(x);
if (pkey == NULL) {
BIO_printf(bio_err, "Modulus=unavailable\n");
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(out, "Modulus=");
#ifndef OPENSSL_NO_RSA
if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
const BIGNUM *n;
RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL);
BN_print(out, n);
} else
#endif
#ifndef OPENSSL_NO_DSA
if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
const BIGNUM *dsapub = NULL;
DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL);
BN_print(out, dsapub);
} else
#endif
{
BIO_printf(out, "Wrong Algorithm type");
}
BIO_printf(out, "\n");
} else if (pubkey == i) {
EVP_PKEY *pkey;
pkey = X509_get0_pubkey(x);
if (pkey == NULL) {
BIO_printf(bio_err, "Error getting public key\n");
ERR_print_errors(bio_err);
goto end;
}
PEM_write_bio_PUBKEY(out, pkey);
} else if (C == i) {
unsigned char *d;
char *m;
int len;
print_name(out, "/*\n"
" * Subject: ", X509_get_subject_name(x), get_nameopt());
print_name(out, " * Issuer: ", X509_get_issuer_name(x), get_nameopt());
BIO_puts(out, " */\n");
len = i2d_X509(x, NULL);
m = app_malloc(len, "x509 name buffer");
d = (unsigned char *)m;
len = i2d_X509_NAME(X509_get_subject_name(x), &d);
print_array(out, "the_subject_name", len, (unsigned char *)m);
d = (unsigned char *)m;
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
print_array(out, "the_public_key", len, (unsigned char *)m);
d = (unsigned char *)m;
len = i2d_X509(x, &d);
print_array(out, "the_certificate", len, (unsigned char *)m);
OPENSSL_free(m);
} else if (text == i) {
X509_print_ex(out, x, get_nameopt(), certflag);
} else if (startdate == i) {
BIO_puts(out, "notBefore=");
ASN1_TIME_print(out, X509_get0_notBefore(x));
BIO_puts(out, "\n");
} else if (enddate == i) {
BIO_puts(out, "notAfter=");
ASN1_TIME_print(out, X509_get0_notAfter(x));
BIO_puts(out, "\n");
} else if (fingerprint == i) {
int j;
unsigned int n;
unsigned char md[EVP_MAX_MD_SIZE];
const EVP_MD *fdig = digest;
if (fdig == NULL)
fdig = EVP_sha1();
if (!X509_digest(x, fdig, md, &n)) {
BIO_printf(bio_err, "out of memory\n");
goto end;
}
BIO_printf(out, "%s Fingerprint=",
OBJ_nid2sn(EVP_MD_type(fdig)));
for (j = 0; j < (int)n; j++) {
BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
? '\n' : ':');
}
}
/* should be in the library */
else if ((sign_flag == i) && (x509req == 0)) {
BIO_printf(bio_err, "Getting Private key\n");
if (Upkey == NULL) {
Upkey = load_key(keyfile, keyformat, 0,
passin, e, "Private key");
if (Upkey == NULL)
goto end;
}
if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates))
goto end;
} else if (CA_flag == i) {
BIO_printf(bio_err, "Getting CA Private Key\n");
if (CAkeyfile != NULL) {
CApkey = load_key(CAkeyfile, CAkeyformat,
0, passin, e, "CA Private Key");
if (CApkey == NULL)
goto end;
}
if (!x509_certify(ctx, CAfile, digest, x, xca,
CApkey, sigopts,
CAserial, CA_createserial, days, clrext,
extconf, extsect, sno, reqfile, preserve_dates))
goto end;
} else if (x509req == i) {
EVP_PKEY *pk;
BIO_printf(bio_err, "Getting request Private Key\n");
if (keyfile == NULL) {
BIO_printf(bio_err, "no request key file specified\n");
goto end;
} else {
pk = load_key(keyfile, keyformat, 0,
passin, e, "request key");
if (pk == NULL)
goto end;
}
BIO_printf(bio_err, "Generating certificate request\n");
rq = X509_to_X509_REQ(x, pk, digest);
EVP_PKEY_free(pk);
if (rq == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (!noout) {
X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT);
PEM_write_bio_X509_REQ(out, rq);
}
noout = 1;
} else if (ocspid == i) {
X509_ocspid_print(out, x);
} else if (ext == i) {
print_x509v3_exts(out, x, exts);
}
}
}
if (checkend) {
time_t tcheck = time(NULL) + checkoffset;
if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) {
BIO_printf(out, "Certificate will expire\n");
ret = 1;
} else {
BIO_printf(out, "Certificate will not expire\n");
ret = 0;
}
goto end;
}
print_cert_checks(out, x, checkhost, checkemail, checkip);
if (noout || nocert) {
ret = 0;
goto end;
}
if (outformat == FORMAT_ASN1) {
i = i2d_X509_bio(out, x);
} else if (outformat == FORMAT_PEM) {
if (trustout)
i = PEM_write_bio_X509_AUX(out, x);
else
i = PEM_write_bio_X509(out, x);
} else {
BIO_printf(bio_err, "bad output format specified for outfile\n");
goto end;
}
if (!i) {
BIO_printf(bio_err, "unable to write certificate\n");
ERR_print_errors(bio_err);
goto end;
}
ret = 0;
end:
NCONF_free(extconf);
BIO_free_all(out);
X509_STORE_free(ctx);
X509_REQ_free(req);
X509_free(x);
X509_free(xca);
EVP_PKEY_free(Upkey);
EVP_PKEY_free(CApkey);
EVP_PKEY_free(fkey);
sk_OPENSSL_STRING_free(sigopts);
X509_REQ_free(rq);
ASN1_INTEGER_free(sno);
sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
ASN1_OBJECT_free(objtmp);
release_engine(e);
OPENSSL_free(passin);
return ret;
}
static ASN1_INTEGER *x509_load_serial(const char *CAfile,
const char *serialfile, int create)
{
char *buf = NULL;
ASN1_INTEGER *bs = NULL;
BIGNUM *serial = NULL;
if (serialfile == NULL) {
const char *p = strrchr(CAfile, '.');
size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile);
buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer");
memcpy(buf, CAfile, len);
memcpy(buf + len, POSTFIX, sizeof(POSTFIX));
serialfile = buf;
}
serial = load_serial(serialfile, create, NULL);
if (serial == NULL)
goto end;
if (!BN_add_word(serial, 1)) {
BIO_printf(bio_err, "add_word failure\n");
goto end;
}
if (!save_serial(serialfile, NULL, serial, &bs))
goto end;
end:
OPENSSL_free(buf);
BN_free(serial);
return bs;
}
static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
X509 *x, X509 *xca, EVP_PKEY *pkey,
STACK_OF(OPENSSL_STRING) *sigopts,
const char *serialfile, int create,
int days, int clrext, CONF *conf, const char *section,
ASN1_INTEGER *sno, int reqfile, int preserve_dates)
{
int ret = 0;
ASN1_INTEGER *bs = NULL;
X509_STORE_CTX *xsc = NULL;
EVP_PKEY *upkey;
upkey = X509_get0_pubkey(xca);
if (upkey == NULL) {
BIO_printf(bio_err, "Error obtaining CA X509 public key\n");
goto end;
}
EVP_PKEY_copy_parameters(upkey, pkey);
xsc = X509_STORE_CTX_new();
if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
BIO_printf(bio_err, "Error initialising X509 store\n");
goto end;
}
if (sno)
bs = sno;
else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
goto end;
/*
* NOTE: this certificate can/should be self signed, unless it was a
* certificate request in which case it is not.
*/
X509_STORE_CTX_set_cert(xsc, x);
X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
if (!reqfile && X509_verify_cert(xsc) <= 0)
goto end;
if (!X509_check_private_key(xca, pkey)) {
BIO_printf(bio_err,
"CA certificate and CA private key do not match\n");
goto end;
}
if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
goto end;
if (!X509_set_serialNumber(x, bs))
goto end;
if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
goto end;
if (clrext) {
while (X509_get_ext_count(x) > 0)
X509_delete_ext(x, 0);
}
if (conf != NULL) {
X509V3_CTX ctx2;
X509_set_version(x, 2); /* version 3 certificate */
X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
X509V3_set_nconf(&ctx2, conf);
if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
goto end;
}
if (!do_X509_sign(x, pkey, digest, sigopts))
goto end;
ret = 1;
end:
X509_STORE_CTX_free(xsc);
if (!ret)
ERR_print_errors(bio_err);
if (!sno)
ASN1_INTEGER_free(bs);
return ret;
}
static int callb(int ok, X509_STORE_CTX *ctx)
{
int err;
X509 *err_cert;
/*
* it is ok to use a self signed certificate This case will catch both
* the initial ok == 0 and the final ok == 1 calls to this function
*/
err = X509_STORE_CTX_get_error(ctx);
if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
return 1;
/*
* BAD we should have gotten an error. Normally if everything worked
* X509_STORE_CTX_get_error(ctx) will still be set to
* DEPTH_ZERO_SELF_....
*/
if (ok) {
BIO_printf(bio_err,
"error with certificate to be certified - should be self signed\n");
return 0;
} else {
err_cert = X509_STORE_CTX_get_current_cert(ctx);
print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
BIO_printf(bio_err,
"error with certificate - error %d at depth %d\n%s\n", err,
X509_STORE_CTX_get_error_depth(ctx),
X509_verify_cert_error_string(err));
return 1;
}
}
/* self sign */
static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
const EVP_MD *digest, CONF *conf, const char *section,
int preserve_dates)
{
if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
goto err;
if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
goto err;
if (!X509_set_pubkey(x, pkey))
goto err;
if (clrext) {
while (X509_get_ext_count(x) > 0)
X509_delete_ext(x, 0);
}
if (conf != NULL) {
X509V3_CTX ctx;
X509_set_version(x, 2); /* version 3 certificate */
X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
X509V3_set_nconf(&ctx, conf);
if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
goto err;
}
if (!X509_sign(x, pkey, digest))
goto err;
return 1;
err:
ERR_print_errors(bio_err);
return 0;
}
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
{
int id, i, idret;
const char *pname;
id = X509_PURPOSE_get_id(pt);
pname = X509_PURPOSE_get0_name(pt);
for (i = 0; i < 2; i++) {
idret = X509_check_purpose(cert, id, i);
BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
if (idret == 1)
BIO_printf(bio, "Yes\n");
else if (idret == 0)
BIO_printf(bio, "No\n");
else
BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
}
return 1;
}
static int parse_ext_names(char *names, const char **result)
{
char *p, *q;
int cnt = 0, len = 0;
p = q = names;
len = strlen(names);
while (q - names <= len) {
if (*q != ',' && *q != '\0') {
q++;
continue;
}
if (p != q) {
/* found */
if (result != NULL) {
result[cnt] = p;
*q = '\0';
}
cnt++;
}
p = ++q;
}
return cnt;
}
static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names)
{
const STACK_OF(X509_EXTENSION) *exts = NULL;
STACK_OF(X509_EXTENSION) *exts2 = NULL;
X509_EXTENSION *ext = NULL;
ASN1_OBJECT *obj;
int i, j, ret = 0, num, nn = 0;
const char *sn, **names = NULL;
char *tmp_ext_names = NULL;
exts = X509_get0_extensions(x);
if ((num = sk_X509_EXTENSION_num(exts)) <= 0) {
BIO_printf(bio, "No extensions in certificate\n");
ret = 1;
goto end;
}
/* parse comma separated ext name string */
if ((tmp_ext_names = OPENSSL_strdup(ext_names)) == NULL)
goto end;
if ((nn = parse_ext_names(tmp_ext_names, NULL)) == 0) {
BIO_printf(bio, "Invalid extension names: %s\n", ext_names);
goto end;
}
if ((names = OPENSSL_malloc(sizeof(char *) * nn)) == NULL)
goto end;
parse_ext_names(tmp_ext_names, names);
for (i = 0; i < num; i++) {
ext = sk_X509_EXTENSION_value(exts, i);
/* check if this ext is what we want */
obj = X509_EXTENSION_get_object(ext);
sn = OBJ_nid2sn(OBJ_obj2nid(obj));
if (sn == NULL || strcmp(sn, "UNDEF") == 0)
continue;
for (j = 0; j < nn; j++) {
if (strcmp(sn, names[j]) == 0) {
/* push the extension into a new stack */
if (exts2 == NULL
&& (exts2 = sk_X509_EXTENSION_new_null()) == NULL)
goto end;
if (!sk_X509_EXTENSION_push(exts2, ext))
goto end;
}
}
}
if (!sk_X509_EXTENSION_num(exts2)) {
BIO_printf(bio, "No extensions matched with %s\n", ext_names);
ret = 1;
goto end;
}
ret = X509V3_extensions_print(bio, NULL, exts2, 0, 0);
end:
sk_X509_EXTENSION_free(exts2);
OPENSSL_free(names);
OPENSSL_free(tmp_ext_names);
return ret;
}
diff --git a/crypto/LPdir_unix.c b/crypto/LPdir_unix.c
index 356089d7fd34..b1022895c855 100644
--- a/crypto/LPdir_unix.c
+++ b/crypto/LPdir_unix.c
@@ -1,169 +1,169 @@
/*
* Copyright 2004-2018 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
*/
/*
* This file is dual-licensed and is also available under the following
* terms:
*
* Copyright (c) 2004, 2018, Richard Levitte <richard@levitte.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#ifndef LPDIR_H
# include "LPdir.h"
#endif
#ifdef __VMS
# include <ctype.h>
#endif
/*
- * The POSIXly macro for the maximum number of characters in a file path is
+ * The POSIX macro for the maximum number of characters in a file path is
* NAME_MAX. However, some operating systems use PATH_MAX instead.
* Therefore, it seems natural to first check for PATH_MAX and use that, and
* if it doesn't exist, use NAME_MAX.
*/
#if defined(PATH_MAX)
# define LP_ENTRY_SIZE PATH_MAX
#elif defined(NAME_MAX)
# define LP_ENTRY_SIZE NAME_MAX
#endif
/*
* Of course, there's the possibility that neither PATH_MAX nor NAME_MAX
* exist. It's also possible that NAME_MAX exists but is define to a very
* small value (HP-UX offers 14), so we need to check if we got a result, and
* if it meets a minimum standard, and create or change it if not.
*/
#if !defined(LP_ENTRY_SIZE) || LP_ENTRY_SIZE<255
# undef LP_ENTRY_SIZE
# define LP_ENTRY_SIZE 255
#endif
struct LP_dir_context_st {
DIR *dir;
char entry_name[LP_ENTRY_SIZE + 1];
#ifdef __VMS
int expect_file_generations;
char previous_entry_name[LP_ENTRY_SIZE + 1];
#endif
};
const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
{
struct dirent *direntry = NULL;
if (ctx == NULL || directory == NULL) {
errno = EINVAL;
return 0;
}
errno = 0;
if (*ctx == NULL) {
*ctx = malloc(sizeof(**ctx));
if (*ctx == NULL) {
errno = ENOMEM;
return 0;
}
memset(*ctx, 0, sizeof(**ctx));
#ifdef __VMS
{
char c = directory[strlen(directory) - 1];
if (c == ']' || c == '>' || c == ':')
(*ctx)->expect_file_generations = 1;
}
#endif
(*ctx)->dir = opendir(directory);
if ((*ctx)->dir == NULL) {
int save_errno = errno; /* Probably not needed, but I'm paranoid */
free(*ctx);
*ctx = NULL;
errno = save_errno;
return 0;
}
}
#ifdef __VMS
strncpy((*ctx)->previous_entry_name, (*ctx)->entry_name,
sizeof((*ctx)->previous_entry_name));
again:
#endif
direntry = readdir((*ctx)->dir);
if (direntry == NULL) {
return 0;
}
strncpy((*ctx)->entry_name, direntry->d_name,
sizeof((*ctx)->entry_name) - 1);
(*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
#ifdef __VMS
if ((*ctx)->expect_file_generations) {
char *p = (*ctx)->entry_name + strlen((*ctx)->entry_name);
while(p > (*ctx)->entry_name && isdigit(p[-1]))
p--;
if (p > (*ctx)->entry_name && p[-1] == ';')
p[-1] = '\0';
if (strcasecmp((*ctx)->entry_name, (*ctx)->previous_entry_name) == 0)
goto again;
}
#endif
return (*ctx)->entry_name;
}
int LP_find_file_end(LP_DIR_CTX **ctx)
{
if (ctx != NULL && *ctx != NULL) {
int ret = closedir((*ctx)->dir);
free(*ctx);
switch (ret) {
case 0:
return 1;
case -1:
return 0;
default:
break;
}
}
errno = EINVAL;
return 0;
}
diff --git a/crypto/async/arch/async_posix.h b/crypto/async/arch/async_posix.h
index b07c2cb01beb..62449fe60e04 100644
--- a/crypto/async/arch/async_posix.h
+++ b/crypto/async/arch/async_posix.h
@@ -1,57 +1,58 @@
/*
* Copyright 2015-2018 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 OPENSSL_ASYNC_ARCH_ASYNC_POSIX_H
#define OPENSSL_ASYNC_ARCH_ASYNC_POSIX_H
#include <openssl/e_os2.h>
#if defined(OPENSSL_SYS_UNIX) \
&& defined(OPENSSL_THREADS) && !defined(OPENSSL_NO_ASYNC) \
&& !defined(__ANDROID__) && !defined(__OpenBSD__)
# include <unistd.h>
-# if _POSIX_VERSION >= 200112L
+# if _POSIX_VERSION >= 200112L \
+ && (_POSIX_VERSION < 200809L || defined(__GLIBC__))
# include <pthread.h>
# define ASYNC_POSIX
# define ASYNC_ARCH
# include <ucontext.h>
# include <setjmp.h>
typedef struct async_fibre_st {
ucontext_t fibre;
jmp_buf env;
int env_init;
} async_fibre;
static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r)
{
o->env_init = 1;
if (!r || !_setjmp(o->env)) {
if (n->env_init)
_longjmp(n->env, 1);
else
setcontext(&n->fibre);
}
return 1;
}
# define async_fibre_init_dispatcher(d)
int async_fibre_makecontext(async_fibre *fibre);
void async_fibre_free(async_fibre *fibre);
# endif
#endif
#endif /* OPENSSL_ASYNC_ARCH_ASYNC_POSIX_H */
diff --git a/crypto/bio/b_sock2.c b/crypto/bio/b_sock2.c
index 823732d64e1a..5d82ab22dc30 100644
--- a/crypto/bio/b_sock2.c
+++ b/crypto/bio/b_sock2.c
@@ -1,315 +1,317 @@
/*
* Copyright 2016-2018 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 <errno.h>
#include "bio_lcl.h"
#include <openssl/err.h>
#ifndef OPENSSL_NO_SOCK
# ifdef SO_MAXCONN
# define MAX_LISTEN SO_MAXCONN
# elif defined(SOMAXCONN)
# define MAX_LISTEN SOMAXCONN
# else
# define MAX_LISTEN 32
# endif
/*-
* BIO_socket - create a socket
* @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
* @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
* @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
* @options: BIO socket options (currently unused)
*
* Creates a socket. This should be called before calling any
* of BIO_connect and BIO_listen.
*
* Returns the file descriptor on success or INVALID_SOCKET on failure. On
* failure errno is set, and a status is added to the OpenSSL error stack.
*/
int BIO_socket(int domain, int socktype, int protocol, int options)
{
int sock = -1;
if (BIO_sock_init() != 1)
return INVALID_SOCKET;
sock = socket(domain, socktype, protocol);
if (sock == -1) {
SYSerr(SYS_F_SOCKET, get_last_socket_error());
BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
return INVALID_SOCKET;
}
return sock;
}
/*-
* BIO_connect - connect to an address
* @sock: the socket to connect with
* @addr: the address to connect to
* @options: BIO socket options
*
* Connects to the address using the given socket and options.
*
* Options can be a combination of the following:
* - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
* - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
* - BIO_SOCK_NODELAY: don't delay small messages.
*
* options holds BIO socket options that can be used
* You should call this for every address returned by BIO_lookup
* until the connection is successful.
*
* Returns 1 on success or 0 on failure. On failure errno is set
* and an error status is added to the OpenSSL error stack.
*/
int BIO_connect(int sock, const BIO_ADDR *addr, int options)
{
const int on = 1;
if (sock == -1) {
BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET);
return 0;
}
if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
return 0;
if (options & BIO_SOCK_KEEPALIVE) {
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
(const void *)&on, sizeof(on)) != 0) {
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE);
return 0;
}
}
if (options & BIO_SOCK_NODELAY) {
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(const void *)&on, sizeof(on)) != 0) {
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY);
return 0;
}
}
if (connect(sock, BIO_ADDR_sockaddr(addr),
BIO_ADDR_sockaddr_size(addr)) == -1) {
if (!BIO_sock_should_retry(-1)) {
SYSerr(SYS_F_CONNECT, get_last_socket_error());
BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR);
}
return 0;
}
return 1;
}
/*-
* BIO_bind - bind socket to address
* @sock: the socket to set
* @addr: local address to bind to
* @options: BIO socket options
*
* Binds to the address using the given socket and options.
*
* Options can be a combination of the following:
* - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
* for a recently closed port.
*
* When restarting the program it could be that the port is still in use. If
* you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
* It's recommended that you use this.
*/
int BIO_bind(int sock, const BIO_ADDR *addr, int options)
{
+# ifndef OPENSSL_SYS_WINDOWS
int on = 1;
+# endif
if (sock == -1) {
BIOerr(BIO_F_BIO_BIND, BIO_R_INVALID_SOCKET);
return 0;
}
# ifndef OPENSSL_SYS_WINDOWS
/*
* SO_REUSEADDR has different behavior on Windows than on
* other operating systems, don't set it there.
*/
if (options & BIO_SOCK_REUSEADDR) {
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(const void *)&on, sizeof(on)) != 0) {
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_REUSEADDR);
return 0;
}
}
# endif
if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
SYSerr(SYS_F_BIND, get_last_socket_error());
BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_BIND_SOCKET);
return 0;
}
return 1;
}
/*-
* BIO_listen - Creates a listen socket
* @sock: the socket to listen with
* @addr: local address to bind to
* @options: BIO socket options
*
* Binds to the address using the given socket and options, then
* starts listening for incoming connections.
*
* Options can be a combination of the following:
* - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
* - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
* - BIO_SOCK_NODELAY: don't delay small messages.
* - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
* for a recently closed port.
* - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
* for IPv6 addresses and not IPv4 addresses mapped to IPv6.
*
* It's recommended that you set up both an IPv6 and IPv4 listen socket, and
* then check both for new clients that connect to it. You want to set up
* the socket as non-blocking in that case since else it could hang.
*
* Not all operating systems support IPv4 addresses on an IPv6 socket, and for
* others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to
* create the IPv6 sockets to only listen for IPv6 connection.
*
* It could be that the first BIO_listen() call will listen to all the IPv6
* and IPv4 addresses and that then trying to bind to the IPv4 address will
* fail. We can't tell the difference between already listening ourself to
* it and someone else listening to it when failing and errno is EADDRINUSE, so
* it's recommended to not give an error in that case if the first call was
* successful.
*
* When restarting the program it could be that the port is still in use. If
* you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
* It's recommended that you use this.
*/
int BIO_listen(int sock, const BIO_ADDR *addr, int options)
{
int on = 1;
int socktype;
socklen_t socktype_len = sizeof(socktype);
if (sock == -1) {
BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET);
return 0;
}
if (getsockopt(sock, SOL_SOCKET, SO_TYPE,
(void *)&socktype, &socktype_len) != 0
|| socktype_len != sizeof(socktype)) {
SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error());
BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE);
return 0;
}
if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
return 0;
if (options & BIO_SOCK_KEEPALIVE) {
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
(const void *)&on, sizeof(on)) != 0) {
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE);
return 0;
}
}
if (options & BIO_SOCK_NODELAY) {
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(const void *)&on, sizeof(on)) != 0) {
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY);
return 0;
}
}
# ifdef IPV6_V6ONLY
if (BIO_ADDR_family(addr) == AF_INET6) {
/*
* Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF.
* Therefore we always have to use setsockopt here.
*/
on = options & BIO_SOCK_V6_ONLY ? 1 : 0;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
(const void *)&on, sizeof(on)) != 0) {
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY);
return 0;
}
}
# endif
if (!BIO_bind(sock, addr, options))
return 0;
if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
SYSerr(SYS_F_LISTEN, get_last_socket_error());
BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET);
return 0;
}
return 1;
}
/*-
* BIO_accept_ex - Accept new incoming connections
* @sock: the listening socket
* @addr: the BIO_ADDR to store the peer address in
* @options: BIO socket options, applied on the accepted socket.
*
*/
int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
{
socklen_t len;
int accepted_sock;
BIO_ADDR locaddr;
BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;
len = sizeof(*addr);
accepted_sock = accept(accept_sock,
BIO_ADDR_sockaddr_noconst(addr), &len);
if (accepted_sock == -1) {
if (!BIO_sock_should_retry(accepted_sock)) {
SYSerr(SYS_F_ACCEPT, get_last_socket_error());
BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR);
}
return INVALID_SOCKET;
}
if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
closesocket(accepted_sock);
return INVALID_SOCKET;
}
return accepted_sock;
}
/*-
* BIO_closesocket - Close a socket
* @sock: the socket to close
*/
int BIO_closesocket(int sock)
{
if (closesocket(sock) < 0)
return 0;
return 1;
}
#endif
diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c
index 95eef7d4bf5b..ca375b911ae8 100644
--- a/crypto/bio/bio_lib.c
+++ b/crypto/bio/bio_lib.c
@@ -1,786 +1,786 @@
/*
* Copyright 1995-2018 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 <openssl/crypto.h>
#include "bio_lcl.h"
#include "internal/cryptlib.h"
/*
* Helper macro for the callback to determine whether an operator expects a
* len parameter or not
*/
#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE || \
(o) == BIO_CB_GETS)
/*
* Helper function to work out whether to call the new style callback or the old
* one, and translate between the two.
*
* This has a long return type for consistency with the old callback. Similarly
* for the "long" used for "inret"
*/
static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
int argi, long argl, long inret, size_t *processed)
{
long ret;
int bareoper;
if (b->callback_ex != NULL)
return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed);
/* Strip off any BIO_CB_RETURN flag */
bareoper = oper & ~BIO_CB_RETURN;
/*
* We have an old style callback, so we will have to do nasty casts and
* check for overflows.
*/
if (HAS_LEN_OPER(bareoper)) {
/* In this case |len| is set, and should be used instead of |argi| */
if (len > INT_MAX)
return -1;
argi = (int)len;
}
- if (inret && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
+ if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
if (*processed > INT_MAX)
return -1;
inret = *processed;
}
ret = b->callback(b, oper, argp, argi, argl, inret);
- if (ret >= 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
+ if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
*processed = (size_t)ret;
ret = 1;
}
return ret;
}
BIO *BIO_new(const BIO_METHOD *method)
{
BIO *bio = OPENSSL_zalloc(sizeof(*bio));
if (bio == NULL) {
BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
bio->method = method;
bio->shutdown = 1;
bio->references = 1;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data))
goto err;
bio->lock = CRYPTO_THREAD_lock_new();
if (bio->lock == NULL) {
BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
goto err;
}
if (method->create != NULL && !method->create(bio)) {
BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
CRYPTO_THREAD_lock_free(bio->lock);
goto err;
}
if (method->create == NULL)
bio->init = 1;
return bio;
err:
OPENSSL_free(bio);
return NULL;
}
int BIO_free(BIO *a)
{
int ret;
if (a == NULL)
return 0;
if (CRYPTO_DOWN_REF(&a->references, &ret, a->lock) <= 0)
return 0;
REF_PRINT_COUNT("BIO", a);
if (ret > 0)
return 1;
REF_ASSERT_ISNT(ret < 0);
if (a->callback != NULL || a->callback_ex != NULL) {
ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL);
if (ret <= 0)
return ret;
}
if ((a->method != NULL) && (a->method->destroy != NULL))
a->method->destroy(a);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
CRYPTO_THREAD_lock_free(a->lock);
OPENSSL_free(a);
return 1;
}
void BIO_set_data(BIO *a, void *ptr)
{
a->ptr = ptr;
}
void *BIO_get_data(BIO *a)
{
return a->ptr;
}
void BIO_set_init(BIO *a, int init)
{
a->init = init;
}
int BIO_get_init(BIO *a)
{
return a->init;
}
void BIO_set_shutdown(BIO *a, int shut)
{
a->shutdown = shut;
}
int BIO_get_shutdown(BIO *a)
{
return a->shutdown;
}
void BIO_vfree(BIO *a)
{
BIO_free(a);
}
int BIO_up_ref(BIO *a)
{
int i;
if (CRYPTO_UP_REF(&a->references, &i, a->lock) <= 0)
return 0;
REF_PRINT_COUNT("BIO", a);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
void BIO_clear_flags(BIO *b, int flags)
{
b->flags &= ~flags;
}
int BIO_test_flags(const BIO *b, int flags)
{
return (b->flags & flags);
}
void BIO_set_flags(BIO *b, int flags)
{
b->flags |= flags;
}
BIO_callback_fn BIO_get_callback(const BIO *b)
{
return b->callback;
}
void BIO_set_callback(BIO *b, BIO_callback_fn cb)
{
b->callback = cb;
}
BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b)
{
return b->callback_ex;
}
void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
{
b->callback_ex = cb;
}
void BIO_set_callback_arg(BIO *b, char *arg)
{
b->cb_arg = arg;
}
char *BIO_get_callback_arg(const BIO *b)
{
return b->cb_arg;
}
const char *BIO_method_name(const BIO *b)
{
return b->method->name;
}
int BIO_method_type(const BIO *b)
{
return b->method->type;
}
/*
* This is essentially the same as BIO_read_ex() except that it allows
* 0 or a negative value to indicate failure (retryable or not) in the return.
* This is for compatibility with the old style BIO_read(), where existing code
* may make assumptions about the return value that it might get.
*/
static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes)
{
int ret;
if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if ((b->callback != NULL || b->callback_ex != NULL) &&
((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L,
NULL)) <= 0))
return ret;
if (!b->init) {
BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNINITIALIZED);
return -2;
}
ret = b->method->bread(b, data, dlen, readbytes);
if (ret > 0)
b->num_read += (uint64_t)*readbytes;
if (b->callback != NULL || b->callback_ex != NULL)
ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data,
dlen, 0, 0L, ret, readbytes);
/* Shouldn't happen */
if (ret > 0 && *readbytes > dlen) {
BIOerr(BIO_F_BIO_READ_INTERN, ERR_R_INTERNAL_ERROR);
return -1;
}
return ret;
}
int BIO_read(BIO *b, void *data, int dlen)
{
size_t readbytes;
int ret;
if (dlen < 0)
return 0;
ret = bio_read_intern(b, data, (size_t)dlen, &readbytes);
if (ret > 0) {
/* *readbytes should always be <= dlen */
ret = (int)readbytes;
}
return ret;
}
int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes)
{
int ret;
ret = bio_read_intern(b, data, dlen, readbytes);
if (ret > 0)
ret = 1;
else
ret = 0;
return ret;
}
static int bio_write_intern(BIO *b, const void *data, size_t dlen,
size_t *written)
{
int ret;
if (b == NULL)
return 0;
if ((b->method == NULL) || (b->method->bwrite == NULL)) {
BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if ((b->callback != NULL || b->callback_ex != NULL) &&
((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L,
NULL)) <= 0))
return ret;
if (!b->init) {
BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNINITIALIZED);
return -2;
}
ret = b->method->bwrite(b, data, dlen, written);
if (ret > 0)
b->num_write += (uint64_t)*written;
if (b->callback != NULL || b->callback_ex != NULL)
ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data,
dlen, 0, 0L, ret, written);
return ret;
}
int BIO_write(BIO *b, const void *data, int dlen)
{
size_t written;
int ret;
if (dlen < 0)
return 0;
ret = bio_write_intern(b, data, (size_t)dlen, &written);
if (ret > 0) {
/* *written should always be <= dlen */
ret = (int)written;
}
return ret;
}
int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written)
{
int ret;
ret = bio_write_intern(b, data, dlen, written);
if (ret > 0)
ret = 1;
else
ret = 0;
return ret;
}
int BIO_puts(BIO *b, const char *buf)
{
int ret;
size_t written = 0;
if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (b->callback != NULL || b->callback_ex != NULL) {
ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL);
if (ret <= 0)
return ret;
}
if (!b->init) {
BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
return -2;
}
ret = b->method->bputs(b, buf);
if (ret > 0) {
b->num_write += (uint64_t)ret;
written = ret;
ret = 1;
}
if (b->callback != NULL || b->callback_ex != NULL)
ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0,
0L, ret, &written);
if (ret > 0) {
if (written > INT_MAX) {
BIOerr(BIO_F_BIO_PUTS, BIO_R_LENGTH_TOO_LONG);
ret = -1;
} else {
ret = (int)written;
}
}
return ret;
}
int BIO_gets(BIO *b, char *buf, int size)
{
int ret;
size_t readbytes = 0;
if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (size < 0) {
BIOerr(BIO_F_BIO_GETS, BIO_R_INVALID_ARGUMENT);
return 0;
}
if (b->callback != NULL || b->callback_ex != NULL) {
ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL);
if (ret <= 0)
return ret;
}
if (!b->init) {
BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
return -2;
}
ret = b->method->bgets(b, buf, size);
if (ret > 0) {
readbytes = ret;
ret = 1;
}
if (b->callback != NULL || b->callback_ex != NULL)
ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size,
0, 0L, ret, &readbytes);
if (ret > 0) {
/* Shouldn't happen */
if (readbytes > (size_t)size)
ret = -1;
else
ret = (int)readbytes;
}
return ret;
}
int BIO_indent(BIO *b, int indent, int max)
{
if (indent < 0)
indent = 0;
if (indent > max)
indent = max;
while (indent--)
if (BIO_puts(b, " ") != 1)
return 0;
return 1;
}
long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
{
int i;
i = iarg;
return BIO_ctrl(b, cmd, larg, (char *)&i);
}
void *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
{
void *p = NULL;
if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
return NULL;
else
return p;
}
long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
{
long ret;
if (b == NULL)
return 0;
if ((b->method == NULL) || (b->method->ctrl == NULL)) {
BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (b->callback != NULL || b->callback_ex != NULL) {
ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
if (ret <= 0)
return ret;
}
ret = b->method->ctrl(b, cmd, larg, parg);
if (b->callback != NULL || b->callback_ex != NULL)
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd,
larg, ret, NULL);
return ret;
}
long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
long ret;
if (b == NULL)
return 0;
if ((b->method == NULL) || (b->method->callback_ctrl == NULL)
|| (cmd != BIO_CTRL_SET_CALLBACK)) {
BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (b->callback != NULL || b->callback_ex != NULL) {
ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L,
NULL);
if (ret <= 0)
return ret;
}
ret = b->method->callback_ctrl(b, cmd, fp);
if (b->callback != NULL || b->callback_ex != NULL)
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0,
cmd, 0, ret, NULL);
return ret;
}
/*
* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
* do; but those macros have inappropriate return type, and for interfacing
* from other programming languages, C macros aren't much of a help anyway.
*/
size_t BIO_ctrl_pending(BIO *bio)
{
return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
}
size_t BIO_ctrl_wpending(BIO *bio)
{
return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
}
/* put the 'bio' on the end of b's list of operators */
BIO *BIO_push(BIO *b, BIO *bio)
{
BIO *lb;
if (b == NULL)
return bio;
lb = b;
while (lb->next_bio != NULL)
lb = lb->next_bio;
lb->next_bio = bio;
if (bio != NULL)
bio->prev_bio = lb;
/* called to do internal processing */
BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
return b;
}
/* Remove the first and return the rest */
BIO *BIO_pop(BIO *b)
{
BIO *ret;
if (b == NULL)
return NULL;
ret = b->next_bio;
BIO_ctrl(b, BIO_CTRL_POP, 0, b);
if (b->prev_bio != NULL)
b->prev_bio->next_bio = b->next_bio;
if (b->next_bio != NULL)
b->next_bio->prev_bio = b->prev_bio;
b->next_bio = NULL;
b->prev_bio = NULL;
return ret;
}
BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
{
BIO *b, *last;
b = last = bio;
for (;;) {
if (!BIO_should_retry(b))
break;
last = b;
b = b->next_bio;
if (b == NULL)
break;
}
if (reason != NULL)
*reason = last->retry_reason;
return last;
}
int BIO_get_retry_reason(BIO *bio)
{
return bio->retry_reason;
}
void BIO_set_retry_reason(BIO *bio, int reason)
{
bio->retry_reason = reason;
}
BIO *BIO_find_type(BIO *bio, int type)
{
int mt, mask;
if (bio == NULL)
return NULL;
mask = type & 0xff;
do {
if (bio->method != NULL) {
mt = bio->method->type;
if (!mask) {
if (mt & type)
return bio;
} else if (mt == type)
return bio;
}
bio = bio->next_bio;
} while (bio != NULL);
return NULL;
}
BIO *BIO_next(BIO *b)
{
if (b == NULL)
return NULL;
return b->next_bio;
}
void BIO_set_next(BIO *b, BIO *next)
{
b->next_bio = next;
}
void BIO_free_all(BIO *bio)
{
BIO *b;
int ref;
while (bio != NULL) {
b = bio;
ref = b->references;
bio = bio->next_bio;
BIO_free(b);
/* Since ref count > 1, don't free anyone else. */
if (ref > 1)
break;
}
}
BIO *BIO_dup_chain(BIO *in)
{
BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
for (bio = in; bio != NULL; bio = bio->next_bio) {
if ((new_bio = BIO_new(bio->method)) == NULL)
goto err;
new_bio->callback = bio->callback;
new_bio->callback_ex = bio->callback_ex;
new_bio->cb_arg = bio->cb_arg;
new_bio->init = bio->init;
new_bio->shutdown = bio->shutdown;
new_bio->flags = bio->flags;
/* This will let SSL_s_sock() work with stdin/stdout */
new_bio->num = bio->num;
if (!BIO_dup_state(bio, (char *)new_bio)) {
BIO_free(new_bio);
goto err;
}
/* copy app data */
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
&bio->ex_data)) {
BIO_free(new_bio);
goto err;
}
if (ret == NULL) {
eoc = new_bio;
ret = eoc;
} else {
BIO_push(eoc, new_bio);
eoc = new_bio;
}
}
return ret;
err:
BIO_free_all(ret);
return NULL;
}
void BIO_copy_next_retry(BIO *b)
{
BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
b->retry_reason = b->next_bio->retry_reason;
}
int BIO_set_ex_data(BIO *bio, int idx, void *data)
{
return CRYPTO_set_ex_data(&(bio->ex_data), idx, data);
}
void *BIO_get_ex_data(BIO *bio, int idx)
{
return CRYPTO_get_ex_data(&(bio->ex_data), idx);
}
uint64_t BIO_number_read(BIO *bio)
{
if (bio)
return bio->num_read;
return 0;
}
uint64_t BIO_number_written(BIO *bio)
{
if (bio)
return bio->num_write;
return 0;
}
void bio_free_ex_data(BIO *bio)
{
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
}
void bio_cleanup(void)
{
#ifndef OPENSSL_NO_SOCK
bio_sock_cleanup_int();
CRYPTO_THREAD_lock_free(bio_lookup_lock);
bio_lookup_lock = NULL;
#endif
CRYPTO_THREAD_lock_free(bio_type_lock);
bio_type_lock = NULL;
}
diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c
index 4324f2412681..e9ab932ec295 100644
--- a/crypto/bio/bss_log.c
+++ b/crypto/bio/bss_log.c
@@ -1,411 +1,416 @@
/*
* Copyright 1999-2018 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
*/
/*
* Why BIO_s_log?
*
* BIO_s_log is useful for system daemons (or services under NT). It is
* one-way BIO, it sends all stuff to syslogd (on system that commonly use
* that), or event log (on NT), or OPCOM (on OpenVMS).
*
*/
#include <stdio.h>
#include <errno.h>
#include "bio_lcl.h"
#include "internal/cryptlib.h"
#if defined(OPENSSL_SYS_WINCE)
#elif defined(OPENSSL_SYS_WIN32)
#elif defined(OPENSSL_SYS_VMS)
# include <opcdef.h>
# include <descrip.h>
# include <lib$routines.h>
# include <starlet.h>
/* Some compiler options may mask the declaration of "_malloc32". */
# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
# if __INITIAL_POINTER_SIZE == 64
# pragma pointer_size save
# pragma pointer_size 32
void *_malloc32(__size_t);
# pragma pointer_size restore
# endif /* __INITIAL_POINTER_SIZE == 64 */
# endif /* __INITIAL_POINTER_SIZE && defined
* _ANSI_C_SOURCE */
#elif defined(__DJGPP__) && defined(OPENSSL_NO_SOCK)
# define NO_SYSLOG
#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
# include <syslog.h>
#endif
#include <openssl/buffer.h>
#include <openssl/err.h>
#ifndef NO_SYSLOG
# if defined(OPENSSL_SYS_WIN32)
# define LOG_EMERG 0
# define LOG_ALERT 1
# define LOG_CRIT 2
# define LOG_ERR 3
# define LOG_WARNING 4
# define LOG_NOTICE 5
# define LOG_INFO 6
# define LOG_DEBUG 7
# define LOG_DAEMON (3<<3)
# elif defined(OPENSSL_SYS_VMS)
/* On VMS, we don't really care about these, but we need them to compile */
# define LOG_EMERG 0
# define LOG_ALERT 1
# define LOG_CRIT 2
# define LOG_ERR 3
# define LOG_WARNING 4
# define LOG_NOTICE 5
# define LOG_INFO 6
# define LOG_DEBUG 7
# define LOG_DAEMON OPC$M_NM_NTWORK
# endif
static int slg_write(BIO *h, const char *buf, int num);
static int slg_puts(BIO *h, const char *str);
static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int slg_new(BIO *h);
static int slg_free(BIO *data);
static void xopenlog(BIO *bp, char *name, int level);
static void xsyslog(BIO *bp, int priority, const char *string);
static void xcloselog(BIO *bp);
static const BIO_METHOD methods_slg = {
BIO_TYPE_MEM,
"syslog",
/* TODO: Convert to new style write function */
bwrite_conv,
slg_write,
NULL, /* slg_write_old, */
NULL, /* slg_read, */
slg_puts,
NULL,
slg_ctrl,
slg_new,
slg_free,
NULL, /* slg_callback_ctrl */
};
const BIO_METHOD *BIO_s_log(void)
{
return &methods_slg;
}
static int slg_new(BIO *bi)
{
bi->init = 1;
bi->num = 0;
bi->ptr = NULL;
xopenlog(bi, "application", LOG_DAEMON);
return 1;
}
static int slg_free(BIO *a)
{
if (a == NULL)
return 0;
xcloselog(a);
return 1;
}
static int slg_write(BIO *b, const char *in, int inl)
{
int ret = inl;
char *buf;
char *pp;
int priority, i;
static const struct {
int strl;
char str[10];
int log_level;
} mapping[] = {
{
6, "PANIC ", LOG_EMERG
},
{
6, "EMERG ", LOG_EMERG
},
{
4, "EMR ", LOG_EMERG
},
{
6, "ALERT ", LOG_ALERT
},
{
4, "ALR ", LOG_ALERT
},
{
5, "CRIT ", LOG_CRIT
},
{
4, "CRI ", LOG_CRIT
},
{
6, "ERROR ", LOG_ERR
},
{
4, "ERR ", LOG_ERR
},
{
8, "WARNING ", LOG_WARNING
},
{
5, "WARN ", LOG_WARNING
},
{
4, "WAR ", LOG_WARNING
},
{
7, "NOTICE ", LOG_NOTICE
},
{
5, "NOTE ", LOG_NOTICE
},
{
4, "NOT ", LOG_NOTICE
},
{
5, "INFO ", LOG_INFO
},
{
4, "INF ", LOG_INFO
},
{
6, "DEBUG ", LOG_DEBUG
},
{
4, "DBG ", LOG_DEBUG
},
{
0, "", LOG_ERR
}
/* The default */
};
if ((buf = OPENSSL_malloc(inl + 1)) == NULL) {
BIOerr(BIO_F_SLG_WRITE, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(buf, in, inl);
buf[inl] = '\0';
i = 0;
while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
i++;
priority = mapping[i].log_level;
pp = buf + mapping[i].strl;
xsyslog(b, priority, pp);
OPENSSL_free(buf);
return ret;
}
static long slg_ctrl(BIO *b, int cmd, long num, void *ptr)
{
switch (cmd) {
case BIO_CTRL_SET:
xcloselog(b);
xopenlog(b, ptr, num);
break;
default:
break;
}
return 0;
}
static int slg_puts(BIO *bp, const char *str)
{
int n, ret;
n = strlen(str);
ret = slg_write(bp, str, n);
return ret;
}
# if defined(OPENSSL_SYS_WIN32)
static void xopenlog(BIO *bp, char *name, int level)
{
if (check_winnt())
bp->ptr = RegisterEventSourceA(NULL, name);
else
bp->ptr = NULL;
}
static void xsyslog(BIO *bp, int priority, const char *string)
{
LPCSTR lpszStrings[2];
WORD evtype = EVENTLOG_ERROR_TYPE;
char pidbuf[DECIMAL_SIZE(DWORD) + 4];
if (bp->ptr == NULL)
return;
switch (priority) {
case LOG_EMERG:
case LOG_ALERT:
case LOG_CRIT:
case LOG_ERR:
evtype = EVENTLOG_ERROR_TYPE;
break;
case LOG_WARNING:
evtype = EVENTLOG_WARNING_TYPE;
break;
case LOG_NOTICE:
case LOG_INFO:
case LOG_DEBUG:
evtype = EVENTLOG_INFORMATION_TYPE;
break;
default:
/*
* Should never happen, but set it
* as error anyway.
*/
evtype = EVENTLOG_ERROR_TYPE;
break;
}
sprintf(pidbuf, "[%lu] ", GetCurrentProcessId());
lpszStrings[0] = pidbuf;
lpszStrings[1] = string;
ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL);
}
static void xcloselog(BIO *bp)
{
if (bp->ptr)
DeregisterEventSource((HANDLE) (bp->ptr));
bp->ptr = NULL;
}
# elif defined(OPENSSL_SYS_VMS)
static int VMS_OPC_target = LOG_DAEMON;
static void xopenlog(BIO *bp, char *name, int level)
{
VMS_OPC_target = level;
}
static void xsyslog(BIO *bp, int priority, const char *string)
{
struct dsc$descriptor_s opc_dsc;
/* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */
# if __INITIAL_POINTER_SIZE == 64
# pragma pointer_size save
# pragma pointer_size 32
# define OPCDEF_TYPE __char_ptr32
# define OPCDEF_MALLOC _malloc32
# else /* __INITIAL_POINTER_SIZE == 64 */
# define OPCDEF_TYPE char *
# define OPCDEF_MALLOC OPENSSL_malloc
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
struct opcdef *opcdef_p;
# if __INITIAL_POINTER_SIZE == 64
# pragma pointer_size restore
# endif /* __INITIAL_POINTER_SIZE == 64 */
char buf[10240];
unsigned int len;
struct dsc$descriptor_s buf_dsc;
$DESCRIPTOR(fao_cmd, "!AZ: !AZ");
char *priority_tag;
switch (priority) {
case LOG_EMERG:
priority_tag = "Emergency";
break;
case LOG_ALERT:
priority_tag = "Alert";
break;
case LOG_CRIT:
priority_tag = "Critical";
break;
case LOG_ERR:
priority_tag = "Error";
break;
case LOG_WARNING:
priority_tag = "Warning";
break;
case LOG_NOTICE:
priority_tag = "Notice";
break;
case LOG_INFO:
priority_tag = "Info";
break;
case LOG_DEBUG:
priority_tag = "DEBUG";
break;
}
buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
buf_dsc.dsc$b_class = DSC$K_CLASS_S;
buf_dsc.dsc$a_pointer = buf;
buf_dsc.dsc$w_length = sizeof(buf) - 1;
lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
/* We know there's an 8-byte header. That's documented. */
opcdef_p = OPCDEF_MALLOC(8 + len);
opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
opcdef_p->opc$l_ms_rqstid = 0;
memcpy(&opcdef_p->opc$l_ms_text, buf, len);
opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
opc_dsc.dsc$b_class = DSC$K_CLASS_S;
opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p;
opc_dsc.dsc$w_length = len + 8;
sys$sndopr(opc_dsc, 0);
OPENSSL_free(opcdef_p);
}
static void xcloselog(BIO *bp)
{
}
# else /* Unix/Watt32 */
static void xopenlog(BIO *bp, char *name, int level)
{
# ifdef WATT32 /* djgpp/DOS */
openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level);
# else
openlog(name, LOG_PID | LOG_CONS, level);
# endif
}
static void xsyslog(BIO *bp, int priority, const char *string)
{
syslog(priority, "%s", string);
}
static void xcloselog(BIO *bp)
{
closelog();
}
# endif /* Unix */
+#else /* NO_SYSLOG */
+const BIO_METHOD *BIO_s_log(void)
+{
+ return NULL;
+}
#endif /* NO_SYSLOG */
diff --git a/crypto/bn/asm/x86_64-gcc.c b/crypto/bn/asm/x86_64-gcc.c
index d38f33716477..31839ba060fa 100644
--- a/crypto/bn/asm/x86_64-gcc.c
+++ b/crypto/bn/asm/x86_64-gcc.c
@@ -1,649 +1,643 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2018 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 "../bn_lcl.h"
#if !(defined(__GNUC__) && __GNUC__>=2)
# include "../bn_asm.c" /* kind of dirty hack for Sun Studio */
#else
/*-
* x86_64 BIGNUM accelerator version 0.1, December 2002.
*
* Implemented 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.
*
* Q. Version 0.1? It doesn't sound like Andy, he used to assign real
* versions, like 1.0...
* A. Well, that's because this code is basically a quick-n-dirty
* proof-of-concept hack. As you can see it's implemented with
* inline assembler, which means that you're bound to GCC and that
* there might be enough room for further improvement.
*
* Q. Why inline assembler?
* A. x86_64 features own ABI which I'm not familiar with. This is
* why I decided to let the compiler take care of subroutine
* prologue/epilogue as well as register allocation. For reference.
* Win64 implements different ABI for AMD64, different from Linux.
*
* Q. How much faster does it get?
* A. 'apps/openssl speed rsa dsa' output with no-asm:
*
* sign verify sign/s verify/s
* rsa 512 bits 0.0006s 0.0001s 1683.8 18456.2
* rsa 1024 bits 0.0028s 0.0002s 356.0 6407.0
* rsa 2048 bits 0.0172s 0.0005s 58.0 1957.8
* rsa 4096 bits 0.1155s 0.0018s 8.7 555.6
* sign verify sign/s verify/s
* dsa 512 bits 0.0005s 0.0006s 2100.8 1768.3
* dsa 1024 bits 0.0014s 0.0018s 692.3 559.2
* dsa 2048 bits 0.0049s 0.0061s 204.7 165.0
*
* 'apps/openssl speed rsa dsa' output with this module:
*
* sign verify sign/s verify/s
* rsa 512 bits 0.0004s 0.0000s 2767.1 33297.9
* rsa 1024 bits 0.0012s 0.0001s 867.4 14674.7
* rsa 2048 bits 0.0061s 0.0002s 164.0 5270.0
* rsa 4096 bits 0.0384s 0.0006s 26.1 1650.8
* sign verify sign/s verify/s
* dsa 512 bits 0.0002s 0.0003s 4442.2 3786.3
* dsa 1024 bits 0.0005s 0.0007s 1835.1 1497.4
* dsa 2048 bits 0.0016s 0.0020s 620.4 504.6
*
* For the reference. IA-32 assembler implementation performs
* very much like 64-bit code compiled with no-asm on the same
* machine.
*/
-# if defined(_WIN64) || !defined(__LP64__)
-# define BN_ULONG unsigned long long
-# else
-# define BN_ULONG unsigned long
-# endif
-
# undef mul
# undef mul_add
/*-
* "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
* "g"(0) let the compiler to decide where does it
* want to keep the value of zero;
*/
# define mul_add(r,a,word,carry) do { \
register BN_ULONG high,low; \
asm ("mulq %3" \
: "=a"(low),"=d"(high) \
: "a"(word),"m"(a) \
: "cc"); \
asm ("addq %2,%0; adcq %3,%1" \
: "+r"(carry),"+d"(high)\
: "a"(low),"g"(0) \
: "cc"); \
asm ("addq %2,%0; adcq %3,%1" \
: "+m"(r),"+d"(high) \
: "r"(carry),"g"(0) \
: "cc"); \
carry=high; \
} while (0)
# define mul(r,a,word,carry) do { \
register BN_ULONG high,low; \
asm ("mulq %3" \
: "=a"(low),"=d"(high) \
: "a"(word),"g"(a) \
: "cc"); \
asm ("addq %2,%0; adcq %3,%1" \
: "+r"(carry),"+d"(high)\
: "a"(low),"g"(0) \
: "cc"); \
(r)=carry, carry=high; \
} while (0)
# undef sqr
# define sqr(r0,r1,a) \
asm ("mulq %2" \
: "=a"(r0),"=d"(r1) \
: "a"(a) \
: "cc");
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w)
{
BN_ULONG c1 = 0;
if (num <= 0)
return c1;
while (num & ~3) {
mul_add(rp[0], ap[0], w, c1);
mul_add(rp[1], ap[1], w, c1);
mul_add(rp[2], ap[2], w, c1);
mul_add(rp[3], ap[3], w, c1);
ap += 4;
rp += 4;
num -= 4;
}
if (num) {
mul_add(rp[0], ap[0], w, c1);
if (--num == 0)
return c1;
mul_add(rp[1], ap[1], w, c1);
if (--num == 0)
return c1;
mul_add(rp[2], ap[2], w, c1);
return c1;
}
return c1;
}
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
{
BN_ULONG c1 = 0;
if (num <= 0)
return c1;
while (num & ~3) {
mul(rp[0], ap[0], w, c1);
mul(rp[1], ap[1], w, c1);
mul(rp[2], ap[2], w, c1);
mul(rp[3], ap[3], w, c1);
ap += 4;
rp += 4;
num -= 4;
}
if (num) {
mul(rp[0], ap[0], w, c1);
if (--num == 0)
return c1;
mul(rp[1], ap[1], w, c1);
if (--num == 0)
return c1;
mul(rp[2], ap[2], w, c1);
}
return c1;
}
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
{
if (n <= 0)
return;
while (n & ~3) {
sqr(r[0], r[1], a[0]);
sqr(r[2], r[3], a[1]);
sqr(r[4], r[5], a[2]);
sqr(r[6], r[7], a[3]);
a += 4;
r += 8;
n -= 4;
}
if (n) {
sqr(r[0], r[1], a[0]);
if (--n == 0)
return;
sqr(r[2], r[3], a[1]);
if (--n == 0)
return;
sqr(r[4], r[5], a[2]);
}
}
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
{
BN_ULONG ret, waste;
asm("divq %4":"=a"(ret), "=d"(waste)
: "a"(l), "d"(h), "r"(d)
: "cc");
return ret;
}
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int n)
{
BN_ULONG ret;
size_t i = 0;
if (n <= 0)
return 0;
asm volatile (" subq %0,%0 \n" /* clear carry */
" jmp 1f \n"
".p2align 4 \n"
"1: movq (%4,%2,8),%0 \n"
" adcq (%5,%2,8),%0 \n"
" movq %0,(%3,%2,8) \n"
" lea 1(%2),%2 \n"
" dec %1 \n"
" jnz 1b \n"
" sbbq %0,%0 \n"
:"=&r" (ret), "+c"(n), "+r"(i)
:"r"(rp), "r"(ap), "r"(bp)
:"cc", "memory");
return ret & 1;
}
# ifndef SIMICS
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int n)
{
BN_ULONG ret;
size_t i = 0;
if (n <= 0)
return 0;
asm volatile (" subq %0,%0 \n" /* clear borrow */
" jmp 1f \n"
".p2align 4 \n"
"1: movq (%4,%2,8),%0 \n"
" sbbq (%5,%2,8),%0 \n"
" movq %0,(%3,%2,8) \n"
" lea 1(%2),%2 \n"
" dec %1 \n"
" jnz 1b \n"
" sbbq %0,%0 \n"
:"=&r" (ret), "+c"(n), "+r"(i)
:"r"(rp), "r"(ap), "r"(bp)
:"cc", "memory");
return ret & 1;
}
# else
/* Simics 1.4<7 has buggy sbbq:-( */
# define BN_MASK2 0xffffffffffffffffL
BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
{
BN_ULONG t1, t2;
int c = 0;
if (n <= 0)
return (BN_ULONG)0;
for (;;) {
t1 = a[0];
t2 = b[0];
r[0] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
if (--n <= 0)
break;
t1 = a[1];
t2 = b[1];
r[1] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
if (--n <= 0)
break;
t1 = a[2];
t2 = b[2];
r[2] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
if (--n <= 0)
break;
t1 = a[3];
t2 = b[3];
r[3] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
if (--n <= 0)
break;
a += 4;
b += 4;
r += 4;
}
return c;
}
# endif
/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
/*
* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number
* c=(c2,c1,c0)
*/
/*
* Keep in mind that carrying into high part of multiplication result
* can not overflow, because it cannot be all-ones.
*/
# if 0
/* original macros are kept for reference purposes */
# define mul_add_c(a,b,c0,c1,c2) do { \
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo, hi; \
BN_UMULT_LOHI(lo,hi,ta,tb); \
c0 += lo; hi += (c0<lo)?1:0; \
c1 += hi; c2 += (c1<hi)?1:0; \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo, hi, tt; \
BN_UMULT_LOHI(lo,hi,ta,tb); \
c0 += lo; tt = hi+((c0<lo)?1:0); \
c1 += tt; c2 += (c1<tt)?1:0; \
c0 += lo; hi += (c0<lo)?1:0; \
c1 += hi; c2 += (c1<hi)?1:0; \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG ta = (a)[i]; \
BN_ULONG lo, hi; \
BN_UMULT_LOHI(lo,hi,ta,ta); \
c0 += lo; hi += (c0<lo)?1:0; \
c1 += hi; c2 += (c1<hi)?1:0; \
} while(0)
# else
# define mul_add_c(a,b,c0,c1,c2) do { \
BN_ULONG t1,t2; \
asm ("mulq %3" \
: "=a"(t1),"=d"(t2) \
: "a"(a),"m"(b) \
: "cc"); \
asm ("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0),"+r"(c1),"+r"(c2) \
: "r"(t1),"r"(t2),"g"(0) \
: "cc"); \
} while (0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG t1,t2; \
asm ("mulq %2" \
: "=a"(t1),"=d"(t2) \
: "a"(a[i]) \
: "cc"); \
asm ("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0),"+r"(c1),"+r"(c2) \
: "r"(t1),"r"(t2),"g"(0) \
: "cc"); \
} while (0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
BN_ULONG t1,t2; \
asm ("mulq %3" \
: "=a"(t1),"=d"(t2) \
: "a"(a),"m"(b) \
: "cc"); \
asm ("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0),"+r"(c1),"+r"(c2) \
: "r"(t1),"r"(t2),"g"(0) \
: "cc"); \
asm ("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0),"+r"(c1),"+r"(c2) \
: "r"(t1),"r"(t2),"g"(0) \
: "cc"); \
} while (0)
# endif
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
mul_add_c(a[0], b[0], c1, c2, c3);
r[0] = c1;
c1 = 0;
mul_add_c(a[0], b[1], c2, c3, c1);
mul_add_c(a[1], b[0], c2, c3, c1);
r[1] = c2;
c2 = 0;
mul_add_c(a[2], b[0], c3, c1, c2);
mul_add_c(a[1], b[1], c3, c1, c2);
mul_add_c(a[0], b[2], c3, c1, c2);
r[2] = c3;
c3 = 0;
mul_add_c(a[0], b[3], c1, c2, c3);
mul_add_c(a[1], b[2], c1, c2, c3);
mul_add_c(a[2], b[1], c1, c2, c3);
mul_add_c(a[3], b[0], c1, c2, c3);
r[3] = c1;
c1 = 0;
mul_add_c(a[4], b[0], c2, c3, c1);
mul_add_c(a[3], b[1], c2, c3, c1);
mul_add_c(a[2], b[2], c2, c3, c1);
mul_add_c(a[1], b[3], c2, c3, c1);
mul_add_c(a[0], b[4], c2, c3, c1);
r[4] = c2;
c2 = 0;
mul_add_c(a[0], b[5], c3, c1, c2);
mul_add_c(a[1], b[4], c3, c1, c2);
mul_add_c(a[2], b[3], c3, c1, c2);
mul_add_c(a[3], b[2], c3, c1, c2);
mul_add_c(a[4], b[1], c3, c1, c2);
mul_add_c(a[5], b[0], c3, c1, c2);
r[5] = c3;
c3 = 0;
mul_add_c(a[6], b[0], c1, c2, c3);
mul_add_c(a[5], b[1], c1, c2, c3);
mul_add_c(a[4], b[2], c1, c2, c3);
mul_add_c(a[3], b[3], c1, c2, c3);
mul_add_c(a[2], b[4], c1, c2, c3);
mul_add_c(a[1], b[5], c1, c2, c3);
mul_add_c(a[0], b[6], c1, c2, c3);
r[6] = c1;
c1 = 0;
mul_add_c(a[0], b[7], c2, c3, c1);
mul_add_c(a[1], b[6], c2, c3, c1);
mul_add_c(a[2], b[5], c2, c3, c1);
mul_add_c(a[3], b[4], c2, c3, c1);
mul_add_c(a[4], b[3], c2, c3, c1);
mul_add_c(a[5], b[2], c2, c3, c1);
mul_add_c(a[6], b[1], c2, c3, c1);
mul_add_c(a[7], b[0], c2, c3, c1);
r[7] = c2;
c2 = 0;
mul_add_c(a[7], b[1], c3, c1, c2);
mul_add_c(a[6], b[2], c3, c1, c2);
mul_add_c(a[5], b[3], c3, c1, c2);
mul_add_c(a[4], b[4], c3, c1, c2);
mul_add_c(a[3], b[5], c3, c1, c2);
mul_add_c(a[2], b[6], c3, c1, c2);
mul_add_c(a[1], b[7], c3, c1, c2);
r[8] = c3;
c3 = 0;
mul_add_c(a[2], b[7], c1, c2, c3);
mul_add_c(a[3], b[6], c1, c2, c3);
mul_add_c(a[4], b[5], c1, c2, c3);
mul_add_c(a[5], b[4], c1, c2, c3);
mul_add_c(a[6], b[3], c1, c2, c3);
mul_add_c(a[7], b[2], c1, c2, c3);
r[9] = c1;
c1 = 0;
mul_add_c(a[7], b[3], c2, c3, c1);
mul_add_c(a[6], b[4], c2, c3, c1);
mul_add_c(a[5], b[5], c2, c3, c1);
mul_add_c(a[4], b[6], c2, c3, c1);
mul_add_c(a[3], b[7], c2, c3, c1);
r[10] = c2;
c2 = 0;
mul_add_c(a[4], b[7], c3, c1, c2);
mul_add_c(a[5], b[6], c3, c1, c2);
mul_add_c(a[6], b[5], c3, c1, c2);
mul_add_c(a[7], b[4], c3, c1, c2);
r[11] = c3;
c3 = 0;
mul_add_c(a[7], b[5], c1, c2, c3);
mul_add_c(a[6], b[6], c1, c2, c3);
mul_add_c(a[5], b[7], c1, c2, c3);
r[12] = c1;
c1 = 0;
mul_add_c(a[6], b[7], c2, c3, c1);
mul_add_c(a[7], b[6], c2, c3, c1);
r[13] = c2;
c2 = 0;
mul_add_c(a[7], b[7], c3, c1, c2);
r[14] = c3;
r[15] = c1;
}
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
mul_add_c(a[0], b[0], c1, c2, c3);
r[0] = c1;
c1 = 0;
mul_add_c(a[0], b[1], c2, c3, c1);
mul_add_c(a[1], b[0], c2, c3, c1);
r[1] = c2;
c2 = 0;
mul_add_c(a[2], b[0], c3, c1, c2);
mul_add_c(a[1], b[1], c3, c1, c2);
mul_add_c(a[0], b[2], c3, c1, c2);
r[2] = c3;
c3 = 0;
mul_add_c(a[0], b[3], c1, c2, c3);
mul_add_c(a[1], b[2], c1, c2, c3);
mul_add_c(a[2], b[1], c1, c2, c3);
mul_add_c(a[3], b[0], c1, c2, c3);
r[3] = c1;
c1 = 0;
mul_add_c(a[3], b[1], c2, c3, c1);
mul_add_c(a[2], b[2], c2, c3, c1);
mul_add_c(a[1], b[3], c2, c3, c1);
r[4] = c2;
c2 = 0;
mul_add_c(a[2], b[3], c3, c1, c2);
mul_add_c(a[3], b[2], c3, c1, c2);
r[5] = c3;
c3 = 0;
mul_add_c(a[3], b[3], c1, c2, c3);
r[6] = c1;
r[7] = c2;
}
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
sqr_add_c(a, 0, c1, c2, c3);
r[0] = c1;
c1 = 0;
sqr_add_c2(a, 1, 0, c2, c3, c1);
r[1] = c2;
c2 = 0;
sqr_add_c(a, 1, c3, c1, c2);
sqr_add_c2(a, 2, 0, c3, c1, c2);
r[2] = c3;
c3 = 0;
sqr_add_c2(a, 3, 0, c1, c2, c3);
sqr_add_c2(a, 2, 1, c1, c2, c3);
r[3] = c1;
c1 = 0;
sqr_add_c(a, 2, c2, c3, c1);
sqr_add_c2(a, 3, 1, c2, c3, c1);
sqr_add_c2(a, 4, 0, c2, c3, c1);
r[4] = c2;
c2 = 0;
sqr_add_c2(a, 5, 0, c3, c1, c2);
sqr_add_c2(a, 4, 1, c3, c1, c2);
sqr_add_c2(a, 3, 2, c3, c1, c2);
r[5] = c3;
c3 = 0;
sqr_add_c(a, 3, c1, c2, c3);
sqr_add_c2(a, 4, 2, c1, c2, c3);
sqr_add_c2(a, 5, 1, c1, c2, c3);
sqr_add_c2(a, 6, 0, c1, c2, c3);
r[6] = c1;
c1 = 0;
sqr_add_c2(a, 7, 0, c2, c3, c1);
sqr_add_c2(a, 6, 1, c2, c3, c1);
sqr_add_c2(a, 5, 2, c2, c3, c1);
sqr_add_c2(a, 4, 3, c2, c3, c1);
r[7] = c2;
c2 = 0;
sqr_add_c(a, 4, c3, c1, c2);
sqr_add_c2(a, 5, 3, c3, c1, c2);
sqr_add_c2(a, 6, 2, c3, c1, c2);
sqr_add_c2(a, 7, 1, c3, c1, c2);
r[8] = c3;
c3 = 0;
sqr_add_c2(a, 7, 2, c1, c2, c3);
sqr_add_c2(a, 6, 3, c1, c2, c3);
sqr_add_c2(a, 5, 4, c1, c2, c3);
r[9] = c1;
c1 = 0;
sqr_add_c(a, 5, c2, c3, c1);
sqr_add_c2(a, 6, 4, c2, c3, c1);
sqr_add_c2(a, 7, 3, c2, c3, c1);
r[10] = c2;
c2 = 0;
sqr_add_c2(a, 7, 4, c3, c1, c2);
sqr_add_c2(a, 6, 5, c3, c1, c2);
r[11] = c3;
c3 = 0;
sqr_add_c(a, 6, c1, c2, c3);
sqr_add_c2(a, 7, 5, c1, c2, c3);
r[12] = c1;
c1 = 0;
sqr_add_c2(a, 7, 6, c2, c3, c1);
r[13] = c2;
c2 = 0;
sqr_add_c(a, 7, c3, c1, c2);
r[14] = c3;
r[15] = c1;
}
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
sqr_add_c(a, 0, c1, c2, c3);
r[0] = c1;
c1 = 0;
sqr_add_c2(a, 1, 0, c2, c3, c1);
r[1] = c2;
c2 = 0;
sqr_add_c(a, 1, c3, c1, c2);
sqr_add_c2(a, 2, 0, c3, c1, c2);
r[2] = c3;
c3 = 0;
sqr_add_c2(a, 3, 0, c1, c2, c3);
sqr_add_c2(a, 2, 1, c1, c2, c3);
r[3] = c1;
c1 = 0;
sqr_add_c(a, 2, c2, c3, c1);
sqr_add_c2(a, 3, 1, c2, c3, c1);
r[4] = c2;
c2 = 0;
sqr_add_c2(a, 3, 2, c3, c1, c2);
r[5] = c3;
c3 = 0;
sqr_add_c(a, 3, c1, c2, c3);
r[6] = c1;
r[7] = c2;
}
#endif
diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c
index 2c92d7eac9d5..c026ffcb339c 100644
--- a/crypto/bn/bn_exp.c
+++ b/crypto/bn/bn_exp.c
@@ -1,1393 +1,1393 @@
/*
* Copyright 1995-2018 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/constant_time_locl.h"
#include "bn_lcl.h"
#include <stdlib.h>
#ifdef _WIN32
# include <malloc.h>
# ifndef alloca
# define alloca _alloca
# endif
#elif defined(__GNUC__)
# ifndef alloca
# define alloca(s) __builtin_alloca((s))
# endif
#elif defined(__sun)
# include <alloca.h>
#endif
#include "rsaz_exp.h"
#undef SPARC_T4_MONT
#if defined(OPENSSL_BN_ASM_MONT) && (defined(__sparc__) || defined(__sparc))
# include "sparc_arch.h"
extern unsigned int OPENSSL_sparcv9cap_P[];
# define SPARC_T4_MONT
#endif
/* maximum precomputation table size for *variable* sliding windows */
#define TABLE_SIZE 32
/* this one works - simple but works */
int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
int i, bits, ret = 0;
BIGNUM *v, *rr;
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(a, BN_FLG_CONSTTIME) != 0) {
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
BNerr(BN_F_BN_EXP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
BN_CTX_start(ctx);
rr = ((r == a) || (r == p)) ? BN_CTX_get(ctx) : r;
v = BN_CTX_get(ctx);
if (rr == NULL || v == NULL)
goto err;
if (BN_copy(v, a) == NULL)
goto err;
bits = BN_num_bits(p);
if (BN_is_odd(p)) {
if (BN_copy(rr, a) == NULL)
goto err;
} else {
if (!BN_one(rr))
goto err;
}
for (i = 1; i < bits; i++) {
if (!BN_sqr(v, v, ctx))
goto err;
if (BN_is_bit_set(p, i)) {
if (!BN_mul(rr, rr, v, ctx))
goto err;
}
}
if (r != rr && BN_copy(r, rr) == NULL)
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
bn_check_top(r);
return ret;
}
int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
BN_CTX *ctx)
{
int ret;
bn_check_top(a);
bn_check_top(p);
bn_check_top(m);
/*-
* For even modulus m = 2^k*m_odd, it might make sense to compute
* a^p mod m_odd and a^p mod 2^k separately (with Montgomery
* exponentiation for the odd part), using appropriate exponent
* reductions, and combine the results using the CRT.
*
* For now, we use Montgomery only if the modulus is odd; otherwise,
* exponentiation using the reciprocal-based quick remaindering
* algorithm is used.
*
* (Timing obtained with expspeed.c [computations a^p mod m
* where a, p, m are of the same length: 256, 512, 1024, 2048,
* 4096, 8192 bits], compared to the running time of the
* standard algorithm:
*
* BN_mod_exp_mont 33 .. 40 % [AMD K6-2, Linux, debug configuration]
* 55 .. 77 % [UltraSparc processor, but
* debug-solaris-sparcv8-gcc conf.]
*
* BN_mod_exp_recp 50 .. 70 % [AMD K6-2, Linux, debug configuration]
* 62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]
*
* On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont
* at 2048 and more bits, but at 512 and 1024 bits, it was
* slower even than the standard algorithm!
*
* "Real" timings [linux-elf, solaris-sparcv9-gcc configurations]
* should be obtained when the new Montgomery reduction code
* has been integrated into OpenSSL.)
*/
#define MONT_MUL_MOD
#define MONT_EXP_WORD
#define RECP_MUL_MOD
#ifdef MONT_MUL_MOD
if (BN_is_odd(m)) {
# ifdef MONT_EXP_WORD
if (a->top == 1 && !a->neg
&& (BN_get_flags(p, BN_FLG_CONSTTIME) == 0)
&& (BN_get_flags(a, BN_FLG_CONSTTIME) == 0)
&& (BN_get_flags(m, BN_FLG_CONSTTIME) == 0)) {
BN_ULONG A = a->d[0];
ret = BN_mod_exp_mont_word(r, A, p, m, ctx, NULL);
} else
# endif
ret = BN_mod_exp_mont(r, a, p, m, ctx, NULL);
} else
#endif
#ifdef RECP_MUL_MOD
{
ret = BN_mod_exp_recp(r, a, p, m, ctx);
}
#else
{
ret = BN_mod_exp_simple(r, a, p, m, ctx);
}
#endif
bn_check_top(r);
return ret;
}
int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx)
{
int i, j, bits, ret = 0, wstart, wend, window, wvalue;
int start = 1;
BIGNUM *aa;
/* Table of variables obtained from 'ctx' */
BIGNUM *val[TABLE_SIZE];
BN_RECP_CTX recp;
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(a, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
BNerr(BN_F_BN_MOD_EXP_RECP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
bits = BN_num_bits(p);
if (bits == 0) {
/* x**0 mod 1, or x**0 mod -1 is still zero. */
if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(r);
} else {
ret = BN_one(r);
}
return ret;
}
BN_CTX_start(ctx);
aa = BN_CTX_get(ctx);
val[0] = BN_CTX_get(ctx);
if (val[0] == NULL)
goto err;
BN_RECP_CTX_init(&recp);
if (m->neg) {
/* ignore sign of 'm' */
if (!BN_copy(aa, m))
goto err;
aa->neg = 0;
if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0)
goto err;
} else {
if (BN_RECP_CTX_set(&recp, m, ctx) <= 0)
goto err;
}
if (!BN_nnmod(val[0], a, m, ctx))
goto err; /* 1 */
if (BN_is_zero(val[0])) {
BN_zero(r);
ret = 1;
goto err;
}
window = BN_window_bits_for_exponent_size(bits);
if (window > 1) {
if (!BN_mod_mul_reciprocal(aa, val[0], val[0], &recp, ctx))
goto err; /* 2 */
j = 1 << (window - 1);
for (i = 1; i < j; i++) {
if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
!BN_mod_mul_reciprocal(val[i], val[i - 1], aa, &recp, ctx))
goto err;
}
}
start = 1; /* This is used to avoid multiplication etc
* when there is only the value '1' in the
* buffer. */
wvalue = 0; /* The 'value' of the window */
wstart = bits - 1; /* The top bit of the window */
wend = 0; /* The bottom bit of the window */
if (!BN_one(r))
goto err;
for (;;) {
if (BN_is_bit_set(p, wstart) == 0) {
if (!start)
if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx))
goto err;
if (wstart == 0)
break;
wstart--;
continue;
}
/*
* We now have wstart on a 'set' bit, we now need to work out how bit
* a window to do. To do this we need to scan forward until the last
* set bit before the end of the window
*/
j = wstart;
wvalue = 1;
wend = 0;
for (i = 1; i < window; i++) {
if (wstart - i < 0)
break;
if (BN_is_bit_set(p, wstart - i)) {
wvalue <<= (i - wend);
wvalue |= 1;
wend = i;
}
}
/* wend is the size of the current window */
j = wend + 1;
/* add the 'bytes above' */
if (!start)
for (i = 0; i < j; i++) {
if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
if (!BN_mod_mul_reciprocal(r, r, val[wvalue >> 1], &recp, ctx))
goto err;
/* move the 'window' down further */
wstart -= wend + 1;
wvalue = 0;
start = 0;
if (wstart < 0)
break;
}
ret = 1;
err:
BN_CTX_end(ctx);
BN_RECP_CTX_free(&recp);
bn_check_top(r);
return ret;
}
int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
{
int i, j, bits, ret = 0, wstart, wend, window, wvalue;
int start = 1;
BIGNUM *d, *r;
const BIGNUM *aa;
/* Table of variables obtained from 'ctx' */
BIGNUM *val[TABLE_SIZE];
BN_MONT_CTX *mont = NULL;
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(a, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
}
bn_check_top(a);
bn_check_top(p);
bn_check_top(m);
if (!BN_is_odd(m)) {
BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
bits = BN_num_bits(p);
if (bits == 0) {
/* x**0 mod 1, or x**0 mod -1 is still zero. */
if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(rr);
} else {
ret = BN_one(rr);
}
return ret;
}
BN_CTX_start(ctx);
d = BN_CTX_get(ctx);
r = BN_CTX_get(ctx);
val[0] = BN_CTX_get(ctx);
if (val[0] == NULL)
goto err;
/*
* If this is not done, things will break in the montgomery part
*/
if (in_mont != NULL)
mont = in_mont;
else {
if ((mont = BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(mont, m, ctx))
goto err;
}
if (a->neg || BN_ucmp(a, m) >= 0) {
if (!BN_nnmod(val[0], a, m, ctx))
goto err;
aa = val[0];
} else
aa = a;
if (!bn_to_mont_fixed_top(val[0], aa, mont, ctx))
goto err; /* 1 */
window = BN_window_bits_for_exponent_size(bits);
if (window > 1) {
if (!bn_mul_mont_fixed_top(d, val[0], val[0], mont, ctx))
goto err; /* 2 */
j = 1 << (window - 1);
for (i = 1; i < j; i++) {
if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
!bn_mul_mont_fixed_top(val[i], val[i - 1], d, mont, ctx))
goto err;
}
}
start = 1; /* This is used to avoid multiplication etc
* when there is only the value '1' in the
* buffer. */
wvalue = 0; /* The 'value' of the window */
wstart = bits - 1; /* The top bit of the window */
wend = 0; /* The bottom bit of the window */
#if 1 /* by Shay Gueron's suggestion */
j = m->top; /* borrow j */
if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
if (bn_wexpand(r, j) == NULL)
goto err;
/* 2^(top*BN_BITS2) - m */
r->d[0] = (0 - m->d[0]) & BN_MASK2;
for (i = 1; i < j; i++)
r->d[i] = (~m->d[i]) & BN_MASK2;
r->top = j;
r->flags |= BN_FLG_FIXED_TOP;
} else
#endif
if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx))
goto err;
for (;;) {
if (BN_is_bit_set(p, wstart) == 0) {
if (!start) {
if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
goto err;
}
if (wstart == 0)
break;
wstart--;
continue;
}
/*
* We now have wstart on a 'set' bit, we now need to work out how bit
* a window to do. To do this we need to scan forward until the last
* set bit before the end of the window
*/
j = wstart;
wvalue = 1;
wend = 0;
for (i = 1; i < window; i++) {
if (wstart - i < 0)
break;
if (BN_is_bit_set(p, wstart - i)) {
wvalue <<= (i - wend);
wvalue |= 1;
wend = i;
}
}
/* wend is the size of the current window */
j = wend + 1;
/* add the 'bytes above' */
if (!start)
for (i = 0; i < j; i++) {
if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
if (!bn_mul_mont_fixed_top(r, r, val[wvalue >> 1], mont, ctx))
goto err;
/* move the 'window' down further */
wstart -= wend + 1;
wvalue = 0;
start = 0;
if (wstart < 0)
break;
}
/*
* Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
* removes padding [if any] and makes return value suitable for public
* API consumer.
*/
#if defined(SPARC_T4_MONT)
if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
j = mont->N.top; /* borrow j */
val[0]->d[0] = 1; /* borrow val[0] */
for (i = 1; i < j; i++)
val[0]->d[i] = 0;
val[0]->top = j;
if (!BN_mod_mul_montgomery(rr, r, val[0], mont, ctx))
goto err;
} else
#endif
if (!BN_from_montgomery(rr, r, mont, ctx))
goto err;
ret = 1;
err:
if (in_mont == NULL)
BN_MONT_CTX_free(mont);
BN_CTX_end(ctx);
bn_check_top(rr);
return ret;
}
static BN_ULONG bn_get_bits(const BIGNUM *a, int bitpos)
{
BN_ULONG ret = 0;
int wordpos;
wordpos = bitpos / BN_BITS2;
bitpos %= BN_BITS2;
if (wordpos >= 0 && wordpos < a->top) {
ret = a->d[wordpos] & BN_MASK2;
if (bitpos) {
ret >>= bitpos;
if (++wordpos < a->top)
ret |= a->d[wordpos] << (BN_BITS2 - bitpos);
}
}
return ret & BN_MASK2;
}
/*
* BN_mod_exp_mont_consttime() stores the precomputed powers in a specific
* layout so that accessing any of these table values shows the same access
* pattern as far as cache lines are concerned. The following functions are
* used to transfer a BIGNUM from/to that table.
*/
static int MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top,
unsigned char *buf, int idx,
int window)
{
int i, j;
int width = 1 << window;
BN_ULONG *table = (BN_ULONG *)buf;
if (top > b->top)
top = b->top; /* this works because 'buf' is explicitly
* zeroed */
for (i = 0, j = idx; i < top; i++, j += width) {
table[j] = b->d[i];
}
return 1;
}
static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
unsigned char *buf, int idx,
int window)
{
int i, j;
int width = 1 << window;
/*
* We declare table 'volatile' in order to discourage compiler
* from reordering loads from the table. Concern is that if
* reordered in specific manner loads might give away the
* information we are trying to conceal. Some would argue that
* compiler can reorder them anyway, but it can as well be
* argued that doing so would be violation of standard...
*/
volatile BN_ULONG *table = (volatile BN_ULONG *)buf;
if (bn_wexpand(b, top) == NULL)
return 0;
if (window <= 3) {
for (i = 0; i < top; i++, table += width) {
BN_ULONG acc = 0;
for (j = 0; j < width; j++) {
acc |= table[j] &
((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1));
}
b->d[i] = acc;
}
} else {
int xstride = 1 << (window - 2);
BN_ULONG y0, y1, y2, y3;
i = idx >> (window - 2); /* equivalent of idx / xstride */
idx &= xstride - 1; /* equivalent of idx % xstride */
y0 = (BN_ULONG)0 - (constant_time_eq_int(i,0)&1);
y1 = (BN_ULONG)0 - (constant_time_eq_int(i,1)&1);
y2 = (BN_ULONG)0 - (constant_time_eq_int(i,2)&1);
y3 = (BN_ULONG)0 - (constant_time_eq_int(i,3)&1);
for (i = 0; i < top; i++, table += width) {
BN_ULONG acc = 0;
for (j = 0; j < xstride; j++) {
acc |= ( (table[j + 0 * xstride] & y0) |
(table[j + 1 * xstride] & y1) |
(table[j + 2 * xstride] & y2) |
(table[j + 3 * xstride] & y3) )
& ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1));
}
b->d[i] = acc;
}
}
b->top = top;
b->flags |= BN_FLG_FIXED_TOP;
return 1;
}
/*
* Given a pointer value, compute the next address that is a cache line
* multiple.
*/
#define MOD_EXP_CTIME_ALIGN(x_) \
((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((size_t)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK))))
/*
* This variant of BN_mod_exp_mont() uses fixed windows and the special
* precomputation memory layout to limit data-dependency to a minimum to
* protect secret exponents (cf. the hyper-threading timing attacks pointed
* out by Colin Percival,
* http://www.daemonology.net/hyperthreading-considered-harmful/)
*/
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *in_mont)
{
int i, bits, ret = 0, window, wvalue, wmask, window0;
int top;
BN_MONT_CTX *mont = NULL;
int numPowers;
unsigned char *powerbufFree = NULL;
int powerbufLen = 0;
unsigned char *powerbuf = NULL;
BIGNUM tmp, am;
#if defined(SPARC_T4_MONT)
unsigned int t4 = 0;
#endif
bn_check_top(a);
bn_check_top(p);
bn_check_top(m);
if (!BN_is_odd(m)) {
BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
top = m->top;
/*
* Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak
* whether the top bits are zero.
*/
bits = p->top * BN_BITS2;
if (bits == 0) {
/* x**0 mod 1, or x**0 mod -1 is still zero. */
if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(rr);
} else {
ret = BN_one(rr);
}
return ret;
}
BN_CTX_start(ctx);
/*
* Allocate a montgomery context if it was not supplied by the caller. If
* this is not done, things will break in the montgomery part.
*/
if (in_mont != NULL)
mont = in_mont;
else {
if ((mont = BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(mont, m, ctx))
goto err;
}
#ifdef RSAZ_ENABLED
if (!a->neg) {
/*
* If the size of the operands allow it, perform the optimized
* RSAZ exponentiation. For further information see
* crypto/bn/rsaz_exp.c and accompanying assembly modules.
*/
if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024)
&& rsaz_avx2_eligible()) {
if (NULL == bn_wexpand(rr, 16))
goto err;
RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d,
mont->n0[0]);
rr->top = 16;
rr->neg = 0;
bn_correct_top(rr);
ret = 1;
goto err;
} else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) {
if (NULL == bn_wexpand(rr, 8))
goto err;
RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d);
rr->top = 8;
rr->neg = 0;
bn_correct_top(rr);
ret = 1;
goto err;
}
}
#endif
/* Get the window size to use with size of p. */
window = BN_window_bits_for_ctime_exponent_size(bits);
#if defined(SPARC_T4_MONT)
if (window >= 5 && (top & 15) == 0 && top <= 64 &&
(OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) ==
(CFR_MONTMUL | CFR_MONTSQR) && (t4 = OPENSSL_sparcv9cap_P[0]))
window = 5;
else
#endif
#if defined(OPENSSL_BN_ASM_MONT5)
if (window >= 5) {
window = 5; /* ~5% improvement for RSA2048 sign, and even
* for RSA4096 */
/* reserve space for mont->N.d[] copy */
powerbufLen += top * sizeof(mont->N.d[0]);
}
#endif
(void)0;
/*
* Allocate a buffer large enough to hold all of the pre-computed powers
* of am, am itself and tmp.
*/
numPowers = 1 << window;
powerbufLen += sizeof(m->d[0]) * (top * numPowers +
((2 * top) >
numPowers ? (2 * top) : numPowers));
#ifdef alloca
if (powerbufLen < 3072)
powerbufFree =
alloca(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH);
else
#endif
if ((powerbufFree =
OPENSSL_malloc(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH))
== NULL)
goto err;
powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
memset(powerbuf, 0, powerbufLen);
#ifdef alloca
if (powerbufLen < 3072)
powerbufFree = NULL;
#endif
/* lay down tmp and am right after powers table */
tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0]) * top * numPowers);
am.d = tmp.d + top;
tmp.top = am.top = 0;
tmp.dmax = am.dmax = top;
tmp.neg = am.neg = 0;
tmp.flags = am.flags = BN_FLG_STATIC_DATA;
/* prepare a^0 in Montgomery domain */
#if 1 /* by Shay Gueron's suggestion */
if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
/* 2^(top*BN_BITS2) - m */
tmp.d[0] = (0 - m->d[0]) & BN_MASK2;
for (i = 1; i < top; i++)
tmp.d[i] = (~m->d[i]) & BN_MASK2;
tmp.top = top;
} else
#endif
if (!bn_to_mont_fixed_top(&tmp, BN_value_one(), mont, ctx))
goto err;
/* prepare a^1 in Montgomery domain */
if (a->neg || BN_ucmp(a, m) >= 0) {
if (!BN_nnmod(&am, a, m, ctx))
goto err;
if (!bn_to_mont_fixed_top(&am, &am, mont, ctx))
goto err;
} else if (!bn_to_mont_fixed_top(&am, a, mont, ctx))
goto err;
#if defined(SPARC_T4_MONT)
if (t4) {
typedef int (*bn_pwr5_mont_f) (BN_ULONG *tp, const BN_ULONG *np,
const BN_ULONG *n0, const void *table,
int power, int bits);
int bn_pwr5_mont_t4_8(BN_ULONG *tp, const BN_ULONG *np,
const BN_ULONG *n0, const void *table,
int power, int bits);
int bn_pwr5_mont_t4_16(BN_ULONG *tp, const BN_ULONG *np,
const BN_ULONG *n0, const void *table,
int power, int bits);
int bn_pwr5_mont_t4_24(BN_ULONG *tp, const BN_ULONG *np,
const BN_ULONG *n0, const void *table,
int power, int bits);
int bn_pwr5_mont_t4_32(BN_ULONG *tp, const BN_ULONG *np,
const BN_ULONG *n0, const void *table,
int power, int bits);
static const bn_pwr5_mont_f pwr5_funcs[4] = {
bn_pwr5_mont_t4_8, bn_pwr5_mont_t4_16,
bn_pwr5_mont_t4_24, bn_pwr5_mont_t4_32
};
bn_pwr5_mont_f pwr5_worker = pwr5_funcs[top / 16 - 1];
typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap,
const void *bp, const BN_ULONG *np,
const BN_ULONG *n0);
int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap, const void *bp,
const BN_ULONG *np, const BN_ULONG *n0);
int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap,
const void *bp, const BN_ULONG *np,
const BN_ULONG *n0);
int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap,
const void *bp, const BN_ULONG *np,
const BN_ULONG *n0);
int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap,
const void *bp, const BN_ULONG *np,
const BN_ULONG *n0);
static const bn_mul_mont_f mul_funcs[4] = {
bn_mul_mont_t4_8, bn_mul_mont_t4_16,
bn_mul_mont_t4_24, bn_mul_mont_t4_32
};
bn_mul_mont_f mul_worker = mul_funcs[top / 16 - 1];
void bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap,
const void *bp, const BN_ULONG *np,
const BN_ULONG *n0, int num);
void bn_mul_mont_t4(BN_ULONG *rp, const BN_ULONG *ap,
const void *bp, const BN_ULONG *np,
const BN_ULONG *n0, int num);
void bn_mul_mont_gather5_t4(BN_ULONG *rp, const BN_ULONG *ap,
const void *table, const BN_ULONG *np,
const BN_ULONG *n0, int num, int power);
void bn_flip_n_scatter5_t4(const BN_ULONG *inp, size_t num,
void *table, size_t power);
void bn_gather5_t4(BN_ULONG *out, size_t num,
void *table, size_t power);
void bn_flip_t4(BN_ULONG *dst, BN_ULONG *src, size_t num);
BN_ULONG *np = mont->N.d, *n0 = mont->n0;
int stride = 5 * (6 - (top / 16 - 1)); /* multiple of 5, but less
* than 32 */
/*
* BN_to_montgomery can contaminate words above .top [in
* BN_DEBUG[_DEBUG] build]...
*/
for (i = am.top; i < top; i++)
am.d[i] = 0;
for (i = tmp.top; i < top; i++)
tmp.d[i] = 0;
bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, 0);
bn_flip_n_scatter5_t4(am.d, top, powerbuf, 1);
if (!(*mul_worker) (tmp.d, am.d, am.d, np, n0) &&
!(*mul_worker) (tmp.d, am.d, am.d, np, n0))
bn_mul_mont_vis3(tmp.d, am.d, am.d, np, n0, top);
bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, 2);
for (i = 3; i < 32; i++) {
/* Calculate a^i = a^(i-1) * a */
if (!(*mul_worker) (tmp.d, tmp.d, am.d, np, n0) &&
!(*mul_worker) (tmp.d, tmp.d, am.d, np, n0))
bn_mul_mont_vis3(tmp.d, tmp.d, am.d, np, n0, top);
bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, i);
}
/* switch to 64-bit domain */
np = alloca(top * sizeof(BN_ULONG));
top /= 2;
bn_flip_t4(np, mont->N.d, top);
/*
* The exponent may not have a whole number of fixed-size windows.
* To simplify the main loop, the initial window has between 1 and
* full-window-size bits such that what remains is always a whole
* number of windows
*/
window0 = (bits - 1) % 5 + 1;
wmask = (1 << window0) - 1;
bits -= window0;
wvalue = bn_get_bits(p, bits) & wmask;
bn_gather5_t4(tmp.d, top, powerbuf, wvalue);
/*
* Scan the exponent one window at a time starting from the most
* significant bits.
*/
while (bits > 0) {
if (bits < stride)
stride = bits;
bits -= stride;
wvalue = bn_get_bits(p, bits);
if ((*pwr5_worker) (tmp.d, np, n0, powerbuf, wvalue, stride))
continue;
/* retry once and fall back */
if ((*pwr5_worker) (tmp.d, np, n0, powerbuf, wvalue, stride))
continue;
bits += stride - 5;
wvalue >>= stride - 5;
wvalue &= 31;
bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont_gather5_t4(tmp.d, tmp.d, powerbuf, np, n0, top,
wvalue);
}
bn_flip_t4(tmp.d, tmp.d, top);
top *= 2;
/* back to 32-bit domain */
tmp.top = top;
bn_correct_top(&tmp);
OPENSSL_cleanse(np, top * sizeof(BN_ULONG));
} else
#endif
#if defined(OPENSSL_BN_ASM_MONT5)
if (window == 5 && top > 1) {
/*
* This optimization uses ideas from http://eprint.iacr.org/2011/239,
* specifically optimization of cache-timing attack countermeasures
* and pre-computation optimization.
*/
/*
* Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as
* 512-bit RSA is hardly relevant, we omit it to spare size...
*/
void bn_mul_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap,
const void *table, const BN_ULONG *np,
const BN_ULONG *n0, int num, int power);
void bn_scatter5(const BN_ULONG *inp, size_t num,
void *table, size_t power);
void bn_gather5(BN_ULONG *out, size_t num, void *table, size_t power);
void bn_power5(BN_ULONG *rp, const BN_ULONG *ap,
const void *table, const BN_ULONG *np,
const BN_ULONG *n0, int num, int power);
int bn_get_bits5(const BN_ULONG *ap, int off);
int bn_from_montgomery(BN_ULONG *rp, const BN_ULONG *ap,
const BN_ULONG *not_used, const BN_ULONG *np,
const BN_ULONG *n0, int num);
BN_ULONG *n0 = mont->n0, *np;
/*
* BN_to_montgomery can contaminate words above .top [in
* BN_DEBUG[_DEBUG] build]...
*/
for (i = am.top; i < top; i++)
am.d[i] = 0;
for (i = tmp.top; i < top; i++)
tmp.d[i] = 0;
/*
* copy mont->N.d[] to improve cache locality
*/
for (np = am.d + top, i = 0; i < top; i++)
np[i] = mont->N.d[i];
bn_scatter5(tmp.d, top, powerbuf, 0);
bn_scatter5(am.d, am.top, powerbuf, 1);
bn_mul_mont(tmp.d, am.d, am.d, np, n0, top);
bn_scatter5(tmp.d, top, powerbuf, 2);
# if 0
for (i = 3; i < 32; i++) {
/* Calculate a^i = a^(i-1) * a */
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
}
# else
/* same as above, but uses squaring for 1/2 of operations */
for (i = 4; i < 32; i *= 2) {
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_scatter5(tmp.d, top, powerbuf, i);
}
for (i = 3; i < 8; i += 2) {
int j;
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
for (j = 2 * i; j < 32; j *= 2) {
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_scatter5(tmp.d, top, powerbuf, j);
}
}
for (; i < 16; i += 2) {
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_scatter5(tmp.d, top, powerbuf, 2 * i);
}
for (; i < 32; i += 2) {
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
}
# endif
/*
* The exponent may not have a whole number of fixed-size windows.
* To simplify the main loop, the initial window has between 1 and
* full-window-size bits such that what remains is always a whole
* number of windows
*/
window0 = (bits - 1) % 5 + 1;
wmask = (1 << window0) - 1;
bits -= window0;
wvalue = bn_get_bits(p, bits) & wmask;
bn_gather5(tmp.d, top, powerbuf, wvalue);
/*
* Scan the exponent one window at a time starting from the most
* significant bits.
*/
if (top & 7) {
while (bits > 0) {
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont_gather5(tmp.d, tmp.d, powerbuf, np, n0, top,
bn_get_bits5(p->d, bits -= 5));
}
} else {
while (bits > 0) {
bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top,
bn_get_bits5(p->d, bits -= 5));
}
}
ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top);
tmp.top = top;
bn_correct_top(&tmp);
if (ret) {
if (!BN_copy(rr, &tmp))
ret = 0;
goto err; /* non-zero ret means it's not error */
}
} else
#endif
{
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, window))
goto err;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, window))
goto err;
/*
* If the window size is greater than 1, then calculate
* val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1) (even
* powers could instead be computed as (a^(i/2))^2 to use the slight
* performance advantage of sqr over mul).
*/
if (window > 1) {
if (!bn_mul_mont_fixed_top(&tmp, &am, &am, mont, ctx))
goto err;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2,
window))
goto err;
for (i = 3; i < numPowers; i++) {
/* Calculate a^i = a^(i-1) * a */
if (!bn_mul_mont_fixed_top(&tmp, &am, &tmp, mont, ctx))
goto err;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i,
window))
goto err;
}
}
/*
* The exponent may not have a whole number of fixed-size windows.
* To simplify the main loop, the initial window has between 1 and
* full-window-size bits such that what remains is always a whole
* number of windows
*/
window0 = (bits - 1) % window + 1;
wmask = (1 << window0) - 1;
bits -= window0;
wvalue = bn_get_bits(p, bits) & wmask;
if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&tmp, top, powerbuf, wvalue,
window))
goto err;
wmask = (1 << window) - 1;
/*
* Scan the exponent one window at a time starting from the most
* significant bits.
*/
while (bits > 0) {
/* Square the result window-size times */
for (i = 0; i < window; i++)
if (!bn_mul_mont_fixed_top(&tmp, &tmp, &tmp, mont, ctx))
goto err;
/*
* Get a window's worth of bits from the exponent
* This avoids calling BN_is_bit_set for each bit, which
* is not only slower but also makes each bit vulnerable to
* EM (and likely other) side-channel attacks like One&Done
* (for details see "One&Done: A Single-Decryption EM-Based
- * Attack on OpenSSL’s Constant-Time Blinded RSA" by M. Alam,
+ * Attack on OpenSSL's Constant-Time Blinded RSA" by M. Alam,
* H. Khan, M. Dey, N. Sinha, R. Callan, A. Zajic, and
* M. Prvulovic, in USENIX Security'18)
*/
bits -= window;
wvalue = bn_get_bits(p, bits) & wmask;
/*
* Fetch the appropriate pre-computed value from the pre-buf
*/
if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&am, top, powerbuf, wvalue,
window))
goto err;
/* Multiply the result into the intermediate result */
if (!bn_mul_mont_fixed_top(&tmp, &tmp, &am, mont, ctx))
goto err;
}
}
/*
* Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
* removes padding [if any] and makes return value suitable for public
* API consumer.
*/
#if defined(SPARC_T4_MONT)
if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
am.d[0] = 1; /* borrow am */
for (i = 1; i < top; i++)
am.d[i] = 0;
if (!BN_mod_mul_montgomery(rr, &tmp, &am, mont, ctx))
goto err;
} else
#endif
if (!BN_from_montgomery(rr, &tmp, mont, ctx))
goto err;
ret = 1;
err:
if (in_mont == NULL)
BN_MONT_CTX_free(mont);
if (powerbuf != NULL) {
OPENSSL_cleanse(powerbuf, powerbufLen);
OPENSSL_free(powerbufFree);
}
BN_CTX_end(ctx);
return ret;
}
int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
{
BN_MONT_CTX *mont = NULL;
int b, bits, ret = 0;
int r_is_one;
BN_ULONG w, next_w;
BIGNUM *r, *t;
BIGNUM *swap_tmp;
#define BN_MOD_MUL_WORD(r, w, m) \
(BN_mul_word(r, (w)) && \
(/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \
(BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
/*
* BN_MOD_MUL_WORD is only used with 'w' large, so the BN_ucmp test is
* probably more overhead than always using BN_mod (which uses BN_copy if
* a similar test returns true).
*/
/*
* We can use BN_mod and do not need BN_nnmod because our accumulator is
* never negative (the result of BN_mod does not depend on the sign of
* the modulus).
*/
#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
BNerr(BN_F_BN_MOD_EXP_MONT_WORD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
bn_check_top(p);
bn_check_top(m);
if (!BN_is_odd(m)) {
BNerr(BN_F_BN_MOD_EXP_MONT_WORD, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
if (m->top == 1)
a %= m->d[0]; /* make sure that 'a' is reduced */
bits = BN_num_bits(p);
if (bits == 0) {
/* x**0 mod 1, or x**0 mod -1 is still zero. */
if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(rr);
} else {
ret = BN_one(rr);
}
return ret;
}
if (a == 0) {
BN_zero(rr);
ret = 1;
return ret;
}
BN_CTX_start(ctx);
r = BN_CTX_get(ctx);
t = BN_CTX_get(ctx);
if (t == NULL)
goto err;
if (in_mont != NULL)
mont = in_mont;
else {
if ((mont = BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(mont, m, ctx))
goto err;
}
r_is_one = 1; /* except for Montgomery factor */
/* bits-1 >= 0 */
/* The result is accumulated in the product r*w. */
w = a; /* bit 'bits-1' of 'p' is always set */
for (b = bits - 2; b >= 0; b--) {
/* First, square r*w. */
next_w = w * w;
if ((next_w / w) != w) { /* overflow */
if (r_is_one) {
if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
goto err;
r_is_one = 0;
} else {
if (!BN_MOD_MUL_WORD(r, w, m))
goto err;
}
next_w = 1;
}
w = next_w;
if (!r_is_one) {
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
goto err;
}
/* Second, multiply r*w by 'a' if exponent bit is set. */
if (BN_is_bit_set(p, b)) {
next_w = w * a;
if ((next_w / a) != w) { /* overflow */
if (r_is_one) {
if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
goto err;
r_is_one = 0;
} else {
if (!BN_MOD_MUL_WORD(r, w, m))
goto err;
}
next_w = a;
}
w = next_w;
}
}
/* Finally, set r:=r*w. */
if (w != 1) {
if (r_is_one) {
if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
goto err;
r_is_one = 0;
} else {
if (!BN_MOD_MUL_WORD(r, w, m))
goto err;
}
}
if (r_is_one) { /* can happen only if a == 1 */
if (!BN_one(rr))
goto err;
} else {
if (!BN_from_montgomery(rr, r, mont, ctx))
goto err;
}
ret = 1;
err:
if (in_mont == NULL)
BN_MONT_CTX_free(mont);
BN_CTX_end(ctx);
bn_check_top(rr);
return ret;
}
/* The old fallback, simple version :-) */
int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx)
{
int i, j, bits, ret = 0, wstart, wend, window, wvalue;
int start = 1;
BIGNUM *d;
/* Table of variables obtained from 'ctx' */
BIGNUM *val[TABLE_SIZE];
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(a, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
BNerr(BN_F_BN_MOD_EXP_SIMPLE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
bits = BN_num_bits(p);
if (bits == 0) {
/* x**0 mod 1, or x**0 mod -1 is still zero. */
if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(r);
} else {
ret = BN_one(r);
}
return ret;
}
BN_CTX_start(ctx);
d = BN_CTX_get(ctx);
val[0] = BN_CTX_get(ctx);
if (val[0] == NULL)
goto err;
if (!BN_nnmod(val[0], a, m, ctx))
goto err; /* 1 */
if (BN_is_zero(val[0])) {
BN_zero(r);
ret = 1;
goto err;
}
window = BN_window_bits_for_exponent_size(bits);
if (window > 1) {
if (!BN_mod_mul(d, val[0], val[0], m, ctx))
goto err; /* 2 */
j = 1 << (window - 1);
for (i = 1; i < j; i++) {
if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
!BN_mod_mul(val[i], val[i - 1], d, m, ctx))
goto err;
}
}
start = 1; /* This is used to avoid multiplication etc
* when there is only the value '1' in the
* buffer. */
wvalue = 0; /* The 'value' of the window */
wstart = bits - 1; /* The top bit of the window */
wend = 0; /* The bottom bit of the window */
if (!BN_one(r))
goto err;
for (;;) {
if (BN_is_bit_set(p, wstart) == 0) {
if (!start)
if (!BN_mod_mul(r, r, r, m, ctx))
goto err;
if (wstart == 0)
break;
wstart--;
continue;
}
/*
* We now have wstart on a 'set' bit, we now need to work out how bit
* a window to do. To do this we need to scan forward until the last
* set bit before the end of the window
*/
j = wstart;
wvalue = 1;
wend = 0;
for (i = 1; i < window; i++) {
if (wstart - i < 0)
break;
if (BN_is_bit_set(p, wstart - i)) {
wvalue <<= (i - wend);
wvalue |= 1;
wend = i;
}
}
/* wend is the size of the current window */
j = wend + 1;
/* add the 'bytes above' */
if (!start)
for (i = 0; i < j; i++) {
if (!BN_mod_mul(r, r, r, m, ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
if (!BN_mod_mul(r, r, val[wvalue >> 1], m, ctx))
goto err;
/* move the 'window' down further */
wstart -= wend + 1;
wvalue = 0;
start = 0;
if (wstart < 0)
break;
}
ret = 1;
err:
BN_CTX_end(ctx);
bn_check_top(r);
return ret;
}
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index 266a3dd3046b..80f910c80779 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -1,984 +1,988 @@
/*
* Copyright 1995-2018 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)
{
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;
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. The code assumes that at most one bit of condition is set.
* nwords is the number of words to swap. The code assumes that at least nwords are allocated in both a and b,
* and that no more than nwords are used by either a or b.
* a and b cannot be the same number
*/
void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
{
BN_ULONG t;
int i;
bn_wcheck_size(a, nwords);
bn_wcheck_size(b, nwords);
assert(a != b);
assert((condition & (condition - 1)) == 0);
assert(sizeof(BN_ULONG) >= sizeof(int));
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;
/*-
- * Idea behind BN_FLG_STATIC_DATA is actually to
- * indicate 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. Remaining flags are
- * BN_FLG_CONSTIME and BN_FLG_SECURE. Latter must be
- * preserved, because it determines how x->d was
- * allocated and hence how to free it. This leaves
- * BN_FLG_CONSTTIME that one can do something about.
- * To summarize it's sufficient to mask and swap
- * BN_FLG_CONSTTIME alone. BN_FLG_STATIC_DATA should
- * be treated as fatal.
+ * 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
*/
- t = ((a->flags ^ b->flags) & BN_FLG_CONSTTIME) & condition;
+
+#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;
#define BN_CONSTTIME_SWAP(ind) \
do { \
t = (a->d[ind] ^ b->d[ind]) & condition; \
a->d[ind] ^= t; \
b->d[ind] ^= t; \
} while (0)
switch (nwords) {
default:
for (i = 10; i < nwords; i++)
BN_CONSTTIME_SWAP(i);
/* Fallthrough */
case 10:
BN_CONSTTIME_SWAP(9); /* Fallthrough */
case 9:
BN_CONSTTIME_SWAP(8); /* Fallthrough */
case 8:
BN_CONSTTIME_SWAP(7); /* Fallthrough */
case 7:
BN_CONSTTIME_SWAP(6); /* Fallthrough */
case 6:
BN_CONSTTIME_SWAP(5); /* Fallthrough */
case 5:
BN_CONSTTIME_SWAP(4); /* Fallthrough */
case 4:
BN_CONSTTIME_SWAP(3); /* Fallthrough */
case 3:
BN_CONSTTIME_SWAP(2); /* Fallthrough */
case 2:
BN_CONSTTIME_SWAP(1); /* Fallthrough */
case 1:
BN_CONSTTIME_SWAP(0);
}
#undef BN_CONSTTIME_SWAP
}
/* 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/build.info b/crypto/build.info
index b515b7318efb..2c619c62e843 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -1,39 +1,39 @@
LIBS=../libcrypto
SOURCE[../libcrypto]=\
cryptlib.c mem.c mem_dbg.c cversion.c ex_data.c cpt_err.c \
ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c ctype.c \
- threads_pthread.c threads_win.c threads_none.c \
+ threads_pthread.c threads_win.c threads_none.c getenv.c \
o_init.c o_fips.c mem_sec.c init.c {- $target{cpuid_asm_src} -} \
{- $target{uplink_aux_src} -}
EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \
x86cpuid.pl x86_64cpuid.pl ia64cpuid.S \
ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl
DEPEND[cversion.o]=buildinf.h
GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" "$(PLATFORM)"
DEPEND[buildinf.h]=../configdata.pm
GENERATE[uplink-x86.s]=../ms/uplink-x86.pl $(PERLASM_SCHEME)
GENERATE[uplink-x86_64.s]=../ms/uplink-x86_64.pl $(PERLASM_SCHEME)
GENERATE[uplink-ia64.s]=../ms/uplink-ia64.pl $(PERLASM_SCHEME)
GENERATE[x86cpuid.s]=x86cpuid.pl \
$(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
DEPEND[x86cpuid.s]=perlasm/x86asm.pl
GENERATE[x86_64cpuid.s]=x86_64cpuid.pl $(PERLASM_SCHEME)
GENERATE[ia64cpuid.s]=ia64cpuid.S
GENERATE[ppccpuid.s]=ppccpuid.pl $(PERLASM_SCHEME)
GENERATE[pariscid.s]=pariscid.pl $(PERLASM_SCHEME)
GENERATE[alphacpuid.s]=alphacpuid.pl
GENERATE[arm64cpuid.S]=arm64cpuid.pl $(PERLASM_SCHEME)
INCLUDE[arm64cpuid.o]=.
GENERATE[armv4cpuid.S]=armv4cpuid.pl $(PERLASM_SCHEME)
INCLUDE[armv4cpuid.o]=.
GENERATE[s390xcpuid.S]=s390xcpuid.pl $(PERLASM_SCHEME)
INCLUDE[s390xcpuid.o]=.
IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}]
SHARED_SOURCE[../libcrypto]=dllmain.c
ENDIF
diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c
index 72fe2da1ad78..5e57d749ce5e 100644
--- a/crypto/conf/conf_api.c
+++ b/crypto/conf/conf_api.c
@@ -1,217 +1,218 @@
/*
* Copyright 1995-2018 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
*/
/* Part of the code in here was originally in conf.c, which is now removed */
#include "e_os.h"
+#include "internal/cryptlib.h"
#include <stdlib.h>
#include <string.h>
#include <openssl/conf.h>
#include <openssl/conf_api.h>
static void value_free_hash(const CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf);
static void value_free_stack_doall(CONF_VALUE *a);
/* Up until OpenSSL 0.9.5a, this was get_section */
CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section)
{
CONF_VALUE *v, vv;
if ((conf == NULL) || (section == NULL))
return NULL;
vv.name = NULL;
vv.section = (char *)section;
v = lh_CONF_VALUE_retrieve(conf->data, &vv);
return v;
}
/* Up until OpenSSL 0.9.5a, this was CONF_get_section */
STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf,
const char *section)
{
CONF_VALUE *v;
v = _CONF_get_section(conf, section);
if (v != NULL)
return ((STACK_OF(CONF_VALUE) *)v->value);
else
return NULL;
}
int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value)
{
CONF_VALUE *v = NULL;
STACK_OF(CONF_VALUE) *ts;
ts = (STACK_OF(CONF_VALUE) *)section->value;
value->section = section->section;
if (!sk_CONF_VALUE_push(ts, value)) {
return 0;
}
v = lh_CONF_VALUE_insert(conf->data, value);
if (v != NULL) {
(void)sk_CONF_VALUE_delete_ptr(ts, v);
OPENSSL_free(v->name);
OPENSSL_free(v->value);
OPENSSL_free(v);
}
return 1;
}
char *_CONF_get_string(const CONF *conf, const char *section,
const char *name)
{
CONF_VALUE *v, vv;
char *p;
if (name == NULL)
return NULL;
if (conf != NULL) {
if (section != NULL) {
vv.name = (char *)name;
vv.section = (char *)section;
v = lh_CONF_VALUE_retrieve(conf->data, &vv);
if (v != NULL)
return v->value;
if (strcmp(section, "ENV") == 0) {
- p = getenv(name);
+ p = ossl_safe_getenv(name);
if (p != NULL)
return p;
}
}
vv.section = "default";
vv.name = (char *)name;
v = lh_CONF_VALUE_retrieve(conf->data, &vv);
if (v != NULL)
return v->value;
else
return NULL;
} else
- return getenv(name);
+ return ossl_safe_getenv(name);
}
static unsigned long conf_value_hash(const CONF_VALUE *v)
{
return (OPENSSL_LH_strhash(v->section) << 2) ^ OPENSSL_LH_strhash(v->name);
}
static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b)
{
int i;
if (a->section != b->section) {
i = strcmp(a->section, b->section);
if (i)
return i;
}
if ((a->name != NULL) && (b->name != NULL)) {
i = strcmp(a->name, b->name);
return i;
} else if (a->name == b->name)
return 0;
else
return ((a->name == NULL) ? -1 : 1);
}
int _CONF_new_data(CONF *conf)
{
if (conf == NULL) {
return 0;
}
if (conf->data == NULL) {
conf->data = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp);
if (conf->data == NULL)
return 0;
}
return 1;
}
typedef LHASH_OF(CONF_VALUE) LH_CONF_VALUE;
IMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, LH_CONF_VALUE);
void _CONF_free_data(CONF *conf)
{
if (conf == NULL || conf->data == NULL)
return;
/* evil thing to make sure the 'OPENSSL_free()' works as expected */
lh_CONF_VALUE_set_down_load(conf->data, 0);
lh_CONF_VALUE_doall_LH_CONF_VALUE(conf->data, value_free_hash, conf->data);
/*
* We now have only 'section' entries in the hash table. Due to problems
* with
*/
lh_CONF_VALUE_doall(conf->data, value_free_stack_doall);
lh_CONF_VALUE_free(conf->data);
}
static void value_free_hash(const CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf)
{
if (a->name != NULL)
(void)lh_CONF_VALUE_delete(conf, a);
}
static void value_free_stack_doall(CONF_VALUE *a)
{
CONF_VALUE *vv;
STACK_OF(CONF_VALUE) *sk;
int i;
if (a->name != NULL)
return;
sk = (STACK_OF(CONF_VALUE) *)a->value;
for (i = sk_CONF_VALUE_num(sk) - 1; i >= 0; i--) {
vv = sk_CONF_VALUE_value(sk, i);
OPENSSL_free(vv->value);
OPENSSL_free(vv->name);
OPENSSL_free(vv);
}
sk_CONF_VALUE_free(sk);
OPENSSL_free(a->section);
OPENSSL_free(a);
}
/* Up until OpenSSL 0.9.5a, this was new_section */
CONF_VALUE *_CONF_new_section(CONF *conf, const char *section)
{
STACK_OF(CONF_VALUE) *sk = NULL;
int i;
CONF_VALUE *v = NULL, *vv;
if ((sk = sk_CONF_VALUE_new_null()) == NULL)
goto err;
if ((v = OPENSSL_malloc(sizeof(*v))) == NULL)
goto err;
i = strlen(section) + 1;
if ((v->section = OPENSSL_malloc(i)) == NULL)
goto err;
memcpy(v->section, section, i);
v->name = NULL;
v->value = (char *)sk;
vv = lh_CONF_VALUE_insert(conf->data, v);
if (vv != NULL || lh_CONF_VALUE_error(conf->data) > 0)
goto err;
return v;
err:
sk_CONF_VALUE_free(sk);
if (v != NULL)
OPENSSL_free(v->section);
OPENSSL_free(v);
return NULL;
}
diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c
index df53609cc47e..51f262e774dd 100644
--- a/crypto/conf/conf_mod.c
+++ b/crypto/conf/conf_mod.c
@@ -1,551 +1,548 @@
/*
* Copyright 2002-2018 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 <stdio.h>
#include <ctype.h>
#include <openssl/crypto.h>
#include "internal/conf.h"
#include "internal/dso.h"
#include <openssl/x509.h>
#define DSO_mod_init_name "OPENSSL_init"
#define DSO_mod_finish_name "OPENSSL_finish"
/*
* This structure contains a data about supported modules. entries in this
* table correspond to either dynamic or static modules.
*/
struct conf_module_st {
/* DSO of this module or NULL if static */
DSO *dso;
/* Name of the module */
char *name;
/* Init function */
conf_init_func *init;
/* Finish function */
conf_finish_func *finish;
/* Number of successfully initialized modules */
int links;
void *usr_data;
};
/*
* This structure contains information about modules that have been
* successfully initialized. There may be more than one entry for a given
* module.
*/
struct conf_imodule_st {
CONF_MODULE *pmod;
char *name;
char *value;
unsigned long flags;
void *usr_data;
};
static STACK_OF(CONF_MODULE) *supported_modules = NULL;
static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
static void module_free(CONF_MODULE *md);
static void module_finish(CONF_IMODULE *imod);
static int module_run(const CONF *cnf, const char *name, const char *value,
unsigned long flags);
static CONF_MODULE *module_add(DSO *dso, const char *name,
conf_init_func *ifunc,
conf_finish_func *ffunc);
static CONF_MODULE *module_find(const char *name);
static int module_init(CONF_MODULE *pmod, const char *name, const char *value,
const CONF *cnf);
static CONF_MODULE *module_load_dso(const CONF *cnf, const char *name,
const char *value);
/* Main function: load modules from a CONF structure */
int CONF_modules_load(const CONF *cnf, const char *appname,
unsigned long flags)
{
STACK_OF(CONF_VALUE) *values;
CONF_VALUE *vl;
char *vsection = NULL;
int ret, i;
if (!cnf)
return 1;
if (appname)
vsection = NCONF_get_string(cnf, NULL, appname);
if (!appname || (!vsection && (flags & CONF_MFLAGS_DEFAULT_SECTION)))
vsection = NCONF_get_string(cnf, NULL, "openssl_conf");
if (!vsection) {
ERR_clear_error();
return 1;
}
values = NCONF_get_section(cnf, vsection);
if (!values)
return 0;
for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
vl = sk_CONF_VALUE_value(values, i);
ret = module_run(cnf, vl->name, vl->value, flags);
if (ret <= 0)
if (!(flags & CONF_MFLAGS_IGNORE_ERRORS))
return ret;
}
return 1;
}
int CONF_modules_load_file(const char *filename, const char *appname,
unsigned long flags)
{
char *file = NULL;
CONF *conf = NULL;
int ret = 0;
conf = NCONF_new(NULL);
if (conf == NULL)
goto err;
if (filename == NULL) {
file = CONF_get1_default_config_file();
if (!file)
goto err;
} else
file = (char *)filename;
if (NCONF_load(conf, file, NULL) <= 0) {
if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) &&
(ERR_GET_REASON(ERR_peek_last_error()) == CONF_R_NO_SUCH_FILE)) {
ERR_clear_error();
ret = 1;
}
goto err;
}
ret = CONF_modules_load(conf, appname, flags);
err:
if (filename == NULL)
OPENSSL_free(file);
NCONF_free(conf);
return ret;
}
static int module_run(const CONF *cnf, const char *name, const char *value,
unsigned long flags)
{
CONF_MODULE *md;
int ret;
md = module_find(name);
/* Module not found: try to load DSO */
if (!md && !(flags & CONF_MFLAGS_NO_DSO))
md = module_load_dso(cnf, name, value);
if (!md) {
if (!(flags & CONF_MFLAGS_SILENT)) {
CONFerr(CONF_F_MODULE_RUN, CONF_R_UNKNOWN_MODULE_NAME);
ERR_add_error_data(2, "module=", name);
}
return -1;
}
ret = module_init(md, name, value, cnf);
if (ret <= 0) {
if (!(flags & CONF_MFLAGS_SILENT)) {
char rcode[DECIMAL_SIZE(ret) + 1];
CONFerr(CONF_F_MODULE_RUN, CONF_R_MODULE_INITIALIZATION_ERROR);
BIO_snprintf(rcode, sizeof(rcode), "%-8d", ret);
ERR_add_error_data(6, "module=", name, ", value=", value,
", retcode=", rcode);
}
}
return ret;
}
/* Load a module from a DSO */
static CONF_MODULE *module_load_dso(const CONF *cnf,
const char *name, const char *value)
{
DSO *dso = NULL;
conf_init_func *ifunc;
conf_finish_func *ffunc;
const char *path = NULL;
int errcode = 0;
CONF_MODULE *md;
/* Look for alternative path in module section */
path = NCONF_get_string(cnf, value, "path");
if (!path) {
ERR_clear_error();
path = name;
}
dso = DSO_load(NULL, path, NULL, 0);
if (!dso) {
errcode = CONF_R_ERROR_LOADING_DSO;
goto err;
}
ifunc = (conf_init_func *)DSO_bind_func(dso, DSO_mod_init_name);
if (!ifunc) {
errcode = CONF_R_MISSING_INIT_FUNCTION;
goto err;
}
ffunc = (conf_finish_func *)DSO_bind_func(dso, DSO_mod_finish_name);
/* All OK, add module */
md = module_add(dso, name, ifunc, ffunc);
if (!md)
goto err;
return md;
err:
DSO_free(dso);
CONFerr(CONF_F_MODULE_LOAD_DSO, errcode);
ERR_add_error_data(4, "module=", name, ", path=", path);
return NULL;
}
/* add module to list */
static CONF_MODULE *module_add(DSO *dso, const char *name,
conf_init_func *ifunc, conf_finish_func *ffunc)
{
CONF_MODULE *tmod = NULL;
if (supported_modules == NULL)
supported_modules = sk_CONF_MODULE_new_null();
if (supported_modules == NULL)
return NULL;
if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL) {
CONFerr(CONF_F_MODULE_ADD, ERR_R_MALLOC_FAILURE);
return NULL;
}
tmod->dso = dso;
tmod->name = OPENSSL_strdup(name);
tmod->init = ifunc;
tmod->finish = ffunc;
if (tmod->name == NULL) {
OPENSSL_free(tmod);
return NULL;
}
if (!sk_CONF_MODULE_push(supported_modules, tmod)) {
OPENSSL_free(tmod->name);
OPENSSL_free(tmod);
return NULL;
}
return tmod;
}
/*
* Find a module from the list. We allow module names of the form
* modname.XXXX to just search for modname to allow the same module to be
* initialized more than once.
*/
static CONF_MODULE *module_find(const char *name)
{
CONF_MODULE *tmod;
int i, nchar;
char *p;
p = strrchr(name, '.');
if (p)
nchar = p - name;
else
nchar = strlen(name);
for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) {
tmod = sk_CONF_MODULE_value(supported_modules, i);
if (strncmp(tmod->name, name, nchar) == 0)
return tmod;
}
return NULL;
}
/* initialize a module */
static int module_init(CONF_MODULE *pmod, const char *name, const char *value,
const CONF *cnf)
{
int ret = 1;
int init_called = 0;
CONF_IMODULE *imod = NULL;
/* Otherwise add initialized module to list */
imod = OPENSSL_malloc(sizeof(*imod));
if (imod == NULL)
goto err;
imod->pmod = pmod;
imod->name = OPENSSL_strdup(name);
imod->value = OPENSSL_strdup(value);
imod->usr_data = NULL;
if (!imod->name || !imod->value)
goto memerr;
/* Try to initialize module */
if (pmod->init) {
ret = pmod->init(imod, cnf);
init_called = 1;
/* Error occurred, exit */
if (ret <= 0)
goto err;
}
if (initialized_modules == NULL) {
initialized_modules = sk_CONF_IMODULE_new_null();
if (!initialized_modules) {
CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (!sk_CONF_IMODULE_push(initialized_modules, imod)) {
CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
goto err;
}
pmod->links++;
return ret;
err:
/* We've started the module so we'd better finish it */
if (pmod->finish && init_called)
pmod->finish(imod);
memerr:
if (imod) {
OPENSSL_free(imod->name);
OPENSSL_free(imod->value);
OPENSSL_free(imod);
}
return -1;
}
/*
* Unload any dynamic modules that have a link count of zero: i.e. have no
* active initialized modules. If 'all' is set then all modules are unloaded
* including static ones.
*/
void CONF_modules_unload(int all)
{
int i;
CONF_MODULE *md;
CONF_modules_finish();
/* unload modules in reverse order */
for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) {
md = sk_CONF_MODULE_value(supported_modules, i);
/* If static or in use and 'all' not set ignore it */
if (((md->links > 0) || !md->dso) && !all)
continue;
/* Since we're working in reverse this is OK */
(void)sk_CONF_MODULE_delete(supported_modules, i);
module_free(md);
}
if (sk_CONF_MODULE_num(supported_modules) == 0) {
sk_CONF_MODULE_free(supported_modules);
supported_modules = NULL;
}
}
/* unload a single module */
static void module_free(CONF_MODULE *md)
{
DSO_free(md->dso);
OPENSSL_free(md->name);
OPENSSL_free(md);
}
/* finish and free up all modules instances */
void CONF_modules_finish(void)
{
CONF_IMODULE *imod;
while (sk_CONF_IMODULE_num(initialized_modules) > 0) {
imod = sk_CONF_IMODULE_pop(initialized_modules);
module_finish(imod);
}
sk_CONF_IMODULE_free(initialized_modules);
initialized_modules = NULL;
}
/* finish a module instance */
static void module_finish(CONF_IMODULE *imod)
{
if (!imod)
return;
if (imod->pmod->finish)
imod->pmod->finish(imod);
imod->pmod->links--;
OPENSSL_free(imod->name);
OPENSSL_free(imod->value);
OPENSSL_free(imod);
}
/* Add a static module to OpenSSL */
int CONF_module_add(const char *name, conf_init_func *ifunc,
conf_finish_func *ffunc)
{
if (module_add(NULL, name, ifunc, ffunc))
return 1;
else
return 0;
}
void conf_modules_free_int(void)
{
CONF_modules_finish();
CONF_modules_unload(1);
}
/* Utility functions */
const char *CONF_imodule_get_name(const CONF_IMODULE *md)
{
return md->name;
}
const char *CONF_imodule_get_value(const CONF_IMODULE *md)
{
return md->value;
}
void *CONF_imodule_get_usr_data(const CONF_IMODULE *md)
{
return md->usr_data;
}
void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data)
{
md->usr_data = usr_data;
}
CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md)
{
return md->pmod;
}
unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md)
{
return md->flags;
}
void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags)
{
md->flags = flags;
}
void *CONF_module_get_usr_data(CONF_MODULE *pmod)
{
return pmod->usr_data;
}
void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data)
{
pmod->usr_data = usr_data;
}
/* Return default config file name */
char *CONF_get1_default_config_file(void)
{
char *file, *sep = "";
int len;
- if (!OPENSSL_issetugid()) {
- file = getenv("OPENSSL_CONF");
- if (file)
- return OPENSSL_strdup(file);
- }
+ if ((file = ossl_safe_getenv("OPENSSL_CONF")) != NULL)
+ return OPENSSL_strdup(file);
len = strlen(X509_get_default_cert_area());
#ifndef OPENSSL_SYS_VMS
len++;
sep = "/";
#endif
len += strlen(OPENSSL_CONF);
file = OPENSSL_malloc(len + 1);
if (file == NULL)
return NULL;
BIO_snprintf(file, len + 1, "%s%s%s", X509_get_default_cert_area(),
sep, OPENSSL_CONF);
return file;
}
/*
* This function takes a list separated by 'sep' and calls the callback
* function giving the start and length of each member optionally stripping
* leading and trailing whitespace. This can be used to parse comma separated
* lists for example.
*/
int CONF_parse_list(const char *list_, int sep, int nospc,
int (*list_cb) (const char *elem, int len, void *usr),
void *arg)
{
int ret;
const char *lstart, *tmpend, *p;
if (list_ == NULL) {
CONFerr(CONF_F_CONF_PARSE_LIST, CONF_R_LIST_CANNOT_BE_NULL);
return 0;
}
lstart = list_;
for (;;) {
if (nospc) {
while (*lstart && isspace((unsigned char)*lstart))
lstart++;
}
p = strchr(lstart, sep);
if (p == lstart || !*lstart)
ret = list_cb(NULL, 0, arg);
else {
if (p)
tmpend = p - 1;
else
tmpend = lstart + strlen(lstart) - 1;
if (nospc) {
while (isspace((unsigned char)*tmpend))
tmpend--;
}
ret = list_cb(lstart, tmpend - lstart + 1, arg);
}
if (ret <= 0)
return ret;
if (p == NULL)
return 1;
lstart = p + 1;
}
}
diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c
index b1e535a69596..1cd77c96d2f7 100644
--- a/crypto/cryptlib.c
+++ b/crypto/cryptlib.c
@@ -1,463 +1,463 @@
/*
* Copyright 1998-2018 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 "e_os.h"
#include "internal/cryptlib_int.h"
#include <openssl/safestack.h>
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64)
extern unsigned int OPENSSL_ia32cap_P[4];
# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
/*
* Purpose of these minimalistic and character-type-agnostic subroutines
* is to break dependency on MSVCRT (on Windows) and locale. This makes
* OPENSSL_cpuid_setup safe to use as "constructor". "Character-type-
* agnostic" means that they work with either wide or 8-bit characters,
* exploiting the fact that first 127 characters can be simply casted
* between the sets, while the rest would be simply rejected by ossl_is*
* subroutines.
*/
# ifdef _WIN32
typedef WCHAR variant_char;
static variant_char *ossl_getenv(const char *name)
{
/*
* Since we pull only one environment variable, it's simpler to
* to just ignore |name| and use equivalent wide-char L-literal.
* As well as to ignore excessively long values...
*/
static WCHAR value[48];
DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, 48);
return (len > 0 && len < 48) ? value : NULL;
}
# else
typedef char variant_char;
# define ossl_getenv getenv
# endif
# include "internal/ctype.h"
static int todigit(variant_char c)
{
if (ossl_isdigit(c))
return c - '0';
else if (ossl_isxdigit(c))
return ossl_tolower(c) - 'a' + 10;
/* return largest base value to make caller terminate the loop */
return 16;
}
static uint64_t ossl_strtouint64(const variant_char *str)
{
uint64_t ret = 0;
unsigned int digit, base = 10;
if (*str == '0') {
base = 8, str++;
if (ossl_tolower(*str) == 'x')
base = 16, str++;
}
while((digit = todigit(*str++)) < base)
ret = ret * base + digit;
return ret;
}
static variant_char *ossl_strchr(const variant_char *str, char srch)
{ variant_char c;
while((c = *str)) {
if (c == srch)
return (variant_char *)str;
str++;
}
return NULL;
}
# define OPENSSL_CPUID_SETUP
typedef uint64_t IA32CAP;
void OPENSSL_cpuid_setup(void)
{
static int trigger = 0;
IA32CAP OPENSSL_ia32_cpuid(unsigned int *);
IA32CAP vec;
const variant_char *env;
if (trigger)
return;
trigger = 1;
if ((env = ossl_getenv("OPENSSL_ia32cap")) != NULL) {
int off = (env[0] == '~') ? 1 : 0;
vec = ossl_strtouint64(env + off);
if (off) {
IA32CAP mask = vec;
vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask;
if (mask & (1<<24)) {
/*
* User disables FXSR bit, mask even other capabilities
* that operate exclusively on XMM, so we don't have to
* double-check all the time. We mask PCLMULQDQ, AMD XOP,
* AES-NI and AVX. Formally speaking we don't have to
* do it in x86_64 case, but we can safely assume that
* x86_64 users won't actually flip this flag.
*/
vec &= ~((IA32CAP)(1<<1|1<<11|1<<25|1<<28) << 32);
}
} else if (env[0] == ':') {
vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
}
if ((env = ossl_strchr(env, ':')) != NULL) {
IA32CAP vecx;
env++;
off = (env[0] == '~') ? 1 : 0;
vecx = ossl_strtouint64(env + off);
if (off) {
OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx;
OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32);
} else {
OPENSSL_ia32cap_P[2] = (unsigned int)vecx;
OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32);
}
} else {
OPENSSL_ia32cap_P[2] = 0;
OPENSSL_ia32cap_P[3] = 0;
}
} else {
vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
}
/*
* |(1<<10) sets a reserved bit to signal that variable
* was initialized already... This is to avoid interference
* with cpuid snippets in ELF .init segment.
*/
OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10);
OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32);
}
# else
unsigned int OPENSSL_ia32cap_P[4];
# endif
#endif
#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
void OPENSSL_cpuid_setup(void)
{
}
#endif
#if defined(_WIN32)
# include <tchar.h>
# include <signal.h>
# ifdef __WATCOMC__
# if defined(_UNICODE) || defined(__UNICODE__)
# define _vsntprintf _vsnwprintf
# else
# define _vsntprintf _vsnprintf
# endif
# endif
# ifdef _MSC_VER
# define alloca _alloca
# endif
# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
# ifdef OPENSSL_SYS_WIN_CORE
int OPENSSL_isservice(void)
{
/* OneCore API cannot interact with GUI */
return 1;
}
# else
int OPENSSL_isservice(void)
{
HWINSTA h;
DWORD len;
WCHAR *name;
static union {
void *p;
FARPROC f;
} _OPENSSL_isservice = {
NULL
};
if (_OPENSSL_isservice.p == NULL) {
HANDLE mod = GetModuleHandle(NULL);
- FARPROC f;
+ FARPROC f = NULL;
if (mod != NULL)
f = GetProcAddress(mod, "_OPENSSL_isservice");
if (f == NULL)
_OPENSSL_isservice.p = (void *)-1;
else
_OPENSSL_isservice.f = f;
}
if (_OPENSSL_isservice.p != (void *)-1)
return (*_OPENSSL_isservice.f) ();
h = GetProcessWindowStation();
if (h == NULL)
return -1;
if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) ||
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return -1;
if (len > 512)
return -1; /* paranoia */
len++, len &= ~1; /* paranoia */
name = (WCHAR *)alloca(len + sizeof(WCHAR));
if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len))
return -1;
len++, len &= ~1; /* paranoia */
name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */
# if 1
/*
* This doesn't cover "interactive" services [working with real
* WinSta0's] nor programs started non-interactively by Task Scheduler
* [those are working with SAWinSta].
*/
if (wcsstr(name, L"Service-0x"))
return 1;
# else
/* This covers all non-interactive programs such as services. */
if (!wcsstr(name, L"WinSta0"))
return 1;
# endif
else
return 0;
}
# endif
# else
int OPENSSL_isservice(void)
{
return 0;
}
# endif
void OPENSSL_showfatal(const char *fmta, ...)
{
va_list ap;
TCHAR buf[256];
const TCHAR *fmt;
/*
* First check if it's a console application, in which case the
* error message would be printed to standard error.
* Windows CE does not have a concept of a console application,
* so we need to guard the check.
*/
# ifdef STD_ERROR_HANDLE
HANDLE h;
if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
GetFileType(h) != FILE_TYPE_UNKNOWN) {
/* must be console application */
int len;
DWORD out;
va_start(ap, fmta);
len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap);
WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL);
va_end(ap);
return;
}
# endif
if (sizeof(TCHAR) == sizeof(char))
fmt = (const TCHAR *)fmta;
else
do {
int keepgoing;
size_t len_0 = strlen(fmta) + 1, i;
WCHAR *fmtw;
fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
if (fmtw == NULL) {
fmt = (const TCHAR *)L"no stack?";
break;
}
if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0))
for (i = 0; i < len_0; i++)
fmtw[i] = (WCHAR)fmta[i];
for (i = 0; i < len_0; i++) {
if (fmtw[i] == L'%')
do {
keepgoing = 0;
switch (fmtw[i + 1]) {
case L'0':
case L'1':
case L'2':
case L'3':
case L'4':
case L'5':
case L'6':
case L'7':
case L'8':
case L'9':
case L'.':
case L'*':
case L'-':
i++;
keepgoing = 1;
break;
case L's':
fmtw[i + 1] = L'S';
break;
case L'S':
fmtw[i + 1] = L's';
break;
case L'c':
fmtw[i + 1] = L'C';
break;
case L'C':
fmtw[i + 1] = L'c';
break;
}
} while (keepgoing);
}
fmt = (const TCHAR *)fmtw;
} while (0);
va_start(ap, fmta);
_vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap);
buf[OSSL_NELEM(buf) - 1] = _T('\0');
va_end(ap);
# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
# ifdef OPENSSL_SYS_WIN_CORE
/* ONECORE is always NONGUI and NT >= 0x0601 */
/*
* TODO: (For non GUI and no std error cases)
* Add event logging feature here.
*/
# if !defined(NDEBUG)
/*
* We are in a situation where we tried to report a critical
* error and this failed for some reason. As a last resort,
* in debug builds, send output to the debugger or any other
* tool like DebugView which can monitor the output.
*/
OutputDebugString(buf);
# endif
# else
/* this -------------v--- guards NT-specific calls */
if (check_winnt() && OPENSSL_isservice() > 0) {
HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL"));
if (hEventLog != NULL) {
const TCHAR *pmsg = buf;
if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL,
1, 0, &pmsg, NULL)) {
# if !defined(NDEBUG)
/*
* We are in a situation where we tried to report a critical
* error and this failed for some reason. As a last resort,
* in debug builds, send output to the debugger or any other
* tool like DebugView which can monitor the output.
*/
OutputDebugString(pmsg);
# endif
}
(void)DeregisterEventSource(hEventLog);
}
} else {
MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);
}
# endif
# else
MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);
# endif
}
#else
void OPENSSL_showfatal(const char *fmta, ...)
{
#ifndef OPENSSL_NO_STDIO
va_list ap;
va_start(ap, fmta);
vfprintf(stderr, fmta, ap);
va_end(ap);
#endif
}
int OPENSSL_isservice(void)
{
return 0;
}
#endif
void OPENSSL_die(const char *message, const char *file, int line)
{
OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n",
file, line, message);
#if !defined(_WIN32)
abort();
#else
/*
* Win32 abort() customarily shows a dialog, but we just did that...
*/
# if !defined(_WIN32_WCE)
raise(SIGABRT);
# endif
_exit(3);
#endif
}
#if !defined(OPENSSL_CPUID_OBJ)
/*
* The volatile is used to to ensure that the compiler generates code that reads
* all values from the array and doesn't try to optimize this away. The standard
* doesn't actually require this behavior if the original data pointed to is
* not volatile, but compilers do this in practice anyway.
*
* There are also assembler versions of this function.
*/
# undef CRYPTO_memcmp
int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len)
{
size_t i;
const volatile unsigned char *a = in_a;
const volatile unsigned char *b = in_b;
unsigned char x = 0;
for (i = 0; i < len; i++)
x |= a[i] ^ b[i];
return x;
}
/*
* For systems that don't provide an instruction counter register or equivalent.
*/
uint32_t OPENSSL_rdtsc(void)
{
return 0;
}
#endif
diff --git a/crypto/ct/ct_log.c b/crypto/ct/ct_log.c
index be6681dca74e..c1bca3e1415e 100644
--- a/crypto/ct/ct_log.c
+++ b/crypto/ct/ct_log.c
@@ -1,306 +1,306 @@
/*
* Copyright 2016-2018 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 <stdlib.h>
#include <string.h>
#include <openssl/conf.h>
#include <openssl/ct.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/safestack.h>
#include "internal/cryptlib.h"
/*
* Information about a CT log server.
*/
struct ctlog_st {
char *name;
uint8_t log_id[CT_V1_HASHLEN];
EVP_PKEY *public_key;
};
/*
* A store for multiple CTLOG instances.
* It takes ownership of any CTLOG instances added to it.
*/
struct ctlog_store_st {
STACK_OF(CTLOG) *logs;
};
/* The context when loading a CT log list from a CONF file. */
typedef struct ctlog_store_load_ctx_st {
CTLOG_STORE *log_store;
CONF *conf;
size_t invalid_log_entries;
} CTLOG_STORE_LOAD_CTX;
/*
* Creates an empty context for loading a CT log store.
* It should be populated before use.
*/
static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void);
/*
* Deletes a CT log store load context.
* Does not delete any of the fields.
*/
static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx);
static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void)
{
CTLOG_STORE_LOAD_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL)
CTerr(CT_F_CTLOG_STORE_LOAD_CTX_NEW, ERR_R_MALLOC_FAILURE);
return ctx;
}
static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx)
{
OPENSSL_free(ctx);
}
/* Converts a log's public key into a SHA256 log ID */
static int ct_v1_log_id_from_pkey(EVP_PKEY *pkey,
unsigned char log_id[CT_V1_HASHLEN])
{
int ret = 0;
unsigned char *pkey_der = NULL;
int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der);
if (pkey_der_len <= 0) {
CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, CT_R_LOG_KEY_INVALID);
goto err;
}
SHA256(pkey_der, pkey_der_len, log_id);
ret = 1;
err:
OPENSSL_free(pkey_der);
return ret;
}
CTLOG_STORE *CTLOG_STORE_new(void)
{
CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
CTerr(CT_F_CTLOG_STORE_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->logs = sk_CTLOG_new_null();
if (ret->logs == NULL)
goto err;
return ret;
err:
OPENSSL_free(ret);
return NULL;
}
void CTLOG_STORE_free(CTLOG_STORE *store)
{
if (store != NULL) {
sk_CTLOG_pop_free(store->logs, CTLOG_free);
OPENSSL_free(store);
}
}
static int ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section)
{
const char *description = NCONF_get_string(conf, section, "description");
char *pkey_base64;
if (description == NULL) {
CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_DESCRIPTION);
return 0;
}
pkey_base64 = NCONF_get_string(conf, section, "key");
if (pkey_base64 == NULL) {
CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_KEY);
return 0;
}
return CTLOG_new_from_base64(ct_log, pkey_base64, description);
}
int CTLOG_STORE_load_default_file(CTLOG_STORE *store)
{
- const char *fpath = getenv(CTLOG_FILE_EVP);
+ const char *fpath = ossl_safe_getenv(CTLOG_FILE_EVP);
if (fpath == NULL)
fpath = CTLOG_FILE;
return CTLOG_STORE_load_file(store, fpath);
}
/*
* Called by CONF_parse_list, which stops if this returns <= 0,
* Otherwise, one bad log entry would stop loading of any of
* the following log entries.
* It may stop parsing and returns -1 on any internal (malloc) error.
*/
static int ctlog_store_load_log(const char *log_name, int log_name_len,
void *arg)
{
CTLOG_STORE_LOAD_CTX *load_ctx = arg;
CTLOG *ct_log = NULL;
/* log_name may not be null-terminated, so fix that before using it */
char *tmp;
int ret = 0;
/* log_name will be NULL for empty list entries */
if (log_name == NULL)
return 1;
tmp = OPENSSL_strndup(log_name, log_name_len);
if (tmp == NULL)
goto mem_err;
ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp);
OPENSSL_free(tmp);
if (ret < 0) {
/* Propagate any internal error */
return ret;
}
if (ret == 0) {
/* If we can't load this log, record that fact and skip it */
++load_ctx->invalid_log_entries;
return 1;
}
if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) {
goto mem_err;
}
return 1;
mem_err:
CTLOG_free(ct_log);
CTerr(CT_F_CTLOG_STORE_LOAD_LOG, ERR_R_MALLOC_FAILURE);
return -1;
}
int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file)
{
int ret = 0;
char *enabled_logs;
CTLOG_STORE_LOAD_CTX* load_ctx = ctlog_store_load_ctx_new();
if (load_ctx == NULL)
return 0;
load_ctx->log_store = store;
load_ctx->conf = NCONF_new(NULL);
if (load_ctx->conf == NULL)
goto end;
if (NCONF_load(load_ctx->conf, file, NULL) <= 0) {
CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
goto end;
}
enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs");
if (enabled_logs == NULL) {
CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
goto end;
}
if (!CONF_parse_list(enabled_logs, ',', 1, ctlog_store_load_log, load_ctx) ||
load_ctx->invalid_log_entries > 0) {
CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
goto end;
}
ret = 1;
end:
NCONF_free(load_ctx->conf);
ctlog_store_load_ctx_free(load_ctx);
return ret;
}
/*
* Initialize a new CTLOG object.
* Takes ownership of the public key.
* Copies the name.
*/
CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name)
{
CTLOG *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->name = OPENSSL_strdup(name);
if (ret->name == NULL) {
CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1)
goto err;
ret->public_key = public_key;
return ret;
err:
CTLOG_free(ret);
return NULL;
}
/* Frees CT log and associated structures */
void CTLOG_free(CTLOG *log)
{
if (log != NULL) {
OPENSSL_free(log->name);
EVP_PKEY_free(log->public_key);
OPENSSL_free(log);
}
}
const char *CTLOG_get0_name(const CTLOG *log)
{
return log->name;
}
void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id,
size_t *log_id_len)
{
*log_id = log->log_id;
*log_id_len = CT_V1_HASHLEN;
}
EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log)
{
return log->public_key;
}
/*
* Given a log ID, finds the matching log.
* Returns NULL if no match found.
*/
const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store,
const uint8_t *log_id,
size_t log_id_len)
{
int i;
for (i = 0; i < sk_CTLOG_num(store->logs); ++i) {
const CTLOG *log = sk_CTLOG_value(store->logs, i);
if (memcmp(log->log_id, log_id, log_id_len) == 0)
return log;
}
return NULL;
}
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
index 46f4f01ee0e4..383d853b6d37 100644
--- a/crypto/dsa/dsa_gen.c
+++ b/crypto/dsa/dsa_gen.c
@@ -1,610 +1,616 @@
/*
* Copyright 1995-2018 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_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_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 ac1f65a51a75..7a0b0874c54e 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -1,395 +1,428 @@
/*
* Copyright 1995-2018 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, *m;
+ BIGNUM *l;
int ret = 0;
- int q_bits;
+ int q_bits, q_words;
if (!dsa->p || !dsa->q || !dsa->g) {
DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS);
return 0;
}
k = BN_new();
l = BN_new();
- m = BN_new();
- if (k == NULL || l == NULL || m == NULL)
+ 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);
- if (!BN_set_bit(k, q_bits)
- || !BN_set_bit(l, q_bits)
- || !BN_set_bit(m, q_bits))
+ 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.
*
- * TODO: revisit the BN_copy aiming for a memory access agnostic
- * conditional copy.
+ * 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(m, l, dsa->q)
- || !BN_copy(k, BN_num_bits(l) > q_bits ? l : m))
+ || !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 = BN_mod_inverse(NULL, k, dsa->q, ctx)) == NULL)
+ /* 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);
- BN_clear_free(m);
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/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index 21302685d877..a3164b5b2ed9 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -1,942 +1,942 @@
/*
* Copyright 2006-2018 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;
return 2;
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_62) <= 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_62;
+ 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_mult.c b/crypto/ec/ec_mult.c
index 7e1b3650e76a..0e0a5e1394af 100644
--- a/crypto/ec/ec_mult.c
+++ b/crypto/ec/ec_mult.c
@@ -1,970 +1,970 @@
/*
* Copyright 2001-2018 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 + 1) == NULL)
- || (bn_wexpand(lambda, group_top + 1) == NULL)) {
+ 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 + 1);
+ 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);
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)) {
/*-
* 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)) {
/*-
* 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_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 5bee031b9201..f4ad0749ef45 100644
--- a/crypto/ec/ec_pmeth.c
+++ b/crypto/ec/ec_pmeth.c
@@ -1,472 +1,472 @@
/*
* Copyright 2006-2018 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_62(key, *keylen, ktmp, ktmplen,
+ 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_62)
+ 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) {
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_kdf.c b/crypto/ec/ecdh_kdf.c
index d47486eb346d..d686f9d897df 100644
--- a/crypto/ec/ecdh_kdf.c
+++ b/crypto/ec/ecdh_kdf.c
@@ -1,68 +1,81 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2018 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/ec.h>
#include <openssl/evp.h>
+#include "ec_lcl.h"
-/* Key derivation function from X9.62/SECG */
+/* Key derivation function from X9.63/SECG */
/* Way more than we will ever need */
#define ECDH_KDF_MAX (1 << 30)
-int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
+int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
const unsigned char *Z, size_t Zlen,
const unsigned char *sinfo, size_t sinfolen,
const EVP_MD *md)
{
EVP_MD_CTX *mctx = NULL;
int rv = 0;
unsigned int i;
size_t mdlen;
unsigned char ctr[4];
if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX
|| Zlen > ECDH_KDF_MAX)
return 0;
mctx = EVP_MD_CTX_new();
if (mctx == NULL)
return 0;
mdlen = EVP_MD_size(md);
for (i = 1;; i++) {
unsigned char mtmp[EVP_MAX_MD_SIZE];
if (!EVP_DigestInit_ex(mctx, md, NULL))
goto err;
ctr[3] = i & 0xFF;
ctr[2] = (i >> 8) & 0xFF;
ctr[1] = (i >> 16) & 0xFF;
ctr[0] = (i >> 24) & 0xFF;
if (!EVP_DigestUpdate(mctx, Z, Zlen))
goto err;
if (!EVP_DigestUpdate(mctx, ctr, sizeof(ctr)))
goto err;
if (!EVP_DigestUpdate(mctx, sinfo, sinfolen))
goto err;
if (outlen >= mdlen) {
if (!EVP_DigestFinal(mctx, out, NULL))
goto err;
outlen -= mdlen;
if (outlen == 0)
break;
out += mdlen;
} else {
if (!EVP_DigestFinal(mctx, mtmp, NULL))
goto err;
memcpy(out, mtmp, outlen);
OPENSSL_cleanse(mtmp, mdlen);
break;
}
}
rv = 1;
err:
EVP_MD_CTX_free(mctx);
return rv;
}
+
+/*-
+ * The old name for ecdh_KDF_X9_63
+ * Retained for ABI compatibility
+ */
+int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ const unsigned char *sinfo, size_t sinfolen,
+ const EVP_MD *md)
+{
+ return ecdh_KDF_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md);
+}
diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c
index 9deaf5c6188c..4a0ba09a38be 100644
--- a/crypto/engine/eng_devcrypto.c
+++ b/crypto/engine/eng_devcrypto.c
@@ -1,678 +1,688 @@
/*
* Copyright 2017-2018 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 <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <assert.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/engine.h>
#include <openssl/objects.h>
#include <crypto/cryptodev.h>
#include "internal/engine.h"
#ifdef CRYPTO_ALGORITHM_MIN
# define CHECK_BSD_STYLE_MACROS
#endif
+/*
+ * ONE global file descriptor for all sessions. This allows operations
+ * such as digest session data copying (see digest_copy()), but is also
+ * saner... why re-open /dev/crypto for every session?
+ */
+static int cfd;
+
/******************************************************************************
*
* Ciphers
*
* Because they all do the same basic operation, we have only one set of
* method functions for them all to share, and a mapping table between
* NIDs and cryptodev IDs, with all the necessary size data.
*
*****/
struct cipher_ctx {
- int cfd;
struct session_op sess;
/* to pass from init to do_cipher */
const unsigned char *iv;
int op; /* COP_ENCRYPT or COP_DECRYPT */
};
static const struct cipher_data_st {
int nid;
int blocksize;
int keylen;
int ivlen;
int flags;
int devcryptoid;
} cipher_data[] = {
#ifndef OPENSSL_NO_DES
{ NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
{ NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
#endif
#ifndef OPENSSL_NO_BF
{ NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
#endif
#ifndef OPENSSL_NO_CAST
{ NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
#endif
{ NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
{ NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
{ NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
#ifndef OPENSSL_NO_RC4
- { NID_rc4, 1, 16, 0, CRYPTO_ARC4 },
+ { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
#endif
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
{ NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
{ NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
{ NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
#endif
#if 0 /* Not yet supported */
{ NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
{ NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
#endif
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
{ NID_aes_128_ecb, 16, 128 / 8, 16, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
{ NID_aes_192_ecb, 16, 192 / 8, 16, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
{ NID_aes_256_ecb, 16, 256 / 8, 16, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
#endif
#if 0 /* Not yet supported */
{ NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
{ NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
{ NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
#endif
#ifndef OPENSSL_NO_CAMELLIA
{ NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
CRYPTO_CAMELLIA_CBC },
{ NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
CRYPTO_CAMELLIA_CBC },
{ NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
CRYPTO_CAMELLIA_CBC },
#endif
};
static size_t get_cipher_data_index(int nid)
{
size_t i;
for (i = 0; i < OSSL_NELEM(cipher_data); i++)
if (nid == cipher_data[i].nid)
return i;
/*
* Code further down must make sure that only NIDs in the table above
* are used. If any other NID reaches this function, there's a grave
* coding error further down.
*/
assert("Code that never should be reached" == NULL);
return -1;
}
static const struct cipher_data_st *get_cipher_data(int nid)
{
return &cipher_data[get_cipher_data_index(nid)];
}
/*
* Following are the three necessary functions to map OpenSSL functionality
* with cryptodev.
*/
static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
struct cipher_ctx *cipher_ctx =
(struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
const struct cipher_data_st *cipher_d =
get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
- if ((cipher_ctx->cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
- SYSerr(SYS_F_OPEN, errno);
- return 0;
- }
-
memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
cipher_ctx->sess.cipher = cipher_d->devcryptoid;
cipher_ctx->sess.keylen = cipher_d->keylen;
cipher_ctx->sess.key = (void *)key;
cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
- if (ioctl(cipher_ctx->cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
+ if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
SYSerr(SYS_F_IOCTL, errno);
- close(cipher_ctx->cfd);
return 0;
}
return 1;
}
static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
struct cipher_ctx *cipher_ctx =
(struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
struct crypt_op cryp;
#if !defined(COP_FLAG_WRITE_IV)
unsigned char saved_iv[EVP_MAX_IV_LENGTH];
#endif
memset(&cryp, 0, sizeof(cryp));
cryp.ses = cipher_ctx->sess.ses;
cryp.len = inl;
cryp.src = (void *)in;
cryp.dst = (void *)out;
cryp.iv = (void *)EVP_CIPHER_CTX_iv_noconst(ctx);
cryp.op = cipher_ctx->op;
#if !defined(COP_FLAG_WRITE_IV)
cryp.flags = 0;
if (EVP_CIPHER_CTX_iv_length(ctx) > 0) {
assert(inl >= EVP_CIPHER_CTX_iv_length(ctx));
if (!EVP_CIPHER_CTX_encrypting(ctx)) {
unsigned char *ivptr = in + inl - EVP_CIPHER_CTX_iv_length(ctx);
memcpy(saved_iv, ivptr, EVP_CIPHER_CTX_iv_length(ctx));
}
}
#else
cryp.flags = COP_FLAG_WRITE_IV;
#endif
- if (ioctl(cipher_ctx->cfd, CIOCCRYPT, &cryp) < 0) {
+ if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
SYSerr(SYS_F_IOCTL, errno);
return 0;
}
#if !defined(COP_FLAG_WRITE_IV)
if (EVP_CIPHER_CTX_iv_length(ctx) > 0) {
unsigned char *ivptr = saved_iv;
assert(inl >= EVP_CIPHER_CTX_iv_length(ctx));
if (!EVP_CIPHER_CTX_encrypting(ctx))
ivptr = out + inl - EVP_CIPHER_CTX_iv_length(ctx);
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), ivptr,
EVP_CIPHER_CTX_iv_length(ctx));
}
#endif
return 1;
}
static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
{
struct cipher_ctx *cipher_ctx =
(struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- if (ioctl(cipher_ctx->cfd, CIOCFSESSION, &cipher_ctx->sess) < 0) {
+ if (ioctl(cfd, CIOCFSESSION, &cipher_ctx->sess.ses) < 0) {
SYSerr(SYS_F_IOCTL, errno);
return 0;
}
- if (close(cipher_ctx->cfd) < 0) {
- SYSerr(SYS_F_CLOSE, errno);
- return 0;
- }
return 1;
}
/*
* Keep a table of known nids and associated methods.
* Note that known_cipher_nids[] isn't necessarily indexed the same way as
* cipher_data[] above, which known_cipher_methods[] is.
*/
static int known_cipher_nids[OSSL_NELEM(cipher_data)];
static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
-static void prepare_cipher_methods()
+static void prepare_cipher_methods(void)
{
size_t i;
struct session_op sess;
- int cfd;
-
- if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0)
- return;
memset(&sess, 0, sizeof(sess));
sess.key = (void *)"01234567890123456789012345678901234567890123456789";
for (i = 0, known_cipher_nids_amount = 0;
i < OSSL_NELEM(cipher_data); i++) {
/*
* Check that the algo is really availably by trying to open and close
* a session.
*/
sess.cipher = cipher_data[i].devcryptoid;
sess.keylen = cipher_data[i].keylen;
if (ioctl(cfd, CIOCGSESSION, &sess) < 0
- || ioctl(cfd, CIOCFSESSION, &sess) < 0)
+ || ioctl(cfd, CIOCFSESSION, &sess.ses) < 0)
continue;
if ((known_cipher_methods[i] =
EVP_CIPHER_meth_new(cipher_data[i].nid,
cipher_data[i].blocksize,
cipher_data[i].keylen)) == NULL
|| !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
cipher_data[i].ivlen)
|| !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
cipher_data[i].flags
| EVP_CIPH_FLAG_DEFAULT_ASN1)
|| !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
|| !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
cipher_do_cipher)
|| !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
cipher_cleanup)
|| !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
sizeof(struct cipher_ctx))) {
EVP_CIPHER_meth_free(known_cipher_methods[i]);
known_cipher_methods[i] = NULL;
} else {
known_cipher_nids[known_cipher_nids_amount++] =
cipher_data[i].nid;
}
}
-
- close(cfd);
}
static const EVP_CIPHER *get_cipher_method(int nid)
{
size_t i = get_cipher_data_index(nid);
if (i == (size_t)-1)
return NULL;
return known_cipher_methods[i];
}
static int get_cipher_nids(const int **nids)
{
*nids = known_cipher_nids;
return known_cipher_nids_amount;
}
static void destroy_cipher_method(int nid)
{
size_t i = get_cipher_data_index(nid);
EVP_CIPHER_meth_free(known_cipher_methods[i]);
known_cipher_methods[i] = NULL;
}
-static void destroy_all_cipher_methods()
+static void destroy_all_cipher_methods(void)
{
size_t i;
for (i = 0; i < OSSL_NELEM(cipher_data); i++)
destroy_cipher_method(cipher_data[i].nid);
}
static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid)
{
if (cipher == NULL)
return get_cipher_nids(nids);
*cipher = get_cipher_method(nid);
return *cipher != NULL;
}
/*
* We only support digests if the cryptodev implementation supports multiple
- * data updates. Otherwise, we would be forced to maintain a cache, which is
- * perilous if there's a lot of data coming in (if someone wants to checksum
- * an OpenSSL tarball, for example).
+ * data updates and session copying. Otherwise, we would be forced to maintain
+ * a cache, which is perilous if there's a lot of data coming in (if someone
+ * wants to checksum an OpenSSL tarball, for example).
*/
-#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
+#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
+#define IMPLEMENT_DIGEST
/******************************************************************************
*
* Digests
*
* Because they all do the same basic operation, we have only one set of
* method functions for them all to share, and a mapping table between
* NIDs and cryptodev IDs, with all the necessary size data.
*
*****/
struct digest_ctx {
- int cfd;
struct session_op sess;
int init;
};
static const struct digest_data_st {
int nid;
int digestlen;
int devcryptoid;
} digest_data[] = {
#ifndef OPENSSL_NO_MD5
{ NID_md5, 16, CRYPTO_MD5 },
#endif
{ NID_sha1, 20, CRYPTO_SHA1 },
#ifndef OPENSSL_NO_RMD160
# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
{ NID_ripemd160, 20, CRYPTO_RIPEMD160 },
# endif
#endif
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
{ NID_sha224, 224 / 8, CRYPTO_SHA2_224 },
#endif
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
{ NID_sha256, 256 / 8, CRYPTO_SHA2_256 },
#endif
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
{ NID_sha384, 384 / 8, CRYPTO_SHA2_384 },
#endif
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
{ NID_sha512, 512 / 8, CRYPTO_SHA2_512 },
#endif
};
static size_t get_digest_data_index(int nid)
{
size_t i;
for (i = 0; i < OSSL_NELEM(digest_data); i++)
if (nid == digest_data[i].nid)
return i;
/*
* Code further down must make sure that only NIDs in the table above
* are used. If any other NID reaches this function, there's a grave
* coding error further down.
*/
assert("Code that never should be reached" == NULL);
return -1;
}
static const struct digest_data_st *get_digest_data(int nid)
{
return &digest_data[get_digest_data_index(nid)];
}
/*
* Following are the four necessary functions to map OpenSSL functionality
* with cryptodev.
*/
static int digest_init(EVP_MD_CTX *ctx)
{
struct digest_ctx *digest_ctx =
(struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
const struct digest_data_st *digest_d =
get_digest_data(EVP_MD_CTX_type(ctx));
- if (digest_ctx->init == 0
- && (digest_ctx->cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
- SYSerr(SYS_F_OPEN, errno);
- return 0;
- }
-
digest_ctx->init = 1;
memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
digest_ctx->sess.mac = digest_d->devcryptoid;
- if (ioctl(digest_ctx->cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
+ if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
SYSerr(SYS_F_IOCTL, errno);
- close(digest_ctx->cfd);
return 0;
}
return 1;
}
static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
void *res, unsigned int flags)
{
struct crypt_op cryp;
memset(&cryp, 0, sizeof(cryp));
cryp.ses = ctx->sess.ses;
cryp.len = srclen;
cryp.src = (void *)src;
cryp.dst = NULL;
cryp.mac = res;
cryp.flags = flags;
- return ioctl(ctx->cfd, CIOCCRYPT, &cryp);
+ return ioctl(cfd, CIOCCRYPT, &cryp);
}
static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
{
struct digest_ctx *digest_ctx =
(struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
if (count == 0)
return 1;
if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) < 0) {
SYSerr(SYS_F_IOCTL, errno);
return 0;
}
return 1;
}
static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
{
struct digest_ctx *digest_ctx =
(struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
SYSerr(SYS_F_IOCTL, errno);
return 0;
}
- if (ioctl(digest_ctx->cfd, CIOCFSESSION, &digest_ctx->sess) < 0) {
+ if (ioctl(cfd, CIOCFSESSION, &digest_ctx->sess.ses) < 0) {
SYSerr(SYS_F_IOCTL, errno);
return 0;
}
return 1;
}
-static int digest_cleanup(EVP_MD_CTX *ctx)
+static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
+ struct digest_ctx *digest_from =
+ (struct digest_ctx *)EVP_MD_CTX_md_data(from);
+ struct digest_ctx *digest_to =
+ (struct digest_ctx *)EVP_MD_CTX_md_data(to);
+ struct cphash_op cphash;
+
+ if (digest_from == NULL)
+ return 1;
- if (close(digest_ctx->cfd) < 0) {
- SYSerr(SYS_F_CLOSE, errno);
+ if (digest_from->init != 1) {
+ SYSerr(SYS_F_IOCTL, EINVAL);
return 0;
}
+ if (!digest_init(to)) {
+ SYSerr(SYS_F_IOCTL, errno);
+ return 0;
+ }
+
+ cphash.src_ses = digest_from->sess.ses;
+ cphash.dst_ses = digest_to->sess.ses;
+ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
+ SYSerr(SYS_F_IOCTL, errno);
+ return 0;
+ }
+ return 1;
+}
+
+static int digest_cleanup(EVP_MD_CTX *ctx)
+{
return 1;
}
/*
* Keep a table of known nids and associated methods.
* Note that known_digest_nids[] isn't necessarily indexed the same way as
* digest_data[] above, which known_digest_methods[] is.
*/
static int known_digest_nids[OSSL_NELEM(digest_data)];
static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
-static void prepare_digest_methods()
+static void prepare_digest_methods(void)
{
size_t i;
struct session_op sess;
- int cfd;
-
- if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0)
- return;
memset(&sess, 0, sizeof(sess));
for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
i++) {
/*
* Check that the algo is really availably by trying to open and close
* a session.
*/
sess.mac = digest_data[i].devcryptoid;
if (ioctl(cfd, CIOCGSESSION, &sess) < 0
- || ioctl(cfd, CIOCFSESSION, &sess) < 0)
+ || ioctl(cfd, CIOCFSESSION, &sess.ses) < 0)
continue;
if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
NID_undef)) == NULL
|| !EVP_MD_meth_set_result_size(known_digest_methods[i],
digest_data[i].digestlen)
|| !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
|| !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
|| !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
+ || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
|| !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
|| !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
sizeof(struct digest_ctx))) {
EVP_MD_meth_free(known_digest_methods[i]);
known_digest_methods[i] = NULL;
} else {
known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
}
}
-
- close(cfd);
}
static const EVP_MD *get_digest_method(int nid)
{
size_t i = get_digest_data_index(nid);
if (i == (size_t)-1)
return NULL;
return known_digest_methods[i];
}
static int get_digest_nids(const int **nids)
{
*nids = known_digest_nids;
return known_digest_nids_amount;
}
static void destroy_digest_method(int nid)
{
size_t i = get_digest_data_index(nid);
EVP_MD_meth_free(known_digest_methods[i]);
known_digest_methods[i] = NULL;
}
-static void destroy_all_digest_methods()
+static void destroy_all_digest_methods(void)
{
size_t i;
for (i = 0; i < OSSL_NELEM(digest_data); i++)
destroy_digest_method(digest_data[i].nid);
}
static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
const int **nids, int nid)
{
if (digest == NULL)
return get_digest_nids(nids);
*digest = get_digest_method(nid);
return *digest != NULL;
}
#endif
/******************************************************************************
*
* LOAD / UNLOAD
*
*****/
static int devcrypto_unload(ENGINE *e)
{
destroy_all_cipher_methods();
-#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
+#ifdef IMPLEMENT_DIGEST
destroy_all_digest_methods();
#endif
+
+ close(cfd);
+
return 1;
}
/*
* This engine is always built into libcrypto, so it doesn't offer any
* ability to be dynamically loadable.
*/
void engine_load_devcrypto_int()
{
ENGINE *e = NULL;
- if (access("/dev/crypto", R_OK | W_OK) < 0) {
- fprintf(stderr,
- "/dev/crypto not present, not enabling devcrypto engine\n");
+ if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+ fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
return;
}
prepare_cipher_methods();
-#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
+#ifdef IMPLEMENT_DIGEST
prepare_digest_methods();
#endif
- if ((e = ENGINE_new()) == NULL)
+ if ((e = ENGINE_new()) == NULL
+ || !ENGINE_set_destroy_function(e, devcrypto_unload)) {
+ ENGINE_free(e);
+ /*
+ * We know that devcrypto_unload() won't be called when one of the
+ * above two calls have failed, so we close cfd explicitly here to
+ * avoid leaking resources.
+ */
+ close(cfd);
return;
+ }
if (!ENGINE_set_id(e, "devcrypto")
|| !ENGINE_set_name(e, "/dev/crypto engine")
- || !ENGINE_set_destroy_function(e, devcrypto_unload)
/*
* Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
* implementations, it seems to only exist in FreeBSD, and regarding the
* parameters in its crypt_kop, the manual crypto(4) has this to say:
*
* The semantics of these arguments are currently undocumented.
*
* Reading through the FreeBSD source code doesn't give much more than
* their CRK_MOD_EXP implementation for ubsec.
*
* It doesn't look much better with cryptodev-linux. They have the crypt_kop
* structure as well as the command (CRK_*) in cryptodev.h, but no support
* seems to be implemented at all for the moment.
*
* At the time of writing, it seems impossible to write proper support for
* FreeBSD's asym features without some very deep knowledge and access to
* specific kernel modules.
*
* /Richard Levitte, 2017-05-11
*/
#if 0
# ifndef OPENSSL_NO_RSA
|| !ENGINE_set_RSA(e, devcrypto_rsa)
# endif
# ifndef OPENSSL_NO_DSA
|| !ENGINE_set_DSA(e, devcrypto_dsa)
# endif
# ifndef OPENSSL_NO_DH
|| !ENGINE_set_DH(e, devcrypto_dh)
# endif
# ifndef OPENSSL_NO_EC
|| !ENGINE_set_EC(e, devcrypto_ec)
# endif
#endif
|| !ENGINE_set_ciphers(e, devcrypto_ciphers)
-#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
+#ifdef IMPLEMENT_DIGEST
|| !ENGINE_set_digests(e, devcrypto_digests)
#endif
) {
ENGINE_free(e);
return;
}
ENGINE_add(e);
ENGINE_free(e); /* Loose our local reference */
ERR_clear_error();
}
diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c
index 4bc7ea173cdc..45c339c54157 100644
--- a/crypto/engine/eng_list.c
+++ b/crypto/engine/eng_list.c
@@ -1,350 +1,349 @@
/*
* Copyright 2001-2018 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 "eng_int.h"
/*
* The linked-list of pointers to engine types. engine_list_head incorporates
* an implicit structural reference but engine_list_tail does not - the
* latter is a computational optimization and only points to something that
* is already pointed to by its predecessor in the list (or engine_list_head
* itself). In the same way, the use of the "prev" pointer in each ENGINE is
* to save excessive list iteration, it doesn't correspond to an extra
* structural reference. Hence, engine_list_head, and each non-null "next"
* pointer account for the list itself assuming exactly 1 structural
* reference on each list member.
*/
static ENGINE *engine_list_head = NULL;
static ENGINE *engine_list_tail = NULL;
/*
* This cleanup function is only needed internally. If it should be called,
* we register it with the "engine_cleanup_int()" stack to be called during
* cleanup.
*/
static void engine_list_cleanup(void)
{
ENGINE *iterator = engine_list_head;
while (iterator != NULL) {
ENGINE_remove(iterator);
iterator = engine_list_head;
}
return;
}
/*
* These static functions starting with a lower case "engine_" always take
* place when global_engine_lock has been locked up.
*/
static int engine_list_add(ENGINE *e)
{
int conflict = 0;
ENGINE *iterator = NULL;
if (e == NULL) {
ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
iterator = engine_list_head;
while (iterator && !conflict) {
conflict = (strcmp(iterator->id, e->id) == 0);
iterator = iterator->next;
}
if (conflict) {
ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_CONFLICTING_ENGINE_ID);
return 0;
}
if (engine_list_head == NULL) {
/* We are adding to an empty list. */
if (engine_list_tail) {
ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
return 0;
}
engine_list_head = e;
e->prev = NULL;
/*
* The first time the list allocates, we should register the cleanup.
*/
engine_cleanup_add_last(engine_list_cleanup);
} else {
/* We are adding to the tail of an existing list. */
if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) {
ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
return 0;
}
engine_list_tail->next = e;
e->prev = engine_list_tail;
}
/*
* Having the engine in the list assumes a structural reference.
*/
e->struct_ref++;
engine_ref_debug(e, 0, 1);
/* However it came to be, e is the last item in the list. */
engine_list_tail = e;
e->next = NULL;
return 1;
}
static int engine_list_remove(ENGINE *e)
{
ENGINE *iterator;
if (e == NULL) {
ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/* We need to check that e is in our linked list! */
iterator = engine_list_head;
while (iterator && (iterator != e))
iterator = iterator->next;
if (iterator == NULL) {
ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE,
ENGINE_R_ENGINE_IS_NOT_IN_LIST);
return 0;
}
/* un-link e from the chain. */
if (e->next)
e->next->prev = e->prev;
if (e->prev)
e->prev->next = e->next;
/* Correct our head/tail if necessary. */
if (engine_list_head == e)
engine_list_head = e->next;
if (engine_list_tail == e)
engine_list_tail = e->prev;
engine_free_util(e, 0);
return 1;
}
/* Get the first/last "ENGINE" type available. */
ENGINE *ENGINE_get_first(void)
{
ENGINE *ret;
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
ENGINEerr(ENGINE_F_ENGINE_GET_FIRST, ERR_R_MALLOC_FAILURE);
return NULL;
}
CRYPTO_THREAD_write_lock(global_engine_lock);
ret = engine_list_head;
if (ret) {
ret->struct_ref++;
engine_ref_debug(ret, 0, 1);
}
CRYPTO_THREAD_unlock(global_engine_lock);
return ret;
}
ENGINE *ENGINE_get_last(void)
{
ENGINE *ret;
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
ENGINEerr(ENGINE_F_ENGINE_GET_LAST, ERR_R_MALLOC_FAILURE);
return NULL;
}
CRYPTO_THREAD_write_lock(global_engine_lock);
ret = engine_list_tail;
if (ret) {
ret->struct_ref++;
engine_ref_debug(ret, 0, 1);
}
CRYPTO_THREAD_unlock(global_engine_lock);
return ret;
}
/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
ENGINE *ENGINE_get_next(ENGINE *e)
{
ENGINE *ret = NULL;
if (e == NULL) {
ENGINEerr(ENGINE_F_ENGINE_GET_NEXT, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
CRYPTO_THREAD_write_lock(global_engine_lock);
ret = e->next;
if (ret) {
/* Return a valid structural reference to the next ENGINE */
ret->struct_ref++;
engine_ref_debug(ret, 0, 1);
}
CRYPTO_THREAD_unlock(global_engine_lock);
/* Release the structural reference to the previous ENGINE */
ENGINE_free(e);
return ret;
}
ENGINE *ENGINE_get_prev(ENGINE *e)
{
ENGINE *ret = NULL;
if (e == NULL) {
ENGINEerr(ENGINE_F_ENGINE_GET_PREV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
CRYPTO_THREAD_write_lock(global_engine_lock);
ret = e->prev;
if (ret) {
/* Return a valid structural reference to the next ENGINE */
ret->struct_ref++;
engine_ref_debug(ret, 0, 1);
}
CRYPTO_THREAD_unlock(global_engine_lock);
/* Release the structural reference to the previous ENGINE */
ENGINE_free(e);
return ret;
}
/* Add another "ENGINE" type into the list. */
int ENGINE_add(ENGINE *e)
{
int to_return = 1;
if (e == NULL) {
ENGINEerr(ENGINE_F_ENGINE_ADD, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((e->id == NULL) || (e->name == NULL)) {
ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_ID_OR_NAME_MISSING);
return 0;
}
CRYPTO_THREAD_write_lock(global_engine_lock);
if (!engine_list_add(e)) {
ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
to_return = 0;
}
CRYPTO_THREAD_unlock(global_engine_lock);
return to_return;
}
/* Remove an existing "ENGINE" type from the array. */
int ENGINE_remove(ENGINE *e)
{
int to_return = 1;
if (e == NULL) {
ENGINEerr(ENGINE_F_ENGINE_REMOVE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
CRYPTO_THREAD_write_lock(global_engine_lock);
if (!engine_list_remove(e)) {
ENGINEerr(ENGINE_F_ENGINE_REMOVE, ENGINE_R_INTERNAL_LIST_ERROR);
to_return = 0;
}
CRYPTO_THREAD_unlock(global_engine_lock);
return to_return;
}
static void engine_cpy(ENGINE *dest, const ENGINE *src)
{
dest->id = src->id;
dest->name = src->name;
#ifndef OPENSSL_NO_RSA
dest->rsa_meth = src->rsa_meth;
#endif
#ifndef OPENSSL_NO_DSA
dest->dsa_meth = src->dsa_meth;
#endif
#ifndef OPENSSL_NO_DH
dest->dh_meth = src->dh_meth;
#endif
#ifndef OPENSSL_NO_EC
dest->ec_meth = src->ec_meth;
#endif
dest->rand_meth = src->rand_meth;
dest->ciphers = src->ciphers;
dest->digests = src->digests;
dest->pkey_meths = src->pkey_meths;
dest->destroy = src->destroy;
dest->init = src->init;
dest->finish = src->finish;
dest->ctrl = src->ctrl;
dest->load_privkey = src->load_privkey;
dest->load_pubkey = src->load_pubkey;
dest->cmd_defns = src->cmd_defns;
dest->flags = src->flags;
}
ENGINE *ENGINE_by_id(const char *id)
{
ENGINE *iterator;
char *load_dir = NULL;
if (id == NULL) {
ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_MALLOC_FAILURE);
return NULL;
}
CRYPTO_THREAD_write_lock(global_engine_lock);
iterator = engine_list_head;
while (iterator && (strcmp(id, iterator->id) != 0))
iterator = iterator->next;
if (iterator != NULL) {
/*
* We need to return a structural reference. If this is an ENGINE
* type that returns copies, make a duplicate - otherwise increment
* the existing ENGINE's reference count.
*/
if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
ENGINE *cp = ENGINE_new();
if (cp == NULL)
iterator = NULL;
else {
engine_cpy(cp, iterator);
iterator = cp;
}
} else {
iterator->struct_ref++;
engine_ref_debug(iterator, 0, 1);
}
}
CRYPTO_THREAD_unlock(global_engine_lock);
if (iterator != NULL)
return iterator;
/*
* Prevent infinite recursion if we're looking for the dynamic engine.
*/
if (strcmp(id, "dynamic")) {
- if (OPENSSL_issetugid()
- || (load_dir = getenv("OPENSSL_ENGINES")) == NULL)
+ if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL)
load_dir = ENGINESDIR;
iterator = ENGINE_by_id("dynamic");
if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
!ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
!ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
load_dir, 0) ||
!ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
!ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
goto notfound;
return iterator;
}
notfound:
ENGINE_free(iterator);
ENGINEerr(ENGINE_F_ENGINE_BY_ID, ENGINE_R_NO_SUCH_ENGINE);
ERR_add_error_data(2, "id=", id);
return NULL;
/* EEK! Experimental code ends */
}
int ENGINE_up_ref(ENGINE *e)
{
int i;
if (e == NULL) {
ENGINEerr(ENGINE_F_ENGINE_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock);
return 1;
}
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 2c8572ba64ad..5003d8735a4d 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1,3025 +1,3026 @@
# Copyright 1999-2018 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
# Function codes
ASN1_F_A2D_ASN1_OBJECT:100:a2d_ASN1_OBJECT
ASN1_F_A2I_ASN1_INTEGER:102:a2i_ASN1_INTEGER
ASN1_F_A2I_ASN1_STRING:103:a2i_ASN1_STRING
ASN1_F_APPEND_EXP:176:append_exp
ASN1_F_ASN1_BIO_INIT:113:asn1_bio_init
ASN1_F_ASN1_BIT_STRING_SET_BIT:183:ASN1_BIT_STRING_set_bit
ASN1_F_ASN1_CB:177:asn1_cb
ASN1_F_ASN1_CHECK_TLEN:104:asn1_check_tlen
ASN1_F_ASN1_COLLECT:106:asn1_collect
ASN1_F_ASN1_D2I_EX_PRIMITIVE:108:asn1_d2i_ex_primitive
ASN1_F_ASN1_D2I_FP:109:ASN1_d2i_fp
ASN1_F_ASN1_D2I_READ_BIO:107:asn1_d2i_read_bio
ASN1_F_ASN1_DIGEST:184:ASN1_digest
ASN1_F_ASN1_DO_ADB:110:asn1_do_adb
ASN1_F_ASN1_DO_LOCK:233:asn1_do_lock
ASN1_F_ASN1_DUP:111:ASN1_dup
ASN1_F_ASN1_ENC_SAVE:115:asn1_enc_save
ASN1_F_ASN1_EX_C2I:204:asn1_ex_c2i
ASN1_F_ASN1_FIND_END:190:asn1_find_end
ASN1_F_ASN1_GENERALIZEDTIME_ADJ:216:ASN1_GENERALIZEDTIME_adj
ASN1_F_ASN1_GENERATE_V3:178:ASN1_generate_v3
ASN1_F_ASN1_GET_INT64:224:asn1_get_int64
ASN1_F_ASN1_GET_OBJECT:114:ASN1_get_object
ASN1_F_ASN1_GET_UINT64:225:asn1_get_uint64
ASN1_F_ASN1_I2D_BIO:116:ASN1_i2d_bio
ASN1_F_ASN1_I2D_FP:117:ASN1_i2d_fp
ASN1_F_ASN1_ITEM_D2I_FP:206:ASN1_item_d2i_fp
ASN1_F_ASN1_ITEM_DUP:191:ASN1_item_dup
ASN1_F_ASN1_ITEM_EMBED_D2I:120:asn1_item_embed_d2i
ASN1_F_ASN1_ITEM_EMBED_NEW:121:asn1_item_embed_new
ASN1_F_ASN1_ITEM_FLAGS_I2D:118:asn1_item_flags_i2d
ASN1_F_ASN1_ITEM_I2D_BIO:192:ASN1_item_i2d_bio
ASN1_F_ASN1_ITEM_I2D_FP:193:ASN1_item_i2d_fp
ASN1_F_ASN1_ITEM_PACK:198:ASN1_item_pack
ASN1_F_ASN1_ITEM_SIGN:195:ASN1_item_sign
ASN1_F_ASN1_ITEM_SIGN_CTX:220:ASN1_item_sign_ctx
ASN1_F_ASN1_ITEM_UNPACK:199:ASN1_item_unpack
ASN1_F_ASN1_ITEM_VERIFY:197:ASN1_item_verify
ASN1_F_ASN1_MBSTRING_NCOPY:122:ASN1_mbstring_ncopy
ASN1_F_ASN1_OBJECT_NEW:123:ASN1_OBJECT_new
ASN1_F_ASN1_OUTPUT_DATA:214:asn1_output_data
ASN1_F_ASN1_PCTX_NEW:205:ASN1_PCTX_new
ASN1_F_ASN1_PRIMITIVE_NEW:119:asn1_primitive_new
ASN1_F_ASN1_SCTX_NEW:221:ASN1_SCTX_new
ASN1_F_ASN1_SIGN:128:ASN1_sign
ASN1_F_ASN1_STR2TYPE:179:asn1_str2type
ASN1_F_ASN1_STRING_GET_INT64:227:asn1_string_get_int64
ASN1_F_ASN1_STRING_GET_UINT64:230:asn1_string_get_uint64
ASN1_F_ASN1_STRING_SET:186:ASN1_STRING_set
ASN1_F_ASN1_STRING_TABLE_ADD:129:ASN1_STRING_TABLE_add
ASN1_F_ASN1_STRING_TO_BN:228:asn1_string_to_bn
ASN1_F_ASN1_STRING_TYPE_NEW:130:ASN1_STRING_type_new
ASN1_F_ASN1_TEMPLATE_EX_D2I:132:asn1_template_ex_d2i
ASN1_F_ASN1_TEMPLATE_NEW:133:asn1_template_new
ASN1_F_ASN1_TEMPLATE_NOEXP_D2I:131:asn1_template_noexp_d2i
ASN1_F_ASN1_TIME_ADJ:217:ASN1_TIME_adj
ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING:134:ASN1_TYPE_get_int_octetstring
ASN1_F_ASN1_TYPE_GET_OCTETSTRING:135:ASN1_TYPE_get_octetstring
ASN1_F_ASN1_UTCTIME_ADJ:218:ASN1_UTCTIME_adj
ASN1_F_ASN1_VERIFY:137:ASN1_verify
ASN1_F_B64_READ_ASN1:209:b64_read_asn1
ASN1_F_B64_WRITE_ASN1:210:B64_write_ASN1
ASN1_F_BIO_NEW_NDEF:208:BIO_new_NDEF
ASN1_F_BITSTR_CB:180:bitstr_cb
ASN1_F_BN_TO_ASN1_STRING:229:bn_to_asn1_string
ASN1_F_C2I_ASN1_BIT_STRING:189:c2i_ASN1_BIT_STRING
ASN1_F_C2I_ASN1_INTEGER:194:c2i_ASN1_INTEGER
ASN1_F_C2I_ASN1_OBJECT:196:c2i_ASN1_OBJECT
ASN1_F_C2I_IBUF:226:c2i_ibuf
ASN1_F_C2I_UINT64_INT:101:c2i_uint64_int
ASN1_F_COLLECT_DATA:140:collect_data
ASN1_F_D2I_ASN1_OBJECT:147:d2i_ASN1_OBJECT
ASN1_F_D2I_ASN1_UINTEGER:150:d2i_ASN1_UINTEGER
ASN1_F_D2I_AUTOPRIVATEKEY:207:d2i_AutoPrivateKey
ASN1_F_D2I_PRIVATEKEY:154:d2i_PrivateKey
ASN1_F_D2I_PUBLICKEY:155:d2i_PublicKey
ASN1_F_DO_BUF:142:do_buf
ASN1_F_DO_CREATE:124:do_create
ASN1_F_DO_DUMP:125:do_dump
ASN1_F_DO_TCREATE:222:do_tcreate
ASN1_F_I2A_ASN1_OBJECT:126:i2a_ASN1_OBJECT
ASN1_F_I2D_ASN1_BIO_STREAM:211:i2d_ASN1_bio_stream
ASN1_F_I2D_ASN1_OBJECT:143:i2d_ASN1_OBJECT
ASN1_F_I2D_DSA_PUBKEY:161:i2d_DSA_PUBKEY
ASN1_F_I2D_EC_PUBKEY:181:i2d_EC_PUBKEY
ASN1_F_I2D_PRIVATEKEY:163:i2d_PrivateKey
ASN1_F_I2D_PUBLICKEY:164:i2d_PublicKey
ASN1_F_I2D_RSA_PUBKEY:165:i2d_RSA_PUBKEY
ASN1_F_LONG_C2I:166:long_c2i
ASN1_F_NDEF_PREFIX:127:ndef_prefix
ASN1_F_NDEF_SUFFIX:136:ndef_suffix
ASN1_F_OID_MODULE_INIT:174:oid_module_init
ASN1_F_PARSE_TAGGING:182:parse_tagging
ASN1_F_PKCS5_PBE2_SET_IV:167:PKCS5_pbe2_set_iv
ASN1_F_PKCS5_PBE2_SET_SCRYPT:231:PKCS5_pbe2_set_scrypt
ASN1_F_PKCS5_PBE_SET:202:PKCS5_pbe_set
ASN1_F_PKCS5_PBE_SET0_ALGOR:215:PKCS5_pbe_set0_algor
ASN1_F_PKCS5_PBKDF2_SET:219:PKCS5_pbkdf2_set
ASN1_F_PKCS5_SCRYPT_SET:232:pkcs5_scrypt_set
ASN1_F_SMIME_READ_ASN1:212:SMIME_read_ASN1
ASN1_F_SMIME_TEXT:213:SMIME_text
ASN1_F_STABLE_GET:138:stable_get
ASN1_F_STBL_MODULE_INIT:223:stbl_module_init
ASN1_F_UINT32_C2I:105:uint32_c2i
ASN1_F_UINT32_NEW:139:uint32_new
ASN1_F_UINT64_C2I:112:uint64_c2i
ASN1_F_UINT64_NEW:141:uint64_new
ASN1_F_X509_CRL_ADD0_REVOKED:169:X509_CRL_add0_revoked
ASN1_F_X509_INFO_NEW:170:X509_INFO_new
ASN1_F_X509_NAME_ENCODE:203:x509_name_encode
ASN1_F_X509_NAME_EX_D2I:158:x509_name_ex_d2i
ASN1_F_X509_NAME_EX_NEW:171:x509_name_ex_new
ASN1_F_X509_PKEY_NEW:173:X509_PKEY_new
ASYNC_F_ASYNC_CTX_NEW:100:async_ctx_new
ASYNC_F_ASYNC_INIT_THREAD:101:ASYNC_init_thread
ASYNC_F_ASYNC_JOB_NEW:102:async_job_new
ASYNC_F_ASYNC_PAUSE_JOB:103:ASYNC_pause_job
ASYNC_F_ASYNC_START_FUNC:104:async_start_func
ASYNC_F_ASYNC_START_JOB:105:ASYNC_start_job
ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD:106:ASYNC_WAIT_CTX_set_wait_fd
BIO_F_ACPT_STATE:100:acpt_state
BIO_F_ADDRINFO_WRAP:148:addrinfo_wrap
BIO_F_ADDR_STRINGS:134:addr_strings
BIO_F_BIO_ACCEPT:101:BIO_accept
BIO_F_BIO_ACCEPT_EX:137:BIO_accept_ex
BIO_F_BIO_ACCEPT_NEW:152:BIO_ACCEPT_new
BIO_F_BIO_ADDR_NEW:144:BIO_ADDR_new
BIO_F_BIO_BIND:147:BIO_bind
BIO_F_BIO_CALLBACK_CTRL:131:BIO_callback_ctrl
BIO_F_BIO_CONNECT:138:BIO_connect
BIO_F_BIO_CONNECT_NEW:153:BIO_CONNECT_new
BIO_F_BIO_CTRL:103:BIO_ctrl
BIO_F_BIO_GETS:104:BIO_gets
BIO_F_BIO_GET_HOST_IP:106:BIO_get_host_ip
BIO_F_BIO_GET_NEW_INDEX:102:BIO_get_new_index
BIO_F_BIO_GET_PORT:107:BIO_get_port
BIO_F_BIO_LISTEN:139:BIO_listen
BIO_F_BIO_LOOKUP:135:BIO_lookup
BIO_F_BIO_LOOKUP_EX:143:BIO_lookup_ex
BIO_F_BIO_MAKE_PAIR:121:bio_make_pair
BIO_F_BIO_METH_NEW:146:BIO_meth_new
BIO_F_BIO_NEW:108:BIO_new
BIO_F_BIO_NEW_DGRAM_SCTP:145:BIO_new_dgram_sctp
BIO_F_BIO_NEW_FILE:109:BIO_new_file
BIO_F_BIO_NEW_MEM_BUF:126:BIO_new_mem_buf
BIO_F_BIO_NREAD:123:BIO_nread
BIO_F_BIO_NREAD0:124:BIO_nread0
BIO_F_BIO_NWRITE:125:BIO_nwrite
BIO_F_BIO_NWRITE0:122:BIO_nwrite0
BIO_F_BIO_PARSE_HOSTSERV:136:BIO_parse_hostserv
BIO_F_BIO_PUTS:110:BIO_puts
BIO_F_BIO_READ:111:BIO_read
BIO_F_BIO_READ_EX:105:BIO_read_ex
BIO_F_BIO_READ_INTERN:120:bio_read_intern
BIO_F_BIO_SOCKET:140:BIO_socket
BIO_F_BIO_SOCKET_NBIO:142:BIO_socket_nbio
BIO_F_BIO_SOCK_INFO:141:BIO_sock_info
BIO_F_BIO_SOCK_INIT:112:BIO_sock_init
BIO_F_BIO_WRITE:113:BIO_write
BIO_F_BIO_WRITE_EX:119:BIO_write_ex
BIO_F_BIO_WRITE_INTERN:128:bio_write_intern
BIO_F_BUFFER_CTRL:114:buffer_ctrl
BIO_F_CONN_CTRL:127:conn_ctrl
BIO_F_CONN_STATE:115:conn_state
BIO_F_DGRAM_SCTP_NEW:149:dgram_sctp_new
BIO_F_DGRAM_SCTP_READ:132:dgram_sctp_read
BIO_F_DGRAM_SCTP_WRITE:133:dgram_sctp_write
BIO_F_DOAPR_OUTCH:150:doapr_outch
BIO_F_FILE_CTRL:116:file_ctrl
BIO_F_FILE_READ:130:file_read
BIO_F_LINEBUFFER_CTRL:129:linebuffer_ctrl
BIO_F_LINEBUFFER_NEW:151:linebuffer_new
BIO_F_MEM_WRITE:117:mem_write
BIO_F_NBIOF_NEW:154:nbiof_new
BIO_F_SLG_WRITE:155:slg_write
BIO_F_SSL_NEW:118:SSL_new
BN_F_BNRAND:127:bnrand
BN_F_BNRAND_RANGE:138:bnrand_range
BN_F_BN_BLINDING_CONVERT_EX:100:BN_BLINDING_convert_ex
BN_F_BN_BLINDING_CREATE_PARAM:128:BN_BLINDING_create_param
BN_F_BN_BLINDING_INVERT_EX:101:BN_BLINDING_invert_ex
BN_F_BN_BLINDING_NEW:102:BN_BLINDING_new
BN_F_BN_BLINDING_UPDATE:103:BN_BLINDING_update
BN_F_BN_BN2DEC:104:BN_bn2dec
BN_F_BN_BN2HEX:105:BN_bn2hex
BN_F_BN_COMPUTE_WNAF:142:bn_compute_wNAF
BN_F_BN_CTX_GET:116:BN_CTX_get
BN_F_BN_CTX_NEW:106:BN_CTX_new
BN_F_BN_CTX_START:129:BN_CTX_start
BN_F_BN_DIV:107:BN_div
BN_F_BN_DIV_RECP:130:BN_div_recp
BN_F_BN_EXP:123:BN_exp
BN_F_BN_EXPAND_INTERNAL:120:bn_expand_internal
BN_F_BN_GENCB_NEW:143:BN_GENCB_new
BN_F_BN_GENERATE_DSA_NONCE:140:BN_generate_dsa_nonce
BN_F_BN_GENERATE_PRIME_EX:141:BN_generate_prime_ex
BN_F_BN_GF2M_MOD:131:BN_GF2m_mod
BN_F_BN_GF2M_MOD_EXP:132:BN_GF2m_mod_exp
BN_F_BN_GF2M_MOD_MUL:133:BN_GF2m_mod_mul
BN_F_BN_GF2M_MOD_SOLVE_QUAD:134:BN_GF2m_mod_solve_quad
BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR:135:BN_GF2m_mod_solve_quad_arr
BN_F_BN_GF2M_MOD_SQR:136:BN_GF2m_mod_sqr
BN_F_BN_GF2M_MOD_SQRT:137:BN_GF2m_mod_sqrt
BN_F_BN_LSHIFT:145:BN_lshift
BN_F_BN_MOD_EXP2_MONT:118:BN_mod_exp2_mont
BN_F_BN_MOD_EXP_MONT:109:BN_mod_exp_mont
BN_F_BN_MOD_EXP_MONT_CONSTTIME:124:BN_mod_exp_mont_consttime
BN_F_BN_MOD_EXP_MONT_WORD:117:BN_mod_exp_mont_word
BN_F_BN_MOD_EXP_RECP:125:BN_mod_exp_recp
BN_F_BN_MOD_EXP_SIMPLE:126:BN_mod_exp_simple
BN_F_BN_MOD_INVERSE:110:BN_mod_inverse
BN_F_BN_MOD_INVERSE_NO_BRANCH:139:BN_mod_inverse_no_branch
BN_F_BN_MOD_LSHIFT_QUICK:119:BN_mod_lshift_quick
BN_F_BN_MOD_SQRT:121:BN_mod_sqrt
BN_F_BN_MONT_CTX_NEW:149:BN_MONT_CTX_new
BN_F_BN_MPI2BN:112:BN_mpi2bn
BN_F_BN_NEW:113:BN_new
BN_F_BN_POOL_GET:147:BN_POOL_get
BN_F_BN_RAND:114:BN_rand
BN_F_BN_RAND_RANGE:122:BN_rand_range
BN_F_BN_RECP_CTX_NEW:150:BN_RECP_CTX_new
BN_F_BN_RSHIFT:146:BN_rshift
BN_F_BN_SET_WORDS:144:bn_set_words
BN_F_BN_STACK_PUSH:148:BN_STACK_push
BN_F_BN_USUB:115:BN_usub
BUF_F_BUF_MEM_GROW:100:BUF_MEM_grow
BUF_F_BUF_MEM_GROW_CLEAN:105:BUF_MEM_grow_clean
BUF_F_BUF_MEM_NEW:101:BUF_MEM_new
CMS_F_CHECK_CONTENT:99:check_content
CMS_F_CMS_ADD0_CERT:164:CMS_add0_cert
CMS_F_CMS_ADD0_RECIPIENT_KEY:100:CMS_add0_recipient_key
CMS_F_CMS_ADD0_RECIPIENT_PASSWORD:165:CMS_add0_recipient_password
CMS_F_CMS_ADD1_RECEIPTREQUEST:158:CMS_add1_ReceiptRequest
CMS_F_CMS_ADD1_RECIPIENT_CERT:101:CMS_add1_recipient_cert
CMS_F_CMS_ADD1_SIGNER:102:CMS_add1_signer
CMS_F_CMS_ADD1_SIGNINGTIME:103:cms_add1_signingTime
CMS_F_CMS_COMPRESS:104:CMS_compress
CMS_F_CMS_COMPRESSEDDATA_CREATE:105:cms_CompressedData_create
CMS_F_CMS_COMPRESSEDDATA_INIT_BIO:106:cms_CompressedData_init_bio
CMS_F_CMS_COPY_CONTENT:107:cms_copy_content
CMS_F_CMS_COPY_MESSAGEDIGEST:108:cms_copy_messageDigest
CMS_F_CMS_DATA:109:CMS_data
CMS_F_CMS_DATAFINAL:110:CMS_dataFinal
CMS_F_CMS_DATAINIT:111:CMS_dataInit
CMS_F_CMS_DECRYPT:112:CMS_decrypt
CMS_F_CMS_DECRYPT_SET1_KEY:113:CMS_decrypt_set1_key
CMS_F_CMS_DECRYPT_SET1_PASSWORD:166:CMS_decrypt_set1_password
CMS_F_CMS_DECRYPT_SET1_PKEY:114:CMS_decrypt_set1_pkey
CMS_F_CMS_DIGESTALGORITHM_FIND_CTX:115:cms_DigestAlgorithm_find_ctx
CMS_F_CMS_DIGESTALGORITHM_INIT_BIO:116:cms_DigestAlgorithm_init_bio
CMS_F_CMS_DIGESTEDDATA_DO_FINAL:117:cms_DigestedData_do_final
CMS_F_CMS_DIGEST_VERIFY:118:CMS_digest_verify
CMS_F_CMS_ENCODE_RECEIPT:161:cms_encode_Receipt
CMS_F_CMS_ENCRYPT:119:CMS_encrypt
CMS_F_CMS_ENCRYPTEDCONTENT_INIT:179:cms_EncryptedContent_init
CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO:120:cms_EncryptedContent_init_bio
CMS_F_CMS_ENCRYPTEDDATA_DECRYPT:121:CMS_EncryptedData_decrypt
CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT:122:CMS_EncryptedData_encrypt
CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY:123:CMS_EncryptedData_set1_key
CMS_F_CMS_ENVELOPEDDATA_CREATE:124:CMS_EnvelopedData_create
CMS_F_CMS_ENVELOPEDDATA_INIT_BIO:125:cms_EnvelopedData_init_bio
CMS_F_CMS_ENVELOPED_DATA_INIT:126:cms_enveloped_data_init
CMS_F_CMS_ENV_ASN1_CTRL:171:cms_env_asn1_ctrl
CMS_F_CMS_FINAL:127:CMS_final
CMS_F_CMS_GET0_CERTIFICATE_CHOICES:128:cms_get0_certificate_choices
CMS_F_CMS_GET0_CONTENT:129:CMS_get0_content
CMS_F_CMS_GET0_ECONTENT_TYPE:130:cms_get0_econtent_type
CMS_F_CMS_GET0_ENVELOPED:131:cms_get0_enveloped
CMS_F_CMS_GET0_REVOCATION_CHOICES:132:cms_get0_revocation_choices
CMS_F_CMS_GET0_SIGNED:133:cms_get0_signed
CMS_F_CMS_MSGSIGDIGEST_ADD1:162:cms_msgSigDigest_add1
CMS_F_CMS_RECEIPTREQUEST_CREATE0:159:CMS_ReceiptRequest_create0
CMS_F_CMS_RECEIPT_VERIFY:160:cms_Receipt_verify
CMS_F_CMS_RECIPIENTINFO_DECRYPT:134:CMS_RecipientInfo_decrypt
CMS_F_CMS_RECIPIENTINFO_ENCRYPT:169:CMS_RecipientInfo_encrypt
CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT:178:cms_RecipientInfo_kari_encrypt
CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG:175:CMS_RecipientInfo_kari_get0_alg
CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID:173:\
CMS_RecipientInfo_kari_get0_orig_id
CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS:172:CMS_RecipientInfo_kari_get0_reks
CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP:174:CMS_RecipientInfo_kari_orig_id_cmp
CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT:135:cms_RecipientInfo_kekri_decrypt
CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT:136:cms_RecipientInfo_kekri_encrypt
CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID:137:CMS_RecipientInfo_kekri_get0_id
CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP:138:CMS_RecipientInfo_kekri_id_cmp
CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP:139:CMS_RecipientInfo_ktri_cert_cmp
CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT:140:cms_RecipientInfo_ktri_decrypt
CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT:141:cms_RecipientInfo_ktri_encrypt
CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS:142:CMS_RecipientInfo_ktri_get0_algs
CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID:143:\
CMS_RecipientInfo_ktri_get0_signer_id
CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT:167:cms_RecipientInfo_pwri_crypt
CMS_F_CMS_RECIPIENTINFO_SET0_KEY:144:CMS_RecipientInfo_set0_key
CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD:168:CMS_RecipientInfo_set0_password
CMS_F_CMS_RECIPIENTINFO_SET0_PKEY:145:CMS_RecipientInfo_set0_pkey
CMS_F_CMS_SD_ASN1_CTRL:170:cms_sd_asn1_ctrl
CMS_F_CMS_SET1_IAS:176:cms_set1_ias
CMS_F_CMS_SET1_KEYID:177:cms_set1_keyid
CMS_F_CMS_SET1_SIGNERIDENTIFIER:146:cms_set1_SignerIdentifier
CMS_F_CMS_SET_DETACHED:147:CMS_set_detached
CMS_F_CMS_SIGN:148:CMS_sign
CMS_F_CMS_SIGNED_DATA_INIT:149:cms_signed_data_init
CMS_F_CMS_SIGNERINFO_CONTENT_SIGN:150:cms_SignerInfo_content_sign
CMS_F_CMS_SIGNERINFO_SIGN:151:CMS_SignerInfo_sign
CMS_F_CMS_SIGNERINFO_VERIFY:152:CMS_SignerInfo_verify
CMS_F_CMS_SIGNERINFO_VERIFY_CERT:153:cms_signerinfo_verify_cert
CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT:154:CMS_SignerInfo_verify_content
CMS_F_CMS_SIGN_RECEIPT:163:CMS_sign_receipt
CMS_F_CMS_STREAM:155:CMS_stream
CMS_F_CMS_UNCOMPRESS:156:CMS_uncompress
CMS_F_CMS_VERIFY:157:CMS_verify
CMS_F_KEK_UNWRAP_KEY:180:kek_unwrap_key
COMP_F_BIO_ZLIB_FLUSH:99:bio_zlib_flush
COMP_F_BIO_ZLIB_NEW:100:bio_zlib_new
COMP_F_BIO_ZLIB_READ:101:bio_zlib_read
COMP_F_BIO_ZLIB_WRITE:102:bio_zlib_write
COMP_F_COMP_CTX_NEW:103:COMP_CTX_new
CONF_F_CONF_DUMP_FP:104:CONF_dump_fp
CONF_F_CONF_LOAD:100:CONF_load
CONF_F_CONF_LOAD_FP:103:CONF_load_fp
CONF_F_CONF_PARSE_LIST:119:CONF_parse_list
CONF_F_DEF_LOAD:120:def_load
CONF_F_DEF_LOAD_BIO:121:def_load_bio
CONF_F_GET_NEXT_FILE:107:get_next_file
CONF_F_MODULE_ADD:122:module_add
CONF_F_MODULE_INIT:115:module_init
CONF_F_MODULE_LOAD_DSO:117:module_load_dso
CONF_F_MODULE_RUN:118:module_run
CONF_F_NCONF_DUMP_BIO:105:NCONF_dump_bio
CONF_F_NCONF_DUMP_FP:106:NCONF_dump_fp
CONF_F_NCONF_GET_NUMBER_E:112:NCONF_get_number_e
CONF_F_NCONF_GET_SECTION:108:NCONF_get_section
CONF_F_NCONF_GET_STRING:109:NCONF_get_string
CONF_F_NCONF_LOAD:113:NCONF_load
CONF_F_NCONF_LOAD_BIO:110:NCONF_load_bio
CONF_F_NCONF_LOAD_FP:114:NCONF_load_fp
CONF_F_NCONF_NEW:111:NCONF_new
CONF_F_PROCESS_INCLUDE:116:process_include
CONF_F_SSL_MODULE_INIT:123:ssl_module_init
CONF_F_STR_COPY:101:str_copy
CRYPTO_F_CMAC_CTX_NEW:120:CMAC_CTX_new
CRYPTO_F_CRYPTO_DUP_EX_DATA:110:CRYPTO_dup_ex_data
CRYPTO_F_CRYPTO_FREE_EX_DATA:111:CRYPTO_free_ex_data
CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX:100:CRYPTO_get_ex_new_index
CRYPTO_F_CRYPTO_MEMDUP:115:CRYPTO_memdup
CRYPTO_F_CRYPTO_NEW_EX_DATA:112:CRYPTO_new_ex_data
CRYPTO_F_CRYPTO_OCB128_COPY_CTX:121:CRYPTO_ocb128_copy_ctx
CRYPTO_F_CRYPTO_OCB128_INIT:122:CRYPTO_ocb128_init
CRYPTO_F_CRYPTO_SET_EX_DATA:102:CRYPTO_set_ex_data
CRYPTO_F_FIPS_MODE_SET:109:FIPS_mode_set
CRYPTO_F_GET_AND_LOCK:113:get_and_lock
CRYPTO_F_OPENSSL_ATEXIT:114:OPENSSL_atexit
CRYPTO_F_OPENSSL_BUF2HEXSTR:117:OPENSSL_buf2hexstr
CRYPTO_F_OPENSSL_FOPEN:119:openssl_fopen
CRYPTO_F_OPENSSL_HEXSTR2BUF:118:OPENSSL_hexstr2buf
CRYPTO_F_OPENSSL_INIT_CRYPTO:116:OPENSSL_init_crypto
CRYPTO_F_OPENSSL_LH_NEW:126:OPENSSL_LH_new
CRYPTO_F_OPENSSL_SK_DEEP_COPY:127:OPENSSL_sk_deep_copy
CRYPTO_F_OPENSSL_SK_DUP:128:OPENSSL_sk_dup
CRYPTO_F_PKEY_HMAC_INIT:123:pkey_hmac_init
CRYPTO_F_PKEY_POLY1305_INIT:124:pkey_poly1305_init
CRYPTO_F_PKEY_SIPHASH_INIT:125:pkey_siphash_init
CRYPTO_F_SK_RESERVE:129:sk_reserve
CT_F_CTLOG_NEW:117:CTLOG_new
CT_F_CTLOG_NEW_FROM_BASE64:118:CTLOG_new_from_base64
CT_F_CTLOG_NEW_FROM_CONF:119:ctlog_new_from_conf
CT_F_CTLOG_STORE_LOAD_CTX_NEW:122:ctlog_store_load_ctx_new
CT_F_CTLOG_STORE_LOAD_FILE:123:CTLOG_STORE_load_file
CT_F_CTLOG_STORE_LOAD_LOG:130:ctlog_store_load_log
CT_F_CTLOG_STORE_NEW:131:CTLOG_STORE_new
CT_F_CT_BASE64_DECODE:124:ct_base64_decode
CT_F_CT_POLICY_EVAL_CTX_NEW:133:CT_POLICY_EVAL_CTX_new
CT_F_CT_V1_LOG_ID_FROM_PKEY:125:ct_v1_log_id_from_pkey
CT_F_I2O_SCT:107:i2o_SCT
CT_F_I2O_SCT_LIST:108:i2o_SCT_LIST
CT_F_I2O_SCT_SIGNATURE:109:i2o_SCT_signature
CT_F_O2I_SCT:110:o2i_SCT
CT_F_O2I_SCT_LIST:111:o2i_SCT_LIST
CT_F_O2I_SCT_SIGNATURE:112:o2i_SCT_signature
CT_F_SCT_CTX_NEW:126:SCT_CTX_new
CT_F_SCT_CTX_VERIFY:128:SCT_CTX_verify
CT_F_SCT_NEW:100:SCT_new
CT_F_SCT_NEW_FROM_BASE64:127:SCT_new_from_base64
CT_F_SCT_SET0_LOG_ID:101:SCT_set0_log_id
CT_F_SCT_SET1_EXTENSIONS:114:SCT_set1_extensions
CT_F_SCT_SET1_LOG_ID:115:SCT_set1_log_id
CT_F_SCT_SET1_SIGNATURE:116:SCT_set1_signature
CT_F_SCT_SET_LOG_ENTRY_TYPE:102:SCT_set_log_entry_type
CT_F_SCT_SET_SIGNATURE_NID:103:SCT_set_signature_nid
CT_F_SCT_SET_VERSION:104:SCT_set_version
DH_F_COMPUTE_KEY:102:compute_key
DH_F_DHPARAMS_PRINT_FP:101:DHparams_print_fp
DH_F_DH_BUILTIN_GENPARAMS:106:dh_builtin_genparams
DH_F_DH_CHECK_EX:121:DH_check_ex
DH_F_DH_CHECK_PARAMS_EX:122:DH_check_params_ex
DH_F_DH_CHECK_PUB_KEY_EX:123:DH_check_pub_key_ex
DH_F_DH_CMS_DECRYPT:114:dh_cms_decrypt
DH_F_DH_CMS_SET_PEERKEY:115:dh_cms_set_peerkey
DH_F_DH_CMS_SET_SHARED_INFO:116:dh_cms_set_shared_info
DH_F_DH_METH_DUP:117:DH_meth_dup
DH_F_DH_METH_NEW:118:DH_meth_new
DH_F_DH_METH_SET1_NAME:119:DH_meth_set1_name
DH_F_DH_NEW_BY_NID:104:DH_new_by_nid
DH_F_DH_NEW_METHOD:105:DH_new_method
DH_F_DH_PARAM_DECODE:107:dh_param_decode
DH_F_DH_PKEY_PUBLIC_CHECK:124:dh_pkey_public_check
DH_F_DH_PRIV_DECODE:110:dh_priv_decode
DH_F_DH_PRIV_ENCODE:111:dh_priv_encode
DH_F_DH_PUB_DECODE:108:dh_pub_decode
DH_F_DH_PUB_ENCODE:109:dh_pub_encode
DH_F_DO_DH_PRINT:100:do_dh_print
DH_F_GENERATE_KEY:103:generate_key
DH_F_PKEY_DH_CTRL_STR:120:pkey_dh_ctrl_str
DH_F_PKEY_DH_DERIVE:112:pkey_dh_derive
DH_F_PKEY_DH_INIT:125:pkey_dh_init
DH_F_PKEY_DH_KEYGEN:113:pkey_dh_keygen
DSA_F_DSAPARAMS_PRINT:100:DSAparams_print
DSA_F_DSAPARAMS_PRINT_FP:101:DSAparams_print_fp
DSA_F_DSA_BUILTIN_PARAMGEN:125:dsa_builtin_paramgen
DSA_F_DSA_BUILTIN_PARAMGEN2:126:dsa_builtin_paramgen2
DSA_F_DSA_DO_SIGN:112:DSA_do_sign
DSA_F_DSA_DO_VERIFY:113:DSA_do_verify
DSA_F_DSA_METH_DUP:127:DSA_meth_dup
DSA_F_DSA_METH_NEW:128:DSA_meth_new
DSA_F_DSA_METH_SET1_NAME:129:DSA_meth_set1_name
DSA_F_DSA_NEW_METHOD:103:DSA_new_method
DSA_F_DSA_PARAM_DECODE:119:dsa_param_decode
DSA_F_DSA_PRINT_FP:105:DSA_print_fp
DSA_F_DSA_PRIV_DECODE:115:dsa_priv_decode
DSA_F_DSA_PRIV_ENCODE:116:dsa_priv_encode
DSA_F_DSA_PUB_DECODE:117:dsa_pub_decode
DSA_F_DSA_PUB_ENCODE:118:dsa_pub_encode
DSA_F_DSA_SIGN:106:DSA_sign
DSA_F_DSA_SIGN_SETUP:107:DSA_sign_setup
DSA_F_DSA_SIG_NEW:102:DSA_SIG_new
DSA_F_OLD_DSA_PRIV_DECODE:122:old_dsa_priv_decode
DSA_F_PKEY_DSA_CTRL:120:pkey_dsa_ctrl
DSA_F_PKEY_DSA_CTRL_STR:104:pkey_dsa_ctrl_str
DSA_F_PKEY_DSA_KEYGEN:121:pkey_dsa_keygen
DSO_F_DLFCN_BIND_FUNC:100:dlfcn_bind_func
DSO_F_DLFCN_LOAD:102:dlfcn_load
DSO_F_DLFCN_MERGER:130:dlfcn_merger
DSO_F_DLFCN_NAME_CONVERTER:123:dlfcn_name_converter
DSO_F_DLFCN_UNLOAD:103:dlfcn_unload
DSO_F_DL_BIND_FUNC:104:dl_bind_func
DSO_F_DL_LOAD:106:dl_load
DSO_F_DL_MERGER:131:dl_merger
DSO_F_DL_NAME_CONVERTER:124:dl_name_converter
DSO_F_DL_UNLOAD:107:dl_unload
DSO_F_DSO_BIND_FUNC:108:DSO_bind_func
DSO_F_DSO_CONVERT_FILENAME:126:DSO_convert_filename
DSO_F_DSO_CTRL:110:DSO_ctrl
DSO_F_DSO_FREE:111:DSO_free
DSO_F_DSO_GET_FILENAME:127:DSO_get_filename
DSO_F_DSO_GLOBAL_LOOKUP:139:DSO_global_lookup
DSO_F_DSO_LOAD:112:DSO_load
DSO_F_DSO_MERGE:132:DSO_merge
DSO_F_DSO_NEW_METHOD:113:DSO_new_method
DSO_F_DSO_PATHBYADDR:105:DSO_pathbyaddr
DSO_F_DSO_SET_FILENAME:129:DSO_set_filename
DSO_F_DSO_UP_REF:114:DSO_up_ref
DSO_F_VMS_BIND_SYM:115:vms_bind_sym
DSO_F_VMS_LOAD:116:vms_load
DSO_F_VMS_MERGER:133:vms_merger
DSO_F_VMS_UNLOAD:117:vms_unload
DSO_F_WIN32_BIND_FUNC:101:win32_bind_func
DSO_F_WIN32_GLOBALLOOKUP:142:win32_globallookup
DSO_F_WIN32_JOINER:135:win32_joiner
DSO_F_WIN32_LOAD:120:win32_load
DSO_F_WIN32_MERGER:134:win32_merger
DSO_F_WIN32_NAME_CONVERTER:125:win32_name_converter
DSO_F_WIN32_PATHBYADDR:109:*
DSO_F_WIN32_SPLITTER:136:win32_splitter
DSO_F_WIN32_UNLOAD:121:win32_unload
EC_F_BN_TO_FELEM:224:BN_to_felem
EC_F_D2I_ECPARAMETERS:144:d2i_ECParameters
EC_F_D2I_ECPKPARAMETERS:145:d2i_ECPKParameters
EC_F_D2I_ECPRIVATEKEY:146:d2i_ECPrivateKey
EC_F_DO_EC_KEY_PRINT:221:do_EC_KEY_print
EC_F_ECDH_CMS_DECRYPT:238:ecdh_cms_decrypt
EC_F_ECDH_CMS_SET_SHARED_INFO:239:ecdh_cms_set_shared_info
EC_F_ECDH_COMPUTE_KEY:246:ECDH_compute_key
EC_F_ECDH_SIMPLE_COMPUTE_KEY:257:ecdh_simple_compute_key
EC_F_ECDSA_DO_SIGN_EX:251:ECDSA_do_sign_ex
EC_F_ECDSA_DO_VERIFY:252:ECDSA_do_verify
EC_F_ECDSA_SIGN_EX:254:ECDSA_sign_ex
EC_F_ECDSA_SIGN_SETUP:248:ECDSA_sign_setup
EC_F_ECDSA_SIG_NEW:265:ECDSA_SIG_new
EC_F_ECDSA_VERIFY:253:ECDSA_verify
EC_F_ECD_ITEM_VERIFY:270:ecd_item_verify
EC_F_ECKEY_PARAM2TYPE:223:eckey_param2type
EC_F_ECKEY_PARAM_DECODE:212:eckey_param_decode
EC_F_ECKEY_PRIV_DECODE:213:eckey_priv_decode
EC_F_ECKEY_PRIV_ENCODE:214:eckey_priv_encode
EC_F_ECKEY_PUB_DECODE:215:eckey_pub_decode
EC_F_ECKEY_PUB_ENCODE:216:eckey_pub_encode
EC_F_ECKEY_TYPE2PARAM:220:eckey_type2param
EC_F_ECPARAMETERS_PRINT:147:ECParameters_print
EC_F_ECPARAMETERS_PRINT_FP:148:ECParameters_print_fp
EC_F_ECPKPARAMETERS_PRINT:149:ECPKParameters_print
EC_F_ECPKPARAMETERS_PRINT_FP:150:ECPKParameters_print_fp
EC_F_ECP_NISTZ256_GET_AFFINE:240:ecp_nistz256_get_affine
EC_F_ECP_NISTZ256_INV_MOD_ORD:275:ecp_nistz256_inv_mod_ord
EC_F_ECP_NISTZ256_MULT_PRECOMPUTE:243:ecp_nistz256_mult_precompute
EC_F_ECP_NISTZ256_POINTS_MUL:241:ecp_nistz256_points_mul
EC_F_ECP_NISTZ256_PRE_COMP_NEW:244:ecp_nistz256_pre_comp_new
EC_F_ECP_NISTZ256_WINDOWED_MUL:242:ecp_nistz256_windowed_mul
EC_F_ECX_KEY_OP:266:ecx_key_op
EC_F_ECX_PRIV_ENCODE:267:ecx_priv_encode
EC_F_ECX_PUB_ENCODE:268:ecx_pub_encode
EC_F_EC_ASN1_GROUP2CURVE:153:ec_asn1_group2curve
EC_F_EC_ASN1_GROUP2FIELDID:154:ec_asn1_group2fieldid
EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY:208:ec_GF2m_montgomery_point_multiply
EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT:159:\
ec_GF2m_simple_group_check_discriminant
EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE:195:ec_GF2m_simple_group_set_curve
EC_F_EC_GF2M_SIMPLE_LADDER_POST:285:ec_GF2m_simple_ladder_post
EC_F_EC_GF2M_SIMPLE_LADDER_PRE:288:ec_GF2m_simple_ladder_pre
EC_F_EC_GF2M_SIMPLE_OCT2POINT:160:ec_GF2m_simple_oct2point
EC_F_EC_GF2M_SIMPLE_POINT2OCT:161:ec_GF2m_simple_point2oct
EC_F_EC_GF2M_SIMPLE_POINTS_MUL:289:ec_GF2m_simple_points_mul
EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES:162:\
ec_GF2m_simple_point_get_affine_coordinates
EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES:163:\
ec_GF2m_simple_point_set_affine_coordinates
EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES:164:\
ec_GF2m_simple_set_compressed_coordinates
EC_F_EC_GFP_MONT_FIELD_DECODE:133:ec_GFp_mont_field_decode
EC_F_EC_GFP_MONT_FIELD_ENCODE:134:ec_GFp_mont_field_encode
EC_F_EC_GFP_MONT_FIELD_MUL:131:ec_GFp_mont_field_mul
EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE:209:ec_GFp_mont_field_set_to_one
EC_F_EC_GFP_MONT_FIELD_SQR:132:ec_GFp_mont_field_sqr
EC_F_EC_GFP_MONT_GROUP_SET_CURVE:189:ec_GFp_mont_group_set_curve
EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE:225:ec_GFp_nistp224_group_set_curve
EC_F_EC_GFP_NISTP224_POINTS_MUL:228:ec_GFp_nistp224_points_mul
EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES:226:\
ec_GFp_nistp224_point_get_affine_coordinates
EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE:230:ec_GFp_nistp256_group_set_curve
EC_F_EC_GFP_NISTP256_POINTS_MUL:231:ec_GFp_nistp256_points_mul
EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES:232:\
ec_GFp_nistp256_point_get_affine_coordinates
EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE:233:ec_GFp_nistp521_group_set_curve
EC_F_EC_GFP_NISTP521_POINTS_MUL:234:ec_GFp_nistp521_points_mul
EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES:235:\
ec_GFp_nistp521_point_get_affine_coordinates
EC_F_EC_GFP_NIST_FIELD_MUL:200:ec_GFp_nist_field_mul
EC_F_EC_GFP_NIST_FIELD_SQR:201:ec_GFp_nist_field_sqr
EC_F_EC_GFP_NIST_GROUP_SET_CURVE:202:ec_GFp_nist_group_set_curve
EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES:287:ec_GFp_simple_blind_coordinates
EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT:165:\
ec_GFp_simple_group_check_discriminant
EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE:166:ec_GFp_simple_group_set_curve
EC_F_EC_GFP_SIMPLE_MAKE_AFFINE:102:ec_GFp_simple_make_affine
EC_F_EC_GFP_SIMPLE_OCT2POINT:103:ec_GFp_simple_oct2point
EC_F_EC_GFP_SIMPLE_POINT2OCT:104:ec_GFp_simple_point2oct
EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE:137:ec_GFp_simple_points_make_affine
EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES:167:\
ec_GFp_simple_point_get_affine_coordinates
EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES:168:\
ec_GFp_simple_point_set_affine_coordinates
EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES:169:\
ec_GFp_simple_set_compressed_coordinates
EC_F_EC_GROUP_CHECK:170:EC_GROUP_check
EC_F_EC_GROUP_CHECK_DISCRIMINANT:171:EC_GROUP_check_discriminant
EC_F_EC_GROUP_COPY:106:EC_GROUP_copy
EC_F_EC_GROUP_GET_CURVE:291:EC_GROUP_get_curve
EC_F_EC_GROUP_GET_CURVE_GF2M:172:EC_GROUP_get_curve_GF2m
EC_F_EC_GROUP_GET_CURVE_GFP:130:EC_GROUP_get_curve_GFp
EC_F_EC_GROUP_GET_DEGREE:173:EC_GROUP_get_degree
EC_F_EC_GROUP_GET_ECPARAMETERS:261:EC_GROUP_get_ecparameters
EC_F_EC_GROUP_GET_ECPKPARAMETERS:262:EC_GROUP_get_ecpkparameters
EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS:193:EC_GROUP_get_pentanomial_basis
EC_F_EC_GROUP_GET_TRINOMIAL_BASIS:194:EC_GROUP_get_trinomial_basis
EC_F_EC_GROUP_NEW:108:EC_GROUP_new
EC_F_EC_GROUP_NEW_BY_CURVE_NAME:174:EC_GROUP_new_by_curve_name
EC_F_EC_GROUP_NEW_FROM_DATA:175:ec_group_new_from_data
EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS:263:EC_GROUP_new_from_ecparameters
EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS:264:EC_GROUP_new_from_ecpkparameters
EC_F_EC_GROUP_SET_CURVE:292:EC_GROUP_set_curve
EC_F_EC_GROUP_SET_CURVE_GF2M:176:EC_GROUP_set_curve_GF2m
EC_F_EC_GROUP_SET_CURVE_GFP:109:EC_GROUP_set_curve_GFp
EC_F_EC_GROUP_SET_GENERATOR:111:EC_GROUP_set_generator
EC_F_EC_GROUP_SET_SEED:286:EC_GROUP_set_seed
EC_F_EC_KEY_CHECK_KEY:177:EC_KEY_check_key
EC_F_EC_KEY_COPY:178:EC_KEY_copy
EC_F_EC_KEY_GENERATE_KEY:179:EC_KEY_generate_key
EC_F_EC_KEY_NEW:182:EC_KEY_new
EC_F_EC_KEY_NEW_METHOD:245:EC_KEY_new_method
EC_F_EC_KEY_OCT2PRIV:255:EC_KEY_oct2priv
EC_F_EC_KEY_PRINT:180:EC_KEY_print
EC_F_EC_KEY_PRINT_FP:181:EC_KEY_print_fp
EC_F_EC_KEY_PRIV2BUF:279:EC_KEY_priv2buf
EC_F_EC_KEY_PRIV2OCT:256:EC_KEY_priv2oct
EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES:229:\
EC_KEY_set_public_key_affine_coordinates
EC_F_EC_KEY_SIMPLE_CHECK_KEY:258:ec_key_simple_check_key
EC_F_EC_KEY_SIMPLE_OCT2PRIV:259:ec_key_simple_oct2priv
EC_F_EC_KEY_SIMPLE_PRIV2OCT:260:ec_key_simple_priv2oct
EC_F_EC_PKEY_CHECK:273:ec_pkey_check
EC_F_EC_PKEY_PARAM_CHECK:274:ec_pkey_param_check
EC_F_EC_POINTS_MAKE_AFFINE:136:EC_POINTs_make_affine
EC_F_EC_POINTS_MUL:290:EC_POINTs_mul
EC_F_EC_POINT_ADD:112:EC_POINT_add
EC_F_EC_POINT_BN2POINT:280:EC_POINT_bn2point
EC_F_EC_POINT_CMP:113:EC_POINT_cmp
EC_F_EC_POINT_COPY:114:EC_POINT_copy
EC_F_EC_POINT_DBL:115:EC_POINT_dbl
EC_F_EC_POINT_GET_AFFINE_COORDINATES:293:EC_POINT_get_affine_coordinates
EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M:183:\
EC_POINT_get_affine_coordinates_GF2m
EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP:116:EC_POINT_get_affine_coordinates_GFp
EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP:117:\
EC_POINT_get_Jprojective_coordinates_GFp
EC_F_EC_POINT_INVERT:210:EC_POINT_invert
EC_F_EC_POINT_IS_AT_INFINITY:118:EC_POINT_is_at_infinity
EC_F_EC_POINT_IS_ON_CURVE:119:EC_POINT_is_on_curve
EC_F_EC_POINT_MAKE_AFFINE:120:EC_POINT_make_affine
EC_F_EC_POINT_NEW:121:EC_POINT_new
EC_F_EC_POINT_OCT2POINT:122:EC_POINT_oct2point
EC_F_EC_POINT_POINT2BUF:281:EC_POINT_point2buf
EC_F_EC_POINT_POINT2OCT:123:EC_POINT_point2oct
EC_F_EC_POINT_SET_AFFINE_COORDINATES:294:EC_POINT_set_affine_coordinates
EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M:185:\
EC_POINT_set_affine_coordinates_GF2m
EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP:124:EC_POINT_set_affine_coordinates_GFp
EC_F_EC_POINT_SET_COMPRESSED_COORDINATES:295:EC_POINT_set_compressed_coordinates
EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M:186:\
EC_POINT_set_compressed_coordinates_GF2m
EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP:125:\
EC_POINT_set_compressed_coordinates_GFp
EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP:126:\
EC_POINT_set_Jprojective_coordinates_GFp
EC_F_EC_POINT_SET_TO_INFINITY:127:EC_POINT_set_to_infinity
EC_F_EC_PRE_COMP_NEW:196:ec_pre_comp_new
EC_F_EC_SCALAR_MUL_LADDER:284:ec_scalar_mul_ladder
EC_F_EC_WNAF_MUL:187:ec_wNAF_mul
EC_F_EC_WNAF_PRECOMPUTE_MULT:188:ec_wNAF_precompute_mult
EC_F_I2D_ECPARAMETERS:190:i2d_ECParameters
EC_F_I2D_ECPKPARAMETERS:191:i2d_ECPKParameters
EC_F_I2D_ECPRIVATEKEY:192:i2d_ECPrivateKey
EC_F_I2O_ECPUBLICKEY:151:i2o_ECPublicKey
EC_F_NISTP224_PRE_COMP_NEW:227:nistp224_pre_comp_new
EC_F_NISTP256_PRE_COMP_NEW:236:nistp256_pre_comp_new
EC_F_NISTP521_PRE_COMP_NEW:237:nistp521_pre_comp_new
EC_F_O2I_ECPUBLICKEY:152:o2i_ECPublicKey
EC_F_OLD_EC_PRIV_DECODE:222:old_ec_priv_decode
EC_F_OSSL_ECDH_COMPUTE_KEY:247:ossl_ecdh_compute_key
EC_F_OSSL_ECDSA_SIGN_SIG:249:ossl_ecdsa_sign_sig
EC_F_OSSL_ECDSA_VERIFY_SIG:250:ossl_ecdsa_verify_sig
EC_F_PKEY_ECD_CTRL:271:pkey_ecd_ctrl
EC_F_PKEY_ECD_DIGESTSIGN:272:pkey_ecd_digestsign
EC_F_PKEY_ECD_DIGESTSIGN25519:276:pkey_ecd_digestsign25519
EC_F_PKEY_ECD_DIGESTSIGN448:277:pkey_ecd_digestsign448
EC_F_PKEY_ECX_DERIVE:269:pkey_ecx_derive
EC_F_PKEY_EC_CTRL:197:pkey_ec_ctrl
EC_F_PKEY_EC_CTRL_STR:198:pkey_ec_ctrl_str
EC_F_PKEY_EC_DERIVE:217:pkey_ec_derive
EC_F_PKEY_EC_INIT:282:pkey_ec_init
EC_F_PKEY_EC_KDF_DERIVE:283:pkey_ec_kdf_derive
EC_F_PKEY_EC_KEYGEN:199:pkey_ec_keygen
EC_F_PKEY_EC_PARAMGEN:219:pkey_ec_paramgen
EC_F_PKEY_EC_SIGN:218:pkey_ec_sign
EC_F_VALIDATE_ECX_DERIVE:278:validate_ecx_derive
ENGINE_F_DIGEST_UPDATE:198:digest_update
ENGINE_F_DYNAMIC_CTRL:180:dynamic_ctrl
ENGINE_F_DYNAMIC_GET_DATA_CTX:181:dynamic_get_data_ctx
ENGINE_F_DYNAMIC_LOAD:182:dynamic_load
ENGINE_F_DYNAMIC_SET_DATA_CTX:183:dynamic_set_data_ctx
ENGINE_F_ENGINE_ADD:105:ENGINE_add
ENGINE_F_ENGINE_BY_ID:106:ENGINE_by_id
ENGINE_F_ENGINE_CMD_IS_EXECUTABLE:170:ENGINE_cmd_is_executable
ENGINE_F_ENGINE_CTRL:142:ENGINE_ctrl
ENGINE_F_ENGINE_CTRL_CMD:178:ENGINE_ctrl_cmd
ENGINE_F_ENGINE_CTRL_CMD_STRING:171:ENGINE_ctrl_cmd_string
ENGINE_F_ENGINE_FINISH:107:ENGINE_finish
ENGINE_F_ENGINE_GET_CIPHER:185:ENGINE_get_cipher
ENGINE_F_ENGINE_GET_DIGEST:186:ENGINE_get_digest
ENGINE_F_ENGINE_GET_FIRST:195:ENGINE_get_first
ENGINE_F_ENGINE_GET_LAST:196:ENGINE_get_last
ENGINE_F_ENGINE_GET_NEXT:115:ENGINE_get_next
ENGINE_F_ENGINE_GET_PKEY_ASN1_METH:193:ENGINE_get_pkey_asn1_meth
ENGINE_F_ENGINE_GET_PKEY_METH:192:ENGINE_get_pkey_meth
ENGINE_F_ENGINE_GET_PREV:116:ENGINE_get_prev
ENGINE_F_ENGINE_INIT:119:ENGINE_init
ENGINE_F_ENGINE_LIST_ADD:120:engine_list_add
ENGINE_F_ENGINE_LIST_REMOVE:121:engine_list_remove
ENGINE_F_ENGINE_LOAD_PRIVATE_KEY:150:ENGINE_load_private_key
ENGINE_F_ENGINE_LOAD_PUBLIC_KEY:151:ENGINE_load_public_key
ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT:194:ENGINE_load_ssl_client_cert
ENGINE_F_ENGINE_NEW:122:ENGINE_new
ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR:197:ENGINE_pkey_asn1_find_str
ENGINE_F_ENGINE_REMOVE:123:ENGINE_remove
ENGINE_F_ENGINE_SET_DEFAULT_STRING:189:ENGINE_set_default_string
ENGINE_F_ENGINE_SET_ID:129:ENGINE_set_id
ENGINE_F_ENGINE_SET_NAME:130:ENGINE_set_name
ENGINE_F_ENGINE_TABLE_REGISTER:184:engine_table_register
ENGINE_F_ENGINE_UNLOCKED_FINISH:191:engine_unlocked_finish
ENGINE_F_ENGINE_UP_REF:190:ENGINE_up_ref
ENGINE_F_INT_CLEANUP_ITEM:199:int_cleanup_item
ENGINE_F_INT_CTRL_HELPER:172:int_ctrl_helper
ENGINE_F_INT_ENGINE_CONFIGURE:188:int_engine_configure
ENGINE_F_INT_ENGINE_MODULE_INIT:187:int_engine_module_init
ENGINE_F_OSSL_HMAC_INIT:200:ossl_hmac_init
EVP_F_AESNI_INIT_KEY:165:aesni_init_key
EVP_F_AES_GCM_CTRL:196:aes_gcm_ctrl
EVP_F_AES_INIT_KEY:133:aes_init_key
EVP_F_AES_OCB_CIPHER:169:aes_ocb_cipher
EVP_F_AES_T4_INIT_KEY:178:aes_t4_init_key
EVP_F_AES_WRAP_CIPHER:170:aes_wrap_cipher
EVP_F_ALG_MODULE_INIT:177:alg_module_init
EVP_F_ARIA_CCM_INIT_KEY:175:aria_ccm_init_key
EVP_F_ARIA_GCM_CTRL:197:aria_gcm_ctrl
EVP_F_ARIA_GCM_INIT_KEY:176:aria_gcm_init_key
EVP_F_ARIA_INIT_KEY:185:aria_init_key
EVP_F_B64_NEW:198:b64_new
EVP_F_CAMELLIA_INIT_KEY:159:camellia_init_key
EVP_F_CHACHA20_POLY1305_CTRL:182:chacha20_poly1305_ctrl
EVP_F_CMLL_T4_INIT_KEY:179:cmll_t4_init_key
EVP_F_DES_EDE3_WRAP_CIPHER:171:des_ede3_wrap_cipher
EVP_F_DO_SIGVER_INIT:161:do_sigver_init
EVP_F_ENC_NEW:199:enc_new
EVP_F_EVP_CIPHERINIT_EX:123:EVP_CipherInit_ex
EVP_F_EVP_CIPHER_ASN1_TO_PARAM:204:EVP_CIPHER_asn1_to_param
EVP_F_EVP_CIPHER_CTX_COPY:163:EVP_CIPHER_CTX_copy
EVP_F_EVP_CIPHER_CTX_CTRL:124:EVP_CIPHER_CTX_ctrl
EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH:122:EVP_CIPHER_CTX_set_key_length
EVP_F_EVP_CIPHER_PARAM_TO_ASN1:205:EVP_CIPHER_param_to_asn1
EVP_F_EVP_DECRYPTFINAL_EX:101:EVP_DecryptFinal_ex
EVP_F_EVP_DECRYPTUPDATE:166:EVP_DecryptUpdate
EVP_F_EVP_DIGESTFINALXOF:174:EVP_DigestFinalXOF
EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
EVP_F_EVP_MD_CTX_COPY_EX:110:EVP_MD_CTX_copy_ex
EVP_F_EVP_MD_SIZE:162:EVP_MD_size
EVP_F_EVP_OPENINIT:102:EVP_OpenInit
EVP_F_EVP_PBE_ALG_ADD:115:EVP_PBE_alg_add
EVP_F_EVP_PBE_ALG_ADD_TYPE:160:EVP_PBE_alg_add_type
EVP_F_EVP_PBE_CIPHERINIT:116:EVP_PBE_CipherInit
EVP_F_EVP_PBE_SCRYPT:181:EVP_PBE_scrypt
EVP_F_EVP_PKCS82PKEY:111:EVP_PKCS82PKEY
EVP_F_EVP_PKEY2PKCS8:113:EVP_PKEY2PKCS8
EVP_F_EVP_PKEY_ASN1_ADD0:188:EVP_PKEY_asn1_add0
EVP_F_EVP_PKEY_CHECK:186:EVP_PKEY_check
EVP_F_EVP_PKEY_COPY_PARAMETERS:103:EVP_PKEY_copy_parameters
EVP_F_EVP_PKEY_CTX_CTRL:137:EVP_PKEY_CTX_ctrl
EVP_F_EVP_PKEY_CTX_CTRL_STR:150:EVP_PKEY_CTX_ctrl_str
EVP_F_EVP_PKEY_CTX_DUP:156:EVP_PKEY_CTX_dup
EVP_F_EVP_PKEY_CTX_MD:168:EVP_PKEY_CTX_md
EVP_F_EVP_PKEY_DECRYPT:104:EVP_PKEY_decrypt
EVP_F_EVP_PKEY_DECRYPT_INIT:138:EVP_PKEY_decrypt_init
EVP_F_EVP_PKEY_DECRYPT_OLD:151:EVP_PKEY_decrypt_old
EVP_F_EVP_PKEY_DERIVE:153:EVP_PKEY_derive
EVP_F_EVP_PKEY_DERIVE_INIT:154:EVP_PKEY_derive_init
EVP_F_EVP_PKEY_DERIVE_SET_PEER:155:EVP_PKEY_derive_set_peer
EVP_F_EVP_PKEY_ENCRYPT:105:EVP_PKEY_encrypt
EVP_F_EVP_PKEY_ENCRYPT_INIT:139:EVP_PKEY_encrypt_init
EVP_F_EVP_PKEY_ENCRYPT_OLD:152:EVP_PKEY_encrypt_old
EVP_F_EVP_PKEY_GET0_DH:119:EVP_PKEY_get0_DH
EVP_F_EVP_PKEY_GET0_DSA:120:EVP_PKEY_get0_DSA
EVP_F_EVP_PKEY_GET0_EC_KEY:131:EVP_PKEY_get0_EC_KEY
EVP_F_EVP_PKEY_GET0_HMAC:183:EVP_PKEY_get0_hmac
EVP_F_EVP_PKEY_GET0_POLY1305:184:EVP_PKEY_get0_poly1305
EVP_F_EVP_PKEY_GET0_RSA:121:EVP_PKEY_get0_RSA
EVP_F_EVP_PKEY_GET0_SIPHASH:172:EVP_PKEY_get0_siphash
EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY:202:EVP_PKEY_get_raw_private_key
EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY:203:EVP_PKEY_get_raw_public_key
EVP_F_EVP_PKEY_KEYGEN:146:EVP_PKEY_keygen
EVP_F_EVP_PKEY_KEYGEN_INIT:147:EVP_PKEY_keygen_init
EVP_F_EVP_PKEY_METH_ADD0:194:EVP_PKEY_meth_add0
EVP_F_EVP_PKEY_METH_NEW:195:EVP_PKEY_meth_new
EVP_F_EVP_PKEY_NEW:106:EVP_PKEY_new
EVP_F_EVP_PKEY_NEW_CMAC_KEY:193:EVP_PKEY_new_CMAC_key
EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY:191:EVP_PKEY_new_raw_private_key
EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY:192:EVP_PKEY_new_raw_public_key
EVP_F_EVP_PKEY_PARAMGEN:148:EVP_PKEY_paramgen
EVP_F_EVP_PKEY_PARAMGEN_INIT:149:EVP_PKEY_paramgen_init
EVP_F_EVP_PKEY_PARAM_CHECK:189:EVP_PKEY_param_check
EVP_F_EVP_PKEY_PUBLIC_CHECK:190:EVP_PKEY_public_check
EVP_F_EVP_PKEY_SET1_ENGINE:187:EVP_PKEY_set1_engine
EVP_F_EVP_PKEY_SET_ALIAS_TYPE:206:EVP_PKEY_set_alias_type
EVP_F_EVP_PKEY_SIGN:140:EVP_PKEY_sign
EVP_F_EVP_PKEY_SIGN_INIT:141:EVP_PKEY_sign_init
EVP_F_EVP_PKEY_VERIFY:142:EVP_PKEY_verify
EVP_F_EVP_PKEY_VERIFY_INIT:143:EVP_PKEY_verify_init
EVP_F_EVP_PKEY_VERIFY_RECOVER:144:EVP_PKEY_verify_recover
EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT:145:EVP_PKEY_verify_recover_init
EVP_F_EVP_SIGNFINAL:107:EVP_SignFinal
EVP_F_EVP_VERIFYFINAL:108:EVP_VerifyFinal
EVP_F_INT_CTX_NEW:157:int_ctx_new
EVP_F_OK_NEW:200:ok_new
EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen
EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen
EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen
EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen
EVP_F_PKEY_SET_TYPE:158:pkey_set_type
EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth
EVP_F_RC5_CTRL:125:rc5_ctrl
EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl
EVP_F_UPDATE:173:update
KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str
KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive
KDF_F_PKEY_HKDF_INIT:108:pkey_hkdf_init
KDF_F_PKEY_SCRYPT_CTRL_STR:104:pkey_scrypt_ctrl_str
KDF_F_PKEY_SCRYPT_CTRL_UINT64:105:pkey_scrypt_ctrl_uint64
KDF_F_PKEY_SCRYPT_DERIVE:109:pkey_scrypt_derive
KDF_F_PKEY_SCRYPT_INIT:106:pkey_scrypt_init
KDF_F_PKEY_SCRYPT_SET_MEMBUF:107:pkey_scrypt_set_membuf
KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str
KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive
KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init
KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg
OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object
OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid
OBJ_F_OBJ_CREATE:100:OBJ_create
OBJ_F_OBJ_DUP:101:OBJ_dup
OBJ_F_OBJ_NAME_NEW_INDEX:106:OBJ_NAME_new_index
OBJ_F_OBJ_NID2LN:102:OBJ_nid2ln
OBJ_F_OBJ_NID2OBJ:103:OBJ_nid2obj
OBJ_F_OBJ_NID2SN:104:OBJ_nid2sn
OBJ_F_OBJ_TXT2OBJ:108:OBJ_txt2obj
OCSP_F_D2I_OCSP_NONCE:102:d2i_ocsp_nonce
OCSP_F_OCSP_BASIC_ADD1_STATUS:103:OCSP_basic_add1_status
OCSP_F_OCSP_BASIC_SIGN:104:OCSP_basic_sign
OCSP_F_OCSP_BASIC_SIGN_CTX:119:OCSP_basic_sign_ctx
OCSP_F_OCSP_BASIC_VERIFY:105:OCSP_basic_verify
OCSP_F_OCSP_CERT_ID_NEW:101:OCSP_cert_id_new
OCSP_F_OCSP_CHECK_DELEGATED:106:ocsp_check_delegated
OCSP_F_OCSP_CHECK_IDS:107:ocsp_check_ids
OCSP_F_OCSP_CHECK_ISSUER:108:ocsp_check_issuer
OCSP_F_OCSP_CHECK_VALIDITY:115:OCSP_check_validity
OCSP_F_OCSP_MATCH_ISSUERID:109:ocsp_match_issuerid
OCSP_F_OCSP_PARSE_URL:114:OCSP_parse_url
OCSP_F_OCSP_REQUEST_SIGN:110:OCSP_request_sign
OCSP_F_OCSP_REQUEST_VERIFY:116:OCSP_request_verify
OCSP_F_OCSP_RESPONSE_GET1_BASIC:111:OCSP_response_get1_basic
OCSP_F_PARSE_HTTP_LINE1:118:parse_http_line1
OSSL_STORE_F_FILE_CTRL:129:file_ctrl
OSSL_STORE_F_FILE_FIND:138:file_find
OSSL_STORE_F_FILE_GET_PASS:118:file_get_pass
OSSL_STORE_F_FILE_LOAD:119:file_load
OSSL_STORE_F_FILE_LOAD_TRY_DECODE:124:file_load_try_decode
OSSL_STORE_F_FILE_NAME_TO_URI:126:file_name_to_uri
OSSL_STORE_F_FILE_OPEN:120:file_open
OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO:127:ossl_store_attach_pem_bio
OSSL_STORE_F_OSSL_STORE_EXPECT:130:OSSL_STORE_expect
OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT:128:\
ossl_store_file_attach_pem_bio_int
OSSL_STORE_F_OSSL_STORE_FIND:131:OSSL_STORE_find
OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT:100:ossl_store_get0_loader_int
OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT:101:OSSL_STORE_INFO_get1_CERT
OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL:102:OSSL_STORE_INFO_get1_CRL
OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME:103:OSSL_STORE_INFO_get1_NAME
OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION:135:\
OSSL_STORE_INFO_get1_NAME_description
OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS:104:OSSL_STORE_INFO_get1_PARAMS
OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY:105:OSSL_STORE_INFO_get1_PKEY
OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT:106:OSSL_STORE_INFO_new_CERT
OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL:107:OSSL_STORE_INFO_new_CRL
OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED:123:ossl_store_info_new_EMBEDDED
OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME:109:OSSL_STORE_INFO_new_NAME
OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS:110:OSSL_STORE_INFO_new_PARAMS
OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY:111:OSSL_STORE_INFO_new_PKEY
OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION:134:\
OSSL_STORE_INFO_set0_NAME_description
OSSL_STORE_F_OSSL_STORE_INIT_ONCE:112:ossl_store_init_once
OSSL_STORE_F_OSSL_STORE_LOADER_NEW:113:OSSL_STORE_LOADER_new
OSSL_STORE_F_OSSL_STORE_OPEN:114:OSSL_STORE_open
OSSL_STORE_F_OSSL_STORE_OPEN_INT:115:*
OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT:117:ossl_store_register_loader_int
OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS:132:OSSL_STORE_SEARCH_by_alias
OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:133:\
OSSL_STORE_SEARCH_by_issuer_serial
OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:136:\
OSSL_STORE_SEARCH_by_key_fingerprint
OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME:137:OSSL_STORE_SEARCH_by_name
OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT:116:\
ossl_store_unregister_loader_int
OSSL_STORE_F_TRY_DECODE_PARAMS:121:try_decode_params
OSSL_STORE_F_TRY_DECODE_PKCS12:122:try_decode_PKCS12
OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED:125:try_decode_PKCS8Encrypted
PEM_F_B2I_DSS:127:b2i_dss
PEM_F_B2I_PVK_BIO:128:b2i_PVK_bio
PEM_F_B2I_RSA:129:b2i_rsa
PEM_F_CHECK_BITLEN_DSA:130:check_bitlen_dsa
PEM_F_CHECK_BITLEN_RSA:131:check_bitlen_rsa
PEM_F_D2I_PKCS8PRIVATEKEY_BIO:120:d2i_PKCS8PrivateKey_bio
PEM_F_D2I_PKCS8PRIVATEKEY_FP:121:d2i_PKCS8PrivateKey_fp
PEM_F_DO_B2I:132:do_b2i
PEM_F_DO_B2I_BIO:133:do_b2i_bio
PEM_F_DO_BLOB_HEADER:134:do_blob_header
PEM_F_DO_I2B:146:do_i2b
PEM_F_DO_PK8PKEY:126:do_pk8pkey
PEM_F_DO_PK8PKEY_FP:125:do_pk8pkey_fp
PEM_F_DO_PVK_BODY:135:do_PVK_body
PEM_F_DO_PVK_HEADER:136:do_PVK_header
PEM_F_GET_HEADER_AND_DATA:143:get_header_and_data
PEM_F_GET_NAME:144:get_name
PEM_F_I2B_PVK:137:i2b_PVK
PEM_F_I2B_PVK_BIO:138:i2b_PVK_bio
PEM_F_LOAD_IV:101:load_iv
PEM_F_PEM_ASN1_READ:102:PEM_ASN1_read
PEM_F_PEM_ASN1_READ_BIO:103:PEM_ASN1_read_bio
PEM_F_PEM_ASN1_WRITE:104:PEM_ASN1_write
PEM_F_PEM_ASN1_WRITE_BIO:105:PEM_ASN1_write_bio
PEM_F_PEM_DEF_CALLBACK:100:PEM_def_callback
PEM_F_PEM_DO_HEADER:106:PEM_do_header
PEM_F_PEM_GET_EVP_CIPHER_INFO:107:PEM_get_EVP_CIPHER_INFO
PEM_F_PEM_READ:108:PEM_read
PEM_F_PEM_READ_BIO:109:PEM_read_bio
PEM_F_PEM_READ_BIO_DHPARAMS:141:PEM_read_bio_DHparams
PEM_F_PEM_READ_BIO_EX:145:PEM_read_bio_ex
PEM_F_PEM_READ_BIO_PARAMETERS:140:PEM_read_bio_Parameters
PEM_F_PEM_READ_BIO_PRIVATEKEY:123:PEM_read_bio_PrivateKey
PEM_F_PEM_READ_DHPARAMS:142:PEM_read_DHparams
PEM_F_PEM_READ_PRIVATEKEY:124:PEM_read_PrivateKey
PEM_F_PEM_SIGNFINAL:112:PEM_SignFinal
PEM_F_PEM_WRITE:113:PEM_write
PEM_F_PEM_WRITE_BIO:114:PEM_write_bio
PEM_F_PEM_WRITE_PRIVATEKEY:139:PEM_write_PrivateKey
PEM_F_PEM_X509_INFO_READ:115:PEM_X509_INFO_read
PEM_F_PEM_X509_INFO_READ_BIO:116:PEM_X509_INFO_read_bio
PEM_F_PEM_X509_INFO_WRITE_BIO:117:PEM_X509_INFO_write_bio
PKCS12_F_OPENSSL_ASC2UNI:121:OPENSSL_asc2uni
PKCS12_F_OPENSSL_UNI2ASC:124:OPENSSL_uni2asc
PKCS12_F_OPENSSL_UNI2UTF8:127:OPENSSL_uni2utf8
PKCS12_F_OPENSSL_UTF82UNI:129:OPENSSL_utf82uni
PKCS12_F_PKCS12_CREATE:105:PKCS12_create
PKCS12_F_PKCS12_GEN_MAC:107:PKCS12_gen_mac
PKCS12_F_PKCS12_INIT:109:PKCS12_init
PKCS12_F_PKCS12_ITEM_DECRYPT_D2I:106:PKCS12_item_decrypt_d2i
PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT:108:PKCS12_item_i2d_encrypt
PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG:117:PKCS12_item_pack_safebag
PKCS12_F_PKCS12_KEY_GEN_ASC:110:PKCS12_key_gen_asc
PKCS12_F_PKCS12_KEY_GEN_UNI:111:PKCS12_key_gen_uni
PKCS12_F_PKCS12_KEY_GEN_UTF8:116:PKCS12_key_gen_utf8
PKCS12_F_PKCS12_NEWPASS:128:PKCS12_newpass
PKCS12_F_PKCS12_PACK_P7DATA:114:PKCS12_pack_p7data
PKCS12_F_PKCS12_PACK_P7ENCDATA:115:PKCS12_pack_p7encdata
PKCS12_F_PKCS12_PARSE:118:PKCS12_parse
PKCS12_F_PKCS12_PBE_CRYPT:119:PKCS12_pbe_crypt
PKCS12_F_PKCS12_PBE_KEYIVGEN:120:PKCS12_PBE_keyivgen
PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF:112:PKCS12_SAFEBAG_create0_p8inf
PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8:113:PKCS12_SAFEBAG_create0_pkcs8
PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT:133:\
PKCS12_SAFEBAG_create_pkcs8_encrypt
PKCS12_F_PKCS12_SETUP_MAC:122:PKCS12_setup_mac
PKCS12_F_PKCS12_SET_MAC:123:PKCS12_set_mac
PKCS12_F_PKCS12_UNPACK_AUTHSAFES:130:PKCS12_unpack_authsafes
PKCS12_F_PKCS12_UNPACK_P7DATA:131:PKCS12_unpack_p7data
PKCS12_F_PKCS12_VERIFY_MAC:126:PKCS12_verify_mac
PKCS12_F_PKCS8_ENCRYPT:125:PKCS8_encrypt
PKCS12_F_PKCS8_SET0_PBE:132:PKCS8_set0_pbe
PKCS7_F_DO_PKCS7_SIGNED_ATTRIB:136:do_pkcs7_signed_attrib
PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME:135:PKCS7_add0_attrib_signing_time
PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP:118:PKCS7_add_attrib_smimecap
PKCS7_F_PKCS7_ADD_CERTIFICATE:100:PKCS7_add_certificate
PKCS7_F_PKCS7_ADD_CRL:101:PKCS7_add_crl
PKCS7_F_PKCS7_ADD_RECIPIENT_INFO:102:PKCS7_add_recipient_info
PKCS7_F_PKCS7_ADD_SIGNATURE:131:PKCS7_add_signature
PKCS7_F_PKCS7_ADD_SIGNER:103:PKCS7_add_signer
PKCS7_F_PKCS7_BIO_ADD_DIGEST:125:PKCS7_bio_add_digest
PKCS7_F_PKCS7_COPY_EXISTING_DIGEST:138:pkcs7_copy_existing_digest
PKCS7_F_PKCS7_CTRL:104:PKCS7_ctrl
PKCS7_F_PKCS7_DATADECODE:112:PKCS7_dataDecode
PKCS7_F_PKCS7_DATAFINAL:128:PKCS7_dataFinal
PKCS7_F_PKCS7_DATAINIT:105:PKCS7_dataInit
PKCS7_F_PKCS7_DATAVERIFY:107:PKCS7_dataVerify
PKCS7_F_PKCS7_DECRYPT:114:PKCS7_decrypt
PKCS7_F_PKCS7_DECRYPT_RINFO:133:pkcs7_decrypt_rinfo
PKCS7_F_PKCS7_ENCODE_RINFO:132:pkcs7_encode_rinfo
PKCS7_F_PKCS7_ENCRYPT:115:PKCS7_encrypt
PKCS7_F_PKCS7_FINAL:134:PKCS7_final
PKCS7_F_PKCS7_FIND_DIGEST:127:PKCS7_find_digest
PKCS7_F_PKCS7_GET0_SIGNERS:124:PKCS7_get0_signers
PKCS7_F_PKCS7_RECIP_INFO_SET:130:PKCS7_RECIP_INFO_set
PKCS7_F_PKCS7_SET_CIPHER:108:PKCS7_set_cipher
PKCS7_F_PKCS7_SET_CONTENT:109:PKCS7_set_content
PKCS7_F_PKCS7_SET_DIGEST:126:PKCS7_set_digest
PKCS7_F_PKCS7_SET_TYPE:110:PKCS7_set_type
PKCS7_F_PKCS7_SIGN:116:PKCS7_sign
PKCS7_F_PKCS7_SIGNATUREVERIFY:113:PKCS7_signatureVerify
PKCS7_F_PKCS7_SIGNER_INFO_SET:129:PKCS7_SIGNER_INFO_set
PKCS7_F_PKCS7_SIGNER_INFO_SIGN:139:PKCS7_SIGNER_INFO_sign
PKCS7_F_PKCS7_SIGN_ADD_SIGNER:137:PKCS7_sign_add_signer
PKCS7_F_PKCS7_SIMPLE_SMIMECAP:119:PKCS7_simple_smimecap
PKCS7_F_PKCS7_VERIFY:117:PKCS7_verify
RAND_F_DRBG_BYTES:101:drbg_bytes
RAND_F_DRBG_GET_ENTROPY:105:drbg_get_entropy
RAND_F_DRBG_SETUP:117:drbg_setup
RAND_F_GET_ENTROPY:106:get_entropy
RAND_F_RAND_BYTES:100:RAND_bytes
RAND_F_RAND_DRBG_ENABLE_LOCKING:119:rand_drbg_enable_locking
RAND_F_RAND_DRBG_GENERATE:107:RAND_DRBG_generate
RAND_F_RAND_DRBG_GET_ENTROPY:120:rand_drbg_get_entropy
RAND_F_RAND_DRBG_GET_NONCE:123:rand_drbg_get_nonce
RAND_F_RAND_DRBG_INSTANTIATE:108:RAND_DRBG_instantiate
RAND_F_RAND_DRBG_NEW:109:RAND_DRBG_new
RAND_F_RAND_DRBG_RESEED:110:RAND_DRBG_reseed
RAND_F_RAND_DRBG_RESTART:102:rand_drbg_restart
RAND_F_RAND_DRBG_SET:104:RAND_DRBG_set
RAND_F_RAND_DRBG_SET_DEFAULTS:121:RAND_DRBG_set_defaults
RAND_F_RAND_DRBG_UNINSTANTIATE:118:RAND_DRBG_uninstantiate
RAND_F_RAND_LOAD_FILE:111:RAND_load_file
RAND_F_RAND_POOL_ACQUIRE_ENTROPY:122:rand_pool_acquire_entropy
RAND_F_RAND_POOL_ADD:103:rand_pool_add
RAND_F_RAND_POOL_ADD_BEGIN:113:rand_pool_add_begin
RAND_F_RAND_POOL_ADD_END:114:rand_pool_add_end
+RAND_F_RAND_POOL_ATTACH:124:rand_pool_attach
RAND_F_RAND_POOL_BYTES_NEEDED:115:rand_pool_bytes_needed
RAND_F_RAND_POOL_NEW:116:rand_pool_new
RAND_F_RAND_WRITE_FILE:112:RAND_write_file
RSA_F_CHECK_PADDING_MD:140:check_padding_md
RSA_F_ENCODE_PKCS1:146:encode_pkcs1
RSA_F_INT_RSA_VERIFY:145:int_rsa_verify
RSA_F_OLD_RSA_PRIV_DECODE:147:old_rsa_priv_decode
RSA_F_PKEY_PSS_INIT:165:pkey_pss_init
RSA_F_PKEY_RSA_CTRL:143:pkey_rsa_ctrl
RSA_F_PKEY_RSA_CTRL_STR:144:pkey_rsa_ctrl_str
RSA_F_PKEY_RSA_SIGN:142:pkey_rsa_sign
RSA_F_PKEY_RSA_VERIFY:149:pkey_rsa_verify
RSA_F_PKEY_RSA_VERIFYRECOVER:141:pkey_rsa_verifyrecover
RSA_F_RSA_ALGOR_TO_MD:156:rsa_algor_to_md
RSA_F_RSA_BUILTIN_KEYGEN:129:rsa_builtin_keygen
RSA_F_RSA_CHECK_KEY:123:RSA_check_key
RSA_F_RSA_CHECK_KEY_EX:160:RSA_check_key_ex
RSA_F_RSA_CMS_DECRYPT:159:rsa_cms_decrypt
RSA_F_RSA_CMS_VERIFY:158:rsa_cms_verify
RSA_F_RSA_ITEM_VERIFY:148:rsa_item_verify
RSA_F_RSA_METH_DUP:161:RSA_meth_dup
RSA_F_RSA_METH_NEW:162:RSA_meth_new
RSA_F_RSA_METH_SET1_NAME:163:RSA_meth_set1_name
RSA_F_RSA_MGF1_TO_MD:157:*
RSA_F_RSA_MULTIP_INFO_NEW:166:rsa_multip_info_new
RSA_F_RSA_NEW_METHOD:106:RSA_new_method
RSA_F_RSA_NULL:124:*
RSA_F_RSA_NULL_PRIVATE_DECRYPT:132:*
RSA_F_RSA_NULL_PRIVATE_ENCRYPT:133:*
RSA_F_RSA_NULL_PUBLIC_DECRYPT:134:*
RSA_F_RSA_NULL_PUBLIC_ENCRYPT:135:*
RSA_F_RSA_OSSL_PRIVATE_DECRYPT:101:rsa_ossl_private_decrypt
RSA_F_RSA_OSSL_PRIVATE_ENCRYPT:102:rsa_ossl_private_encrypt
RSA_F_RSA_OSSL_PUBLIC_DECRYPT:103:rsa_ossl_public_decrypt
RSA_F_RSA_OSSL_PUBLIC_ENCRYPT:104:rsa_ossl_public_encrypt
RSA_F_RSA_PADDING_ADD_NONE:107:RSA_padding_add_none
RSA_F_RSA_PADDING_ADD_PKCS1_OAEP:121:RSA_padding_add_PKCS1_OAEP
RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1:154:RSA_padding_add_PKCS1_OAEP_mgf1
RSA_F_RSA_PADDING_ADD_PKCS1_PSS:125:RSA_padding_add_PKCS1_PSS
RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1:152:RSA_padding_add_PKCS1_PSS_mgf1
RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1:108:RSA_padding_add_PKCS1_type_1
RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2:109:RSA_padding_add_PKCS1_type_2
RSA_F_RSA_PADDING_ADD_SSLV23:110:RSA_padding_add_SSLv23
RSA_F_RSA_PADDING_ADD_X931:127:RSA_padding_add_X931
RSA_F_RSA_PADDING_CHECK_NONE:111:RSA_padding_check_none
RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP:122:RSA_padding_check_PKCS1_OAEP
RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1:153:RSA_padding_check_PKCS1_OAEP_mgf1
RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1:112:RSA_padding_check_PKCS1_type_1
RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2:113:RSA_padding_check_PKCS1_type_2
RSA_F_RSA_PADDING_CHECK_SSLV23:114:RSA_padding_check_SSLv23
RSA_F_RSA_PADDING_CHECK_X931:128:RSA_padding_check_X931
RSA_F_RSA_PARAM_DECODE:164:rsa_param_decode
RSA_F_RSA_PRINT:115:RSA_print
RSA_F_RSA_PRINT_FP:116:RSA_print_fp
RSA_F_RSA_PRIV_DECODE:150:rsa_priv_decode
RSA_F_RSA_PRIV_ENCODE:138:rsa_priv_encode
RSA_F_RSA_PSS_GET_PARAM:151:rsa_pss_get_param
RSA_F_RSA_PSS_TO_CTX:155:rsa_pss_to_ctx
RSA_F_RSA_PUB_DECODE:139:rsa_pub_decode
RSA_F_RSA_SETUP_BLINDING:136:RSA_setup_blinding
RSA_F_RSA_SIGN:117:RSA_sign
RSA_F_RSA_SIGN_ASN1_OCTET_STRING:118:RSA_sign_ASN1_OCTET_STRING
RSA_F_RSA_VERIFY:119:RSA_verify
RSA_F_RSA_VERIFY_ASN1_OCTET_STRING:120:RSA_verify_ASN1_OCTET_STRING
RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1:126:RSA_verify_PKCS1_PSS_mgf1
RSA_F_SETUP_TBUF:167:setup_tbuf
SM2_F_PKEY_SM2_COPY:115:pkey_sm2_copy
SM2_F_PKEY_SM2_CTRL:109:pkey_sm2_ctrl
SM2_F_PKEY_SM2_CTRL_STR:110:pkey_sm2_ctrl_str
SM2_F_PKEY_SM2_DIGEST_CUSTOM:114:pkey_sm2_digest_custom
SM2_F_PKEY_SM2_INIT:111:pkey_sm2_init
SM2_F_PKEY_SM2_SIGN:112:pkey_sm2_sign
SM2_F_SM2_COMPUTE_MSG_HASH:100:sm2_compute_msg_hash
SM2_F_SM2_COMPUTE_USERID_DIGEST:101:sm2_compute_userid_digest
SM2_F_SM2_COMPUTE_Z_DIGEST:113:sm2_compute_z_digest
SM2_F_SM2_DECRYPT:102:sm2_decrypt
SM2_F_SM2_ENCRYPT:103:sm2_encrypt
SM2_F_SM2_PLAINTEXT_SIZE:104:sm2_plaintext_size
SM2_F_SM2_SIGN:105:sm2_sign
SM2_F_SM2_SIG_GEN:106:sm2_sig_gen
SM2_F_SM2_SIG_VERIFY:107:sm2_sig_verify
SM2_F_SM2_VERIFY:108:sm2_verify
SSL_F_ADD_CLIENT_KEY_SHARE_EXT:438:*
SSL_F_ADD_KEY_SHARE:512:add_key_share
SSL_F_BYTES_TO_CIPHER_LIST:519:bytes_to_cipher_list
SSL_F_CHECK_SUITEB_CIPHER_LIST:331:check_suiteb_cipher_list
SSL_F_CIPHERSUITE_CB:622:ciphersuite_cb
SSL_F_CONSTRUCT_CA_NAMES:552:construct_ca_names
SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS:553:construct_key_exchange_tbs
SSL_F_CONSTRUCT_STATEFUL_TICKET:636:construct_stateful_ticket
SSL_F_CONSTRUCT_STATELESS_TICKET:637:construct_stateless_ticket
SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH:539:create_synthetic_message_hash
SSL_F_CREATE_TICKET_PREQUEL:638:create_ticket_prequel
SSL_F_CT_MOVE_SCTS:345:ct_move_scts
SSL_F_CT_STRICT:349:ct_strict
SSL_F_CUSTOM_EXT_ADD:554:custom_ext_add
SSL_F_CUSTOM_EXT_PARSE:555:custom_ext_parse
SSL_F_D2I_SSL_SESSION:103:d2i_SSL_SESSION
SSL_F_DANE_CTX_ENABLE:347:dane_ctx_enable
SSL_F_DANE_MTYPE_SET:393:dane_mtype_set
SSL_F_DANE_TLSA_ADD:394:dane_tlsa_add
SSL_F_DERIVE_SECRET_KEY_AND_IV:514:derive_secret_key_and_iv
SSL_F_DO_DTLS1_WRITE:245:do_dtls1_write
SSL_F_DO_SSL3_WRITE:104:do_ssl3_write
SSL_F_DTLS1_BUFFER_RECORD:247:dtls1_buffer_record
SSL_F_DTLS1_CHECK_TIMEOUT_NUM:318:dtls1_check_timeout_num
SSL_F_DTLS1_HEARTBEAT:305:*
SSL_F_DTLS1_HM_FRAGMENT_NEW:623:dtls1_hm_fragment_new
SSL_F_DTLS1_PREPROCESS_FRAGMENT:288:dtls1_preprocess_fragment
SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS:424:dtls1_process_buffered_records
SSL_F_DTLS1_PROCESS_RECORD:257:dtls1_process_record
SSL_F_DTLS1_READ_BYTES:258:dtls1_read_bytes
SSL_F_DTLS1_READ_FAILED:339:dtls1_read_failed
SSL_F_DTLS1_RETRANSMIT_MESSAGE:390:dtls1_retransmit_message
SSL_F_DTLS1_WRITE_APP_DATA_BYTES:268:dtls1_write_app_data_bytes
SSL_F_DTLS1_WRITE_BYTES:545:dtls1_write_bytes
SSL_F_DTLSV1_LISTEN:350:DTLSv1_listen
SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC:371:dtls_construct_change_cipher_spec
SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST:385:\
dtls_construct_hello_verify_request
SSL_F_DTLS_GET_REASSEMBLED_MESSAGE:370:dtls_get_reassembled_message
SSL_F_DTLS_PROCESS_HELLO_VERIFY:386:dtls_process_hello_verify
SSL_F_DTLS_RECORD_LAYER_NEW:635:DTLS_RECORD_LAYER_new
SSL_F_DTLS_WAIT_FOR_DRY:592:dtls_wait_for_dry
SSL_F_EARLY_DATA_COUNT_OK:532:early_data_count_ok
SSL_F_FINAL_EARLY_DATA:556:final_early_data
SSL_F_FINAL_EC_PT_FORMATS:485:final_ec_pt_formats
SSL_F_FINAL_EMS:486:final_ems
SSL_F_FINAL_KEY_SHARE:503:final_key_share
SSL_F_FINAL_MAXFRAGMENTLEN:557:final_maxfragmentlen
SSL_F_FINAL_RENEGOTIATE:483:final_renegotiate
SSL_F_FINAL_SERVER_NAME:558:final_server_name
SSL_F_FINAL_SIG_ALGS:497:final_sig_algs
SSL_F_GET_CERT_VERIFY_TBS_DATA:588:get_cert_verify_tbs_data
SSL_F_NSS_KEYLOG_INT:500:nss_keylog_int
SSL_F_OPENSSL_INIT_SSL:342:OPENSSL_init_ssl
SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION:436:*
SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION:598:\
ossl_statem_client13_write_transition
SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE:430:*
SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE:593:\
ossl_statem_client_post_process_message
SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE:594:ossl_statem_client_process_message
SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION:417:ossl_statem_client_read_transition
SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION:599:\
ossl_statem_client_write_transition
SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION:437:*
SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION:600:\
ossl_statem_server13_write_transition
SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:*
SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\
ossl_statem_server_post_process_message
SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work
SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message
SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition
SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\
ossl_statem_server_write_transition
SSL_F_PARSE_CA_NAMES:541:parse_ca_names
SSL_F_PITEM_NEW:624:pitem_new
SSL_F_PQUEUE_NEW:625:pqueue_new
SSL_F_PROCESS_KEY_SHARE_EXT:439:*
SSL_F_READ_STATE_MACHINE:352:read_state_machine
SSL_F_SET_CLIENT_CIPHERSUITE:540:set_client_ciphersuite
SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET:595:srp_generate_client_master_secret
SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET:589:srp_generate_server_master_secret
SSL_F_SRP_VERIFY_SERVER_PARAM:596:srp_verify_server_param
SSL_F_SSL3_CHANGE_CIPHER_STATE:129:ssl3_change_cipher_state
SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM:130:ssl3_check_cert_and_algorithm
SSL_F_SSL3_CTRL:213:ssl3_ctrl
SSL_F_SSL3_CTX_CTRL:133:ssl3_ctx_ctrl
SSL_F_SSL3_DIGEST_CACHED_RECORDS:293:ssl3_digest_cached_records
SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC:292:ssl3_do_change_cipher_spec
SSL_F_SSL3_ENC:608:ssl3_enc
SSL_F_SSL3_FINAL_FINISH_MAC:285:ssl3_final_finish_mac
SSL_F_SSL3_FINISH_MAC:587:ssl3_finish_mac
SSL_F_SSL3_GENERATE_KEY_BLOCK:238:ssl3_generate_key_block
SSL_F_SSL3_GENERATE_MASTER_SECRET:388:ssl3_generate_master_secret
SSL_F_SSL3_GET_RECORD:143:ssl3_get_record
SSL_F_SSL3_INIT_FINISHED_MAC:397:ssl3_init_finished_mac
SSL_F_SSL3_OUTPUT_CERT_CHAIN:147:ssl3_output_cert_chain
SSL_F_SSL3_READ_BYTES:148:ssl3_read_bytes
SSL_F_SSL3_READ_N:149:ssl3_read_n
SSL_F_SSL3_SETUP_KEY_BLOCK:157:ssl3_setup_key_block
SSL_F_SSL3_SETUP_READ_BUFFER:156:ssl3_setup_read_buffer
SSL_F_SSL3_SETUP_WRITE_BUFFER:291:ssl3_setup_write_buffer
SSL_F_SSL3_WRITE_BYTES:158:ssl3_write_bytes
SSL_F_SSL3_WRITE_PENDING:159:ssl3_write_pending
SSL_F_SSL_ADD_CERT_CHAIN:316:ssl_add_cert_chain
SSL_F_SSL_ADD_CERT_TO_BUF:319:*
SSL_F_SSL_ADD_CERT_TO_WPACKET:493:ssl_add_cert_to_wpacket
SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT:298:*
SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT:277:*
SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT:307:*
SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK:215:SSL_add_dir_cert_subjects_to_stack
SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK:216:\
SSL_add_file_cert_subjects_to_stack
SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT:299:*
SSL_F_SSL_ADD_SERVERHELLO_TLSEXT:278:*
SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT:308:*
SSL_F_SSL_BAD_METHOD:160:ssl_bad_method
SSL_F_SSL_BUILD_CERT_CHAIN:332:ssl_build_cert_chain
SSL_F_SSL_BYTES_TO_CIPHER_LIST:161:SSL_bytes_to_cipher_list
SSL_F_SSL_CACHE_CIPHERLIST:520:ssl_cache_cipherlist
SSL_F_SSL_CERT_ADD0_CHAIN_CERT:346:ssl_cert_add0_chain_cert
SSL_F_SSL_CERT_DUP:221:ssl_cert_dup
SSL_F_SSL_CERT_NEW:162:ssl_cert_new
SSL_F_SSL_CERT_SET0_CHAIN:340:ssl_cert_set0_chain
SSL_F_SSL_CHECK_PRIVATE_KEY:163:SSL_check_private_key
SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT:280:*
SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO:606:ssl_check_srp_ext_ClientHello
SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG:279:ssl_check_srvr_ecc_cert_and_alg
SSL_F_SSL_CHOOSE_CLIENT_VERSION:607:ssl_choose_client_version
SSL_F_SSL_CIPHER_DESCRIPTION:626:SSL_CIPHER_description
SSL_F_SSL_CIPHER_LIST_TO_BYTES:425:ssl_cipher_list_to_bytes
SSL_F_SSL_CIPHER_PROCESS_RULESTR:230:ssl_cipher_process_rulestr
SSL_F_SSL_CIPHER_STRENGTH_SORT:231:ssl_cipher_strength_sort
SSL_F_SSL_CLEAR:164:SSL_clear
SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT:627:\
SSL_client_hello_get1_extensions_present
SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD:165:SSL_COMP_add_compression_method
SSL_F_SSL_CONF_CMD:334:SSL_CONF_cmd
SSL_F_SSL_CREATE_CIPHER_LIST:166:ssl_create_cipher_list
SSL_F_SSL_CTRL:232:SSL_ctrl
SSL_F_SSL_CTX_CHECK_PRIVATE_KEY:168:SSL_CTX_check_private_key
SSL_F_SSL_CTX_ENABLE_CT:398:SSL_CTX_enable_ct
SSL_F_SSL_CTX_MAKE_PROFILES:309:ssl_ctx_make_profiles
SSL_F_SSL_CTX_NEW:169:SSL_CTX_new
SSL_F_SSL_CTX_SET_ALPN_PROTOS:343:SSL_CTX_set_alpn_protos
SSL_F_SSL_CTX_SET_CIPHER_LIST:269:SSL_CTX_set_cipher_list
SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE:290:SSL_CTX_set_client_cert_engine
SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK:396:SSL_CTX_set_ct_validation_callback
SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT:219:SSL_CTX_set_session_id_context
SSL_F_SSL_CTX_SET_SSL_VERSION:170:SSL_CTX_set_ssl_version
SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH:551:\
SSL_CTX_set_tlsext_max_fragment_length
SSL_F_SSL_CTX_USE_CERTIFICATE:171:SSL_CTX_use_certificate
SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1:172:SSL_CTX_use_certificate_ASN1
SSL_F_SSL_CTX_USE_CERTIFICATE_FILE:173:SSL_CTX_use_certificate_file
SSL_F_SSL_CTX_USE_PRIVATEKEY:174:SSL_CTX_use_PrivateKey
SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1:175:SSL_CTX_use_PrivateKey_ASN1
SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE:176:SSL_CTX_use_PrivateKey_file
SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT:272:SSL_CTX_use_psk_identity_hint
SSL_F_SSL_CTX_USE_RSAPRIVATEKEY:177:SSL_CTX_use_RSAPrivateKey
SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1:178:SSL_CTX_use_RSAPrivateKey_ASN1
SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE:179:SSL_CTX_use_RSAPrivateKey_file
SSL_F_SSL_CTX_USE_SERVERINFO:336:SSL_CTX_use_serverinfo
SSL_F_SSL_CTX_USE_SERVERINFO_EX:543:SSL_CTX_use_serverinfo_ex
SSL_F_SSL_CTX_USE_SERVERINFO_FILE:337:SSL_CTX_use_serverinfo_file
SSL_F_SSL_DANE_DUP:403:ssl_dane_dup
SSL_F_SSL_DANE_ENABLE:395:SSL_dane_enable
SSL_F_SSL_DERIVE:590:ssl_derive
SSL_F_SSL_DO_CONFIG:391:ssl_do_config
SSL_F_SSL_DO_HANDSHAKE:180:SSL_do_handshake
SSL_F_SSL_DUP_CA_LIST:408:SSL_dup_CA_list
SSL_F_SSL_ENABLE_CT:402:SSL_enable_ct
SSL_F_SSL_GENERATE_PKEY_GROUP:559:ssl_generate_pkey_group
SSL_F_SSL_GENERATE_SESSION_ID:547:ssl_generate_session_id
SSL_F_SSL_GET_NEW_SESSION:181:ssl_get_new_session
SSL_F_SSL_GET_PREV_SESSION:217:ssl_get_prev_session
SSL_F_SSL_GET_SERVER_CERT_INDEX:322:*
SSL_F_SSL_GET_SIGN_PKEY:183:*
SSL_F_SSL_HANDSHAKE_HASH:560:ssl_handshake_hash
SSL_F_SSL_INIT_WBIO_BUFFER:184:ssl_init_wbio_buffer
SSL_F_SSL_KEY_UPDATE:515:SSL_key_update
SSL_F_SSL_LOAD_CLIENT_CA_FILE:185:SSL_load_client_CA_file
SSL_F_SSL_LOG_MASTER_SECRET:498:*
SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE:499:ssl_log_rsa_client_key_exchange
SSL_F_SSL_MODULE_INIT:392:ssl_module_init
SSL_F_SSL_NEW:186:SSL_new
SSL_F_SSL_NEXT_PROTO_VALIDATE:565:ssl_next_proto_validate
SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT:300:*
SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT:302:*
SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT:310:*
SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT:301:*
SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT:303:*
SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT:311:*
SSL_F_SSL_PEEK:270:SSL_peek
SSL_F_SSL_PEEK_EX:432:SSL_peek_ex
SSL_F_SSL_PEEK_INTERNAL:522:ssl_peek_internal
SSL_F_SSL_READ:223:SSL_read
SSL_F_SSL_READ_EARLY_DATA:529:SSL_read_early_data
SSL_F_SSL_READ_EX:434:SSL_read_ex
SSL_F_SSL_READ_INTERNAL:523:ssl_read_internal
SSL_F_SSL_RENEGOTIATE:516:SSL_renegotiate
SSL_F_SSL_RENEGOTIATE_ABBREVIATED:546:SSL_renegotiate_abbreviated
SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT:320:*
SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT:321:*
SSL_F_SSL_SESSION_DUP:348:ssl_session_dup
SSL_F_SSL_SESSION_NEW:189:SSL_SESSION_new
SSL_F_SSL_SESSION_PRINT_FP:190:SSL_SESSION_print_fp
SSL_F_SSL_SESSION_SET1_ID:423:SSL_SESSION_set1_id
SSL_F_SSL_SESSION_SET1_ID_CONTEXT:312:SSL_SESSION_set1_id_context
SSL_F_SSL_SET_ALPN_PROTOS:344:SSL_set_alpn_protos
SSL_F_SSL_SET_CERT:191:ssl_set_cert
SSL_F_SSL_SET_CERT_AND_KEY:621:ssl_set_cert_and_key
SSL_F_SSL_SET_CIPHER_LIST:271:SSL_set_cipher_list
SSL_F_SSL_SET_CT_VALIDATION_CALLBACK:399:SSL_set_ct_validation_callback
SSL_F_SSL_SET_FD:192:SSL_set_fd
SSL_F_SSL_SET_PKEY:193:ssl_set_pkey
SSL_F_SSL_SET_RFD:194:SSL_set_rfd
SSL_F_SSL_SET_SESSION:195:SSL_set_session
SSL_F_SSL_SET_SESSION_ID_CONTEXT:218:SSL_set_session_id_context
SSL_F_SSL_SET_SESSION_TICKET_EXT:294:SSL_set_session_ticket_ext
SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH:550:SSL_set_tlsext_max_fragment_length
SSL_F_SSL_SET_WFD:196:SSL_set_wfd
SSL_F_SSL_SHUTDOWN:224:SSL_shutdown
SSL_F_SSL_SRP_CTX_INIT:313:SSL_SRP_CTX_init
SSL_F_SSL_START_ASYNC_JOB:389:ssl_start_async_job
SSL_F_SSL_UNDEFINED_FUNCTION:197:ssl_undefined_function
SSL_F_SSL_UNDEFINED_VOID_FUNCTION:244:ssl_undefined_void_function
SSL_F_SSL_USE_CERTIFICATE:198:SSL_use_certificate
SSL_F_SSL_USE_CERTIFICATE_ASN1:199:SSL_use_certificate_ASN1
SSL_F_SSL_USE_CERTIFICATE_FILE:200:SSL_use_certificate_file
SSL_F_SSL_USE_PRIVATEKEY:201:SSL_use_PrivateKey
SSL_F_SSL_USE_PRIVATEKEY_ASN1:202:SSL_use_PrivateKey_ASN1
SSL_F_SSL_USE_PRIVATEKEY_FILE:203:SSL_use_PrivateKey_file
SSL_F_SSL_USE_PSK_IDENTITY_HINT:273:SSL_use_psk_identity_hint
SSL_F_SSL_USE_RSAPRIVATEKEY:204:SSL_use_RSAPrivateKey
SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1:205:SSL_use_RSAPrivateKey_ASN1
SSL_F_SSL_USE_RSAPRIVATEKEY_FILE:206:SSL_use_RSAPrivateKey_file
SSL_F_SSL_VALIDATE_CT:400:ssl_validate_ct
SSL_F_SSL_VERIFY_CERT_CHAIN:207:ssl_verify_cert_chain
SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE:616:SSL_verify_client_post_handshake
SSL_F_SSL_WRITE:208:SSL_write
SSL_F_SSL_WRITE_EARLY_DATA:526:SSL_write_early_data
SSL_F_SSL_WRITE_EARLY_FINISH:527:*
SSL_F_SSL_WRITE_EX:433:SSL_write_ex
SSL_F_SSL_WRITE_INTERNAL:524:ssl_write_internal
SSL_F_STATE_MACHINE:353:state_machine
SSL_F_TLS12_CHECK_PEER_SIGALG:333:tls12_check_peer_sigalg
SSL_F_TLS12_COPY_SIGALGS:533:tls12_copy_sigalgs
SSL_F_TLS13_CHANGE_CIPHER_STATE:440:tls13_change_cipher_state
SSL_F_TLS13_ENC:609:tls13_enc
SSL_F_TLS13_FINAL_FINISH_MAC:605:tls13_final_finish_mac
SSL_F_TLS13_GENERATE_SECRET:591:tls13_generate_secret
SSL_F_TLS13_HKDF_EXPAND:561:tls13_hkdf_expand
SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA:617:\
tls13_restore_handshake_digest_for_pha
SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA:618:\
tls13_save_handshake_digest_for_pha
SSL_F_TLS13_SETUP_KEY_BLOCK:441:tls13_setup_key_block
SSL_F_TLS1_CHANGE_CIPHER_STATE:209:tls1_change_cipher_state
SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS:341:*
SSL_F_TLS1_ENC:401:tls1_enc
SSL_F_TLS1_EXPORT_KEYING_MATERIAL:314:tls1_export_keying_material
SSL_F_TLS1_GET_CURVELIST:338:tls1_get_curvelist
SSL_F_TLS1_PRF:284:tls1_PRF
SSL_F_TLS1_SAVE_U16:628:tls1_save_u16
SSL_F_TLS1_SETUP_KEY_BLOCK:211:tls1_setup_key_block
SSL_F_TLS1_SET_GROUPS:629:tls1_set_groups
SSL_F_TLS1_SET_RAW_SIGALGS:630:tls1_set_raw_sigalgs
SSL_F_TLS1_SET_SERVER_SIGALGS:335:tls1_set_server_sigalgs
SSL_F_TLS1_SET_SHARED_SIGALGS:631:tls1_set_shared_sigalgs
SSL_F_TLS1_SET_SIGALGS:632:tls1_set_sigalgs
SSL_F_TLS_CHOOSE_SIGALG:513:tls_choose_sigalg
SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK:354:tls_client_key_exchange_post_work
SSL_F_TLS_COLLECT_EXTENSIONS:435:tls_collect_extensions
SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES:542:\
tls_construct_certificate_authorities
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST:372:tls_construct_certificate_request
SSL_F_TLS_CONSTRUCT_CERT_STATUS:429:*
SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY:494:tls_construct_cert_status_body
SSL_F_TLS_CONSTRUCT_CERT_VERIFY:496:tls_construct_cert_verify
SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC:427:tls_construct_change_cipher_spec
SSL_F_TLS_CONSTRUCT_CKE_DHE:404:tls_construct_cke_dhe
SSL_F_TLS_CONSTRUCT_CKE_ECDHE:405:tls_construct_cke_ecdhe
SSL_F_TLS_CONSTRUCT_CKE_GOST:406:tls_construct_cke_gost
SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE:407:tls_construct_cke_psk_preamble
SSL_F_TLS_CONSTRUCT_CKE_RSA:409:tls_construct_cke_rsa
SSL_F_TLS_CONSTRUCT_CKE_SRP:410:tls_construct_cke_srp
SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE:484:tls_construct_client_certificate
SSL_F_TLS_CONSTRUCT_CLIENT_HELLO:487:tls_construct_client_hello
SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE:488:tls_construct_client_key_exchange
SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY:489:*
SSL_F_TLS_CONSTRUCT_CTOS_ALPN:466:tls_construct_ctos_alpn
SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE:355:*
SSL_F_TLS_CONSTRUCT_CTOS_COOKIE:535:tls_construct_ctos_cookie
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA:530:tls_construct_ctos_early_data
SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS:467:tls_construct_ctos_ec_pt_formats
SSL_F_TLS_CONSTRUCT_CTOS_EMS:468:tls_construct_ctos_ems
SSL_F_TLS_CONSTRUCT_CTOS_ETM:469:tls_construct_ctos_etm
SSL_F_TLS_CONSTRUCT_CTOS_HELLO:356:*
SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE:357:*
SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE:470:tls_construct_ctos_key_share
SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN:549:tls_construct_ctos_maxfragmentlen
SSL_F_TLS_CONSTRUCT_CTOS_NPN:471:tls_construct_ctos_npn
SSL_F_TLS_CONSTRUCT_CTOS_PADDING:472:tls_construct_ctos_padding
SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH:619:\
tls_construct_ctos_post_handshake_auth
SSL_F_TLS_CONSTRUCT_CTOS_PSK:501:tls_construct_ctos_psk
SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES:509:tls_construct_ctos_psk_kex_modes
SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE:473:tls_construct_ctos_renegotiate
SSL_F_TLS_CONSTRUCT_CTOS_SCT:474:tls_construct_ctos_sct
SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME:475:tls_construct_ctos_server_name
SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET:476:tls_construct_ctos_session_ticket
SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS:477:tls_construct_ctos_sig_algs
SSL_F_TLS_CONSTRUCT_CTOS_SRP:478:tls_construct_ctos_srp
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST:479:tls_construct_ctos_status_request
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS:480:\
tls_construct_ctos_supported_groups
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS:481:\
tls_construct_ctos_supported_versions
SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP:482:tls_construct_ctos_use_srtp
SSL_F_TLS_CONSTRUCT_CTOS_VERIFY:358:*
SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS:443:tls_construct_encrypted_extensions
SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA:536:tls_construct_end_of_early_data
SSL_F_TLS_CONSTRUCT_EXTENSIONS:447:tls_construct_extensions
SSL_F_TLS_CONSTRUCT_FINISHED:359:tls_construct_finished
SSL_F_TLS_CONSTRUCT_HELLO_REQUEST:373:*
SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST:510:tls_construct_hello_retry_request
SSL_F_TLS_CONSTRUCT_KEY_UPDATE:517:tls_construct_key_update
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET:428:tls_construct_new_session_ticket
SSL_F_TLS_CONSTRUCT_NEXT_PROTO:426:tls_construct_next_proto
SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE:490:tls_construct_server_certificate
SSL_F_TLS_CONSTRUCT_SERVER_HELLO:491:tls_construct_server_hello
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE:492:tls_construct_server_key_exchange
SSL_F_TLS_CONSTRUCT_STOC_ALPN:451:tls_construct_stoc_alpn
SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE:374:*
SSL_F_TLS_CONSTRUCT_STOC_COOKIE:613:tls_construct_stoc_cookie
SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG:452:tls_construct_stoc_cryptopro_bug
SSL_F_TLS_CONSTRUCT_STOC_DONE:375:*
SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA:531:tls_construct_stoc_early_data
SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO:525:*
SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS:453:tls_construct_stoc_ec_pt_formats
SSL_F_TLS_CONSTRUCT_STOC_EMS:454:tls_construct_stoc_ems
SSL_F_TLS_CONSTRUCT_STOC_ETM:455:tls_construct_stoc_etm
SSL_F_TLS_CONSTRUCT_STOC_HELLO:376:*
SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE:377:*
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE:456:tls_construct_stoc_key_share
SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN:548:tls_construct_stoc_maxfragmentlen
SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG:457:tls_construct_stoc_next_proto_neg
SSL_F_TLS_CONSTRUCT_STOC_PSK:504:tls_construct_stoc_psk
SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE:458:tls_construct_stoc_renegotiate
SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME:459:tls_construct_stoc_server_name
SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET:460:tls_construct_stoc_session_ticket
SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST:461:tls_construct_stoc_status_request
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS:544:\
tls_construct_stoc_supported_groups
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS:611:\
tls_construct_stoc_supported_versions
SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP:462:tls_construct_stoc_use_srtp
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO:521:\
tls_early_post_process_client_hello
SSL_F_TLS_FINISH_HANDSHAKE:597:tls_finish_handshake
SSL_F_TLS_GET_MESSAGE_BODY:351:tls_get_message_body
SSL_F_TLS_GET_MESSAGE_HEADER:387:tls_get_message_header
SSL_F_TLS_HANDLE_ALPN:562:tls_handle_alpn
SSL_F_TLS_HANDLE_STATUS_REQUEST:563:tls_handle_status_request
SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES:566:tls_parse_certificate_authorities
SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT:449:*
SSL_F_TLS_PARSE_CTOS_ALPN:567:tls_parse_ctos_alpn
SSL_F_TLS_PARSE_CTOS_COOKIE:614:tls_parse_ctos_cookie
SSL_F_TLS_PARSE_CTOS_EARLY_DATA:568:tls_parse_ctos_early_data
SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS:569:tls_parse_ctos_ec_pt_formats
SSL_F_TLS_PARSE_CTOS_EMS:570:tls_parse_ctos_ems
SSL_F_TLS_PARSE_CTOS_KEY_SHARE:463:tls_parse_ctos_key_share
SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN:571:tls_parse_ctos_maxfragmentlen
SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH:620:tls_parse_ctos_post_handshake_auth
SSL_F_TLS_PARSE_CTOS_PSK:505:tls_parse_ctos_psk
SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES:572:tls_parse_ctos_psk_kex_modes
SSL_F_TLS_PARSE_CTOS_RENEGOTIATE:464:tls_parse_ctos_renegotiate
SSL_F_TLS_PARSE_CTOS_SERVER_NAME:573:tls_parse_ctos_server_name
SSL_F_TLS_PARSE_CTOS_SESSION_TICKET:574:tls_parse_ctos_session_ticket
SSL_F_TLS_PARSE_CTOS_SIG_ALGS:575:tls_parse_ctos_sig_algs
SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT:615:tls_parse_ctos_sig_algs_cert
SSL_F_TLS_PARSE_CTOS_SRP:576:tls_parse_ctos_srp
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST:577:tls_parse_ctos_status_request
SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS:578:tls_parse_ctos_supported_groups
SSL_F_TLS_PARSE_CTOS_USE_SRTP:465:tls_parse_ctos_use_srtp
SSL_F_TLS_PARSE_STOC_ALPN:579:tls_parse_stoc_alpn
SSL_F_TLS_PARSE_STOC_COOKIE:534:tls_parse_stoc_cookie
SSL_F_TLS_PARSE_STOC_EARLY_DATA:538:tls_parse_stoc_early_data
SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO:528:*
SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS:580:tls_parse_stoc_ec_pt_formats
SSL_F_TLS_PARSE_STOC_KEY_SHARE:445:tls_parse_stoc_key_share
SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN:581:tls_parse_stoc_maxfragmentlen
SSL_F_TLS_PARSE_STOC_NPN:582:tls_parse_stoc_npn
SSL_F_TLS_PARSE_STOC_PSK:502:tls_parse_stoc_psk
SSL_F_TLS_PARSE_STOC_RENEGOTIATE:448:tls_parse_stoc_renegotiate
SSL_F_TLS_PARSE_STOC_SCT:564:tls_parse_stoc_sct
SSL_F_TLS_PARSE_STOC_SERVER_NAME:583:tls_parse_stoc_server_name
SSL_F_TLS_PARSE_STOC_SESSION_TICKET:584:tls_parse_stoc_session_ticket
SSL_F_TLS_PARSE_STOC_STATUS_REQUEST:585:tls_parse_stoc_status_request
SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS:612:tls_parse_stoc_supported_versions
SSL_F_TLS_PARSE_STOC_USE_SRTP:446:tls_parse_stoc_use_srtp
SSL_F_TLS_POST_PROCESS_CLIENT_HELLO:378:tls_post_process_client_hello
SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE:384:\
tls_post_process_client_key_exchange
SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE:360:tls_prepare_client_certificate
SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST:610:tls_process_as_hello_retry_request
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST:361:tls_process_certificate_request
SSL_F_TLS_PROCESS_CERT_STATUS:362:*
SSL_F_TLS_PROCESS_CERT_STATUS_BODY:495:tls_process_cert_status_body
SSL_F_TLS_PROCESS_CERT_VERIFY:379:tls_process_cert_verify
SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC:363:tls_process_change_cipher_spec
SSL_F_TLS_PROCESS_CKE_DHE:411:tls_process_cke_dhe
SSL_F_TLS_PROCESS_CKE_ECDHE:412:tls_process_cke_ecdhe
SSL_F_TLS_PROCESS_CKE_GOST:413:tls_process_cke_gost
SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE:414:tls_process_cke_psk_preamble
SSL_F_TLS_PROCESS_CKE_RSA:415:tls_process_cke_rsa
SSL_F_TLS_PROCESS_CKE_SRP:416:tls_process_cke_srp
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE:380:tls_process_client_certificate
SSL_F_TLS_PROCESS_CLIENT_HELLO:381:tls_process_client_hello
SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE:382:tls_process_client_key_exchange
SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS:444:tls_process_encrypted_extensions
SSL_F_TLS_PROCESS_END_OF_EARLY_DATA:537:tls_process_end_of_early_data
SSL_F_TLS_PROCESS_FINISHED:364:tls_process_finished
SSL_F_TLS_PROCESS_HELLO_REQ:507:tls_process_hello_req
SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST:511:tls_process_hello_retry_request
SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT:442:tls_process_initial_server_flight
SSL_F_TLS_PROCESS_KEY_EXCHANGE:365:tls_process_key_exchange
SSL_F_TLS_PROCESS_KEY_UPDATE:518:tls_process_key_update
SSL_F_TLS_PROCESS_NEW_SESSION_TICKET:366:tls_process_new_session_ticket
SSL_F_TLS_PROCESS_NEXT_PROTO:383:tls_process_next_proto
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE:367:tls_process_server_certificate
SSL_F_TLS_PROCESS_SERVER_DONE:368:tls_process_server_done
SSL_F_TLS_PROCESS_SERVER_HELLO:369:tls_process_server_hello
SSL_F_TLS_PROCESS_SKE_DHE:419:tls_process_ske_dhe
SSL_F_TLS_PROCESS_SKE_ECDHE:420:tls_process_ske_ecdhe
SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE:421:tls_process_ske_psk_preamble
SSL_F_TLS_PROCESS_SKE_SRP:422:tls_process_ske_srp
SSL_F_TLS_PSK_DO_BINDER:506:tls_psk_do_binder
SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT:450:*
SSL_F_TLS_SETUP_HANDSHAKE:508:tls_setup_handshake
SSL_F_USE_CERTIFICATE_CHAIN_FILE:220:use_certificate_chain_file
SSL_F_WPACKET_INTERN_INIT_LEN:633:wpacket_intern_init_len
SSL_F_WPACKET_START_SUB_PACKET_LEN__:634:WPACKET_start_sub_packet_len__
SSL_F_WRITE_STATE_MACHINE:586:write_state_machine
TS_F_DEF_SERIAL_CB:110:def_serial_cb
TS_F_DEF_TIME_CB:111:def_time_cb
TS_F_ESS_ADD_SIGNING_CERT:112:ess_add_signing_cert
TS_F_ESS_ADD_SIGNING_CERT_V2:147:ess_add_signing_cert_v2
TS_F_ESS_CERT_ID_NEW_INIT:113:ess_CERT_ID_new_init
TS_F_ESS_CERT_ID_V2_NEW_INIT:156:ess_cert_id_v2_new_init
TS_F_ESS_SIGNING_CERT_NEW_INIT:114:ess_SIGNING_CERT_new_init
TS_F_ESS_SIGNING_CERT_V2_NEW_INIT:157:ess_signing_cert_v2_new_init
TS_F_INT_TS_RESP_VERIFY_TOKEN:149:int_ts_RESP_verify_token
TS_F_PKCS7_TO_TS_TST_INFO:148:PKCS7_to_TS_TST_INFO
TS_F_TS_ACCURACY_SET_MICROS:115:TS_ACCURACY_set_micros
TS_F_TS_ACCURACY_SET_MILLIS:116:TS_ACCURACY_set_millis
TS_F_TS_ACCURACY_SET_SECONDS:117:TS_ACCURACY_set_seconds
TS_F_TS_CHECK_IMPRINTS:100:ts_check_imprints
TS_F_TS_CHECK_NONCES:101:ts_check_nonces
TS_F_TS_CHECK_POLICY:102:ts_check_policy
TS_F_TS_CHECK_SIGNING_CERTS:103:ts_check_signing_certs
TS_F_TS_CHECK_STATUS_INFO:104:ts_check_status_info
TS_F_TS_COMPUTE_IMPRINT:145:ts_compute_imprint
TS_F_TS_CONF_INVALID:151:ts_CONF_invalid
TS_F_TS_CONF_LOAD_CERT:153:TS_CONF_load_cert
TS_F_TS_CONF_LOAD_CERTS:154:TS_CONF_load_certs
TS_F_TS_CONF_LOAD_KEY:155:TS_CONF_load_key
TS_F_TS_CONF_LOOKUP_FAIL:152:ts_CONF_lookup_fail
TS_F_TS_CONF_SET_DEFAULT_ENGINE:146:TS_CONF_set_default_engine
TS_F_TS_GET_STATUS_TEXT:105:ts_get_status_text
TS_F_TS_MSG_IMPRINT_SET_ALGO:118:TS_MSG_IMPRINT_set_algo
TS_F_TS_REQ_SET_MSG_IMPRINT:119:TS_REQ_set_msg_imprint
TS_F_TS_REQ_SET_NONCE:120:TS_REQ_set_nonce
TS_F_TS_REQ_SET_POLICY_ID:121:TS_REQ_set_policy_id
TS_F_TS_RESP_CREATE_RESPONSE:122:TS_RESP_create_response
TS_F_TS_RESP_CREATE_TST_INFO:123:ts_RESP_create_tst_info
TS_F_TS_RESP_CTX_ADD_FAILURE_INFO:124:TS_RESP_CTX_add_failure_info
TS_F_TS_RESP_CTX_ADD_MD:125:TS_RESP_CTX_add_md
TS_F_TS_RESP_CTX_ADD_POLICY:126:TS_RESP_CTX_add_policy
TS_F_TS_RESP_CTX_NEW:127:TS_RESP_CTX_new
TS_F_TS_RESP_CTX_SET_ACCURACY:128:TS_RESP_CTX_set_accuracy
TS_F_TS_RESP_CTX_SET_CERTS:129:TS_RESP_CTX_set_certs
TS_F_TS_RESP_CTX_SET_DEF_POLICY:130:TS_RESP_CTX_set_def_policy
TS_F_TS_RESP_CTX_SET_SIGNER_CERT:131:TS_RESP_CTX_set_signer_cert
TS_F_TS_RESP_CTX_SET_STATUS_INFO:132:TS_RESP_CTX_set_status_info
TS_F_TS_RESP_GET_POLICY:133:ts_RESP_get_policy
TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION:134:TS_RESP_set_genTime_with_precision
TS_F_TS_RESP_SET_STATUS_INFO:135:TS_RESP_set_status_info
TS_F_TS_RESP_SET_TST_INFO:150:TS_RESP_set_tst_info
TS_F_TS_RESP_SIGN:136:ts_RESP_sign
TS_F_TS_RESP_VERIFY_SIGNATURE:106:TS_RESP_verify_signature
TS_F_TS_TST_INFO_SET_ACCURACY:137:TS_TST_INFO_set_accuracy
TS_F_TS_TST_INFO_SET_MSG_IMPRINT:138:TS_TST_INFO_set_msg_imprint
TS_F_TS_TST_INFO_SET_NONCE:139:TS_TST_INFO_set_nonce
TS_F_TS_TST_INFO_SET_POLICY_ID:140:TS_TST_INFO_set_policy_id
TS_F_TS_TST_INFO_SET_SERIAL:141:TS_TST_INFO_set_serial
TS_F_TS_TST_INFO_SET_TIME:142:TS_TST_INFO_set_time
TS_F_TS_TST_INFO_SET_TSA:143:TS_TST_INFO_set_tsa
TS_F_TS_VERIFY:108:*
TS_F_TS_VERIFY_CERT:109:ts_verify_cert
TS_F_TS_VERIFY_CTX_NEW:144:TS_VERIFY_CTX_new
UI_F_CLOSE_CONSOLE:115:close_console
UI_F_ECHO_CONSOLE:116:echo_console
UI_F_GENERAL_ALLOCATE_BOOLEAN:108:general_allocate_boolean
UI_F_GENERAL_ALLOCATE_PROMPT:109:general_allocate_prompt
UI_F_NOECHO_CONSOLE:117:noecho_console
UI_F_OPEN_CONSOLE:114:open_console
UI_F_UI_CONSTRUCT_PROMPT:121:UI_construct_prompt
UI_F_UI_CREATE_METHOD:112:UI_create_method
UI_F_UI_CTRL:111:UI_ctrl
UI_F_UI_DUP_ERROR_STRING:101:UI_dup_error_string
UI_F_UI_DUP_INFO_STRING:102:UI_dup_info_string
UI_F_UI_DUP_INPUT_BOOLEAN:110:UI_dup_input_boolean
UI_F_UI_DUP_INPUT_STRING:103:UI_dup_input_string
UI_F_UI_DUP_USER_DATA:118:UI_dup_user_data
UI_F_UI_DUP_VERIFY_STRING:106:UI_dup_verify_string
UI_F_UI_GET0_RESULT:107:UI_get0_result
UI_F_UI_GET_RESULT_LENGTH:119:UI_get_result_length
UI_F_UI_NEW_METHOD:104:UI_new_method
UI_F_UI_PROCESS:113:UI_process
UI_F_UI_SET_RESULT:105:UI_set_result
UI_F_UI_SET_RESULT_EX:120:UI_set_result_ex
X509V3_F_A2I_GENERAL_NAME:164:a2i_GENERAL_NAME
X509V3_F_ADDR_VALIDATE_PATH_INTERNAL:166:addr_validate_path_internal
X509V3_F_ASIDENTIFIERCHOICE_CANONIZE:161:ASIdentifierChoice_canonize
X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL:162:ASIdentifierChoice_is_canonical
X509V3_F_BIGNUM_TO_STRING:167:bignum_to_string
X509V3_F_COPY_EMAIL:122:copy_email
X509V3_F_COPY_ISSUER:123:copy_issuer
X509V3_F_DO_DIRNAME:144:do_dirname
X509V3_F_DO_EXT_I2D:135:do_ext_i2d
X509V3_F_DO_EXT_NCONF:151:do_ext_nconf
X509V3_F_GNAMES_FROM_SECTNAME:156:gnames_from_sectname
X509V3_F_I2S_ASN1_ENUMERATED:121:i2s_ASN1_ENUMERATED
X509V3_F_I2S_ASN1_IA5STRING:149:i2s_ASN1_IA5STRING
X509V3_F_I2S_ASN1_INTEGER:120:i2s_ASN1_INTEGER
X509V3_F_I2V_AUTHORITY_INFO_ACCESS:138:i2v_AUTHORITY_INFO_ACCESS
X509V3_F_LEVEL_ADD_NODE:168:level_add_node
X509V3_F_NOTICE_SECTION:132:notice_section
X509V3_F_NREF_NOS:133:nref_nos
X509V3_F_POLICY_CACHE_CREATE:169:policy_cache_create
X509V3_F_POLICY_CACHE_NEW:170:policy_cache_new
X509V3_F_POLICY_DATA_NEW:171:policy_data_new
X509V3_F_POLICY_SECTION:131:policy_section
X509V3_F_PROCESS_PCI_VALUE:150:process_pci_value
X509V3_F_R2I_CERTPOL:130:r2i_certpol
X509V3_F_R2I_PCI:155:r2i_pci
X509V3_F_S2I_ASN1_IA5STRING:100:s2i_ASN1_IA5STRING
X509V3_F_S2I_ASN1_INTEGER:108:s2i_ASN1_INTEGER
X509V3_F_S2I_ASN1_OCTET_STRING:112:s2i_ASN1_OCTET_STRING
X509V3_F_S2I_SKEY_ID:115:s2i_skey_id
X509V3_F_SET_DIST_POINT_NAME:158:set_dist_point_name
X509V3_F_SXNET_ADD_ID_ASC:125:SXNET_add_id_asc
X509V3_F_SXNET_ADD_ID_INTEGER:126:SXNET_add_id_INTEGER
X509V3_F_SXNET_ADD_ID_ULONG:127:SXNET_add_id_ulong
X509V3_F_SXNET_GET_ID_ASC:128:SXNET_get_id_asc
X509V3_F_SXNET_GET_ID_ULONG:129:SXNET_get_id_ulong
X509V3_F_TREE_INIT:172:tree_init
X509V3_F_V2I_ASIDENTIFIERS:163:v2i_ASIdentifiers
X509V3_F_V2I_ASN1_BIT_STRING:101:v2i_ASN1_BIT_STRING
X509V3_F_V2I_AUTHORITY_INFO_ACCESS:139:v2i_AUTHORITY_INFO_ACCESS
X509V3_F_V2I_AUTHORITY_KEYID:119:v2i_AUTHORITY_KEYID
X509V3_F_V2I_BASIC_CONSTRAINTS:102:v2i_BASIC_CONSTRAINTS
X509V3_F_V2I_CRLD:134:v2i_crld
X509V3_F_V2I_EXTENDED_KEY_USAGE:103:v2i_EXTENDED_KEY_USAGE
X509V3_F_V2I_GENERAL_NAMES:118:v2i_GENERAL_NAMES
X509V3_F_V2I_GENERAL_NAME_EX:117:v2i_GENERAL_NAME_ex
X509V3_F_V2I_IDP:157:v2i_idp
X509V3_F_V2I_IPADDRBLOCKS:159:v2i_IPAddrBlocks
X509V3_F_V2I_ISSUER_ALT:153:v2i_issuer_alt
X509V3_F_V2I_NAME_CONSTRAINTS:147:v2i_NAME_CONSTRAINTS
X509V3_F_V2I_POLICY_CONSTRAINTS:146:v2i_POLICY_CONSTRAINTS
X509V3_F_V2I_POLICY_MAPPINGS:145:v2i_POLICY_MAPPINGS
X509V3_F_V2I_SUBJECT_ALT:154:v2i_subject_alt
X509V3_F_V2I_TLS_FEATURE:165:v2i_TLS_FEATURE
X509V3_F_V3_GENERIC_EXTENSION:116:v3_generic_extension
X509V3_F_X509V3_ADD1_I2D:140:X509V3_add1_i2d
X509V3_F_X509V3_ADD_VALUE:105:X509V3_add_value
X509V3_F_X509V3_EXT_ADD:104:X509V3_EXT_add
X509V3_F_X509V3_EXT_ADD_ALIAS:106:X509V3_EXT_add_alias
X509V3_F_X509V3_EXT_I2D:136:X509V3_EXT_i2d
X509V3_F_X509V3_EXT_NCONF:152:X509V3_EXT_nconf
X509V3_F_X509V3_GET_SECTION:142:X509V3_get_section
X509V3_F_X509V3_GET_STRING:143:X509V3_get_string
X509V3_F_X509V3_GET_VALUE_BOOL:110:X509V3_get_value_bool
X509V3_F_X509V3_PARSE_LIST:109:X509V3_parse_list
X509V3_F_X509_PURPOSE_ADD:137:X509_PURPOSE_add
X509V3_F_X509_PURPOSE_SET:141:X509_PURPOSE_set
X509_F_ADD_CERT_DIR:100:add_cert_dir
X509_F_BUILD_CHAIN:106:build_chain
X509_F_BY_FILE_CTRL:101:by_file_ctrl
X509_F_CHECK_NAME_CONSTRAINTS:149:check_name_constraints
X509_F_CHECK_POLICY:145:check_policy
X509_F_DANE_I2D:107:dane_i2d
X509_F_DIR_CTRL:102:dir_ctrl
X509_F_GET_CERT_BY_SUBJECT:103:get_cert_by_subject
X509_F_I2D_X509_AUX:151:i2d_X509_AUX
X509_F_LOOKUP_CERTS_SK:152:lookup_certs_sk
X509_F_NETSCAPE_SPKI_B64_DECODE:129:NETSCAPE_SPKI_b64_decode
X509_F_NETSCAPE_SPKI_B64_ENCODE:130:NETSCAPE_SPKI_b64_encode
X509_F_NEW_DIR:153:new_dir
X509_F_X509AT_ADD1_ATTR:135:X509at_add1_attr
X509_F_X509V3_ADD_EXT:104:X509v3_add_ext
X509_F_X509_ATTRIBUTE_CREATE_BY_NID:136:X509_ATTRIBUTE_create_by_NID
X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ:137:X509_ATTRIBUTE_create_by_OBJ
X509_F_X509_ATTRIBUTE_CREATE_BY_TXT:140:X509_ATTRIBUTE_create_by_txt
X509_F_X509_ATTRIBUTE_GET0_DATA:139:X509_ATTRIBUTE_get0_data
X509_F_X509_ATTRIBUTE_SET1_DATA:138:X509_ATTRIBUTE_set1_data
X509_F_X509_CHECK_PRIVATE_KEY:128:X509_check_private_key
X509_F_X509_CRL_DIFF:105:X509_CRL_diff
X509_F_X509_CRL_METHOD_NEW:154:X509_CRL_METHOD_new
X509_F_X509_CRL_PRINT_FP:147:X509_CRL_print_fp
X509_F_X509_EXTENSION_CREATE_BY_NID:108:X509_EXTENSION_create_by_NID
X509_F_X509_EXTENSION_CREATE_BY_OBJ:109:X509_EXTENSION_create_by_OBJ
X509_F_X509_GET_PUBKEY_PARAMETERS:110:X509_get_pubkey_parameters
X509_F_X509_LOAD_CERT_CRL_FILE:132:X509_load_cert_crl_file
X509_F_X509_LOAD_CERT_FILE:111:X509_load_cert_file
X509_F_X509_LOAD_CRL_FILE:112:X509_load_crl_file
X509_F_X509_LOOKUP_METH_NEW:160:X509_LOOKUP_meth_new
X509_F_X509_LOOKUP_NEW:155:X509_LOOKUP_new
X509_F_X509_NAME_ADD_ENTRY:113:X509_NAME_add_entry
X509_F_X509_NAME_CANON:156:x509_name_canon
X509_F_X509_NAME_ENTRY_CREATE_BY_NID:114:X509_NAME_ENTRY_create_by_NID
X509_F_X509_NAME_ENTRY_CREATE_BY_TXT:131:X509_NAME_ENTRY_create_by_txt
X509_F_X509_NAME_ENTRY_SET_OBJECT:115:X509_NAME_ENTRY_set_object
X509_F_X509_NAME_ONELINE:116:X509_NAME_oneline
X509_F_X509_NAME_PRINT:117:X509_NAME_print
X509_F_X509_OBJECT_NEW:150:X509_OBJECT_new
X509_F_X509_PRINT_EX_FP:118:X509_print_ex_fp
X509_F_X509_PUBKEY_DECODE:148:x509_pubkey_decode
X509_F_X509_PUBKEY_GET0:119:X509_PUBKEY_get0
X509_F_X509_PUBKEY_SET:120:X509_PUBKEY_set
X509_F_X509_REQ_CHECK_PRIVATE_KEY:144:X509_REQ_check_private_key
X509_F_X509_REQ_PRINT_EX:121:X509_REQ_print_ex
X509_F_X509_REQ_PRINT_FP:122:X509_REQ_print_fp
X509_F_X509_REQ_TO_X509:123:X509_REQ_to_X509
X509_F_X509_STORE_ADD_CERT:124:X509_STORE_add_cert
X509_F_X509_STORE_ADD_CRL:125:X509_STORE_add_crl
X509_F_X509_STORE_ADD_LOOKUP:157:X509_STORE_add_lookup
X509_F_X509_STORE_CTX_GET1_ISSUER:146:X509_STORE_CTX_get1_issuer
X509_F_X509_STORE_CTX_INIT:143:X509_STORE_CTX_init
X509_F_X509_STORE_CTX_NEW:142:X509_STORE_CTX_new
X509_F_X509_STORE_CTX_PURPOSE_INHERIT:134:X509_STORE_CTX_purpose_inherit
X509_F_X509_STORE_NEW:158:X509_STORE_new
X509_F_X509_TO_X509_REQ:126:X509_to_X509_REQ
X509_F_X509_TRUST_ADD:133:X509_TRUST_add
X509_F_X509_TRUST_SET:141:X509_TRUST_set
X509_F_X509_VERIFY_CERT:127:X509_verify_cert
X509_F_X509_VERIFY_PARAM_NEW:159:X509_VERIFY_PARAM_new
#Reason codes
ASN1_R_ADDING_OBJECT:171:adding object
ASN1_R_ASN1_PARSE_ERROR:203:asn1 parse error
ASN1_R_ASN1_SIG_PARSE_ERROR:204:asn1 sig parse error
ASN1_R_AUX_ERROR:100:aux error
ASN1_R_BAD_OBJECT_HEADER:102:bad object header
ASN1_R_BMPSTRING_IS_WRONG_LENGTH:214:bmpstring is wrong length
ASN1_R_BN_LIB:105:bn lib
ASN1_R_BOOLEAN_IS_WRONG_LENGTH:106:boolean is wrong length
ASN1_R_BUFFER_TOO_SMALL:107:buffer too small
ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER:108:cipher has no object identifier
ASN1_R_CONTEXT_NOT_INITIALISED:217:context not initialised
ASN1_R_DATA_IS_WRONG:109:data is wrong
ASN1_R_DECODE_ERROR:110:decode error
ASN1_R_DEPTH_EXCEEDED:174:depth exceeded
ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED:198:digest and key type not supported
ASN1_R_ENCODE_ERROR:112:encode error
ASN1_R_ERROR_GETTING_TIME:173:error getting time
ASN1_R_ERROR_LOADING_SECTION:172:error loading section
ASN1_R_ERROR_SETTING_CIPHER_PARAMS:114:error setting cipher params
ASN1_R_EXPECTING_AN_INTEGER:115:expecting an integer
ASN1_R_EXPECTING_AN_OBJECT:116:expecting an object
ASN1_R_EXPLICIT_LENGTH_MISMATCH:119:explicit length mismatch
ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED:120:explicit tag not constructed
ASN1_R_FIELD_MISSING:121:field missing
ASN1_R_FIRST_NUM_TOO_LARGE:122:first num too large
ASN1_R_HEADER_TOO_LONG:123:header too long
ASN1_R_ILLEGAL_BITSTRING_FORMAT:175:illegal bitstring format
ASN1_R_ILLEGAL_BOOLEAN:176:illegal boolean
ASN1_R_ILLEGAL_CHARACTERS:124:illegal characters
ASN1_R_ILLEGAL_FORMAT:177:illegal format
ASN1_R_ILLEGAL_HEX:178:illegal hex
ASN1_R_ILLEGAL_IMPLICIT_TAG:179:illegal implicit tag
ASN1_R_ILLEGAL_INTEGER:180:illegal integer
ASN1_R_ILLEGAL_NEGATIVE_VALUE:226:illegal negative value
ASN1_R_ILLEGAL_NESTED_TAGGING:181:illegal nested tagging
ASN1_R_ILLEGAL_NULL:125:illegal null
ASN1_R_ILLEGAL_NULL_VALUE:182:illegal null value
ASN1_R_ILLEGAL_OBJECT:183:illegal object
ASN1_R_ILLEGAL_OPTIONAL_ANY:126:illegal optional any
ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE:170:illegal options on item template
ASN1_R_ILLEGAL_PADDING:221:illegal padding
ASN1_R_ILLEGAL_TAGGED_ANY:127:illegal tagged any
ASN1_R_ILLEGAL_TIME_VALUE:184:illegal time value
ASN1_R_ILLEGAL_ZERO_CONTENT:222:illegal zero content
ASN1_R_INTEGER_NOT_ASCII_FORMAT:185:integer not ascii format
ASN1_R_INTEGER_TOO_LARGE_FOR_LONG:128:integer too large for long
ASN1_R_INVALID_BIT_STRING_BITS_LEFT:220:invalid bit string bits left
ASN1_R_INVALID_BMPSTRING_LENGTH:129:invalid bmpstring length
ASN1_R_INVALID_DIGIT:130:invalid digit
ASN1_R_INVALID_MIME_TYPE:205:invalid mime type
ASN1_R_INVALID_MODIFIER:186:invalid modifier
ASN1_R_INVALID_NUMBER:187:invalid number
ASN1_R_INVALID_OBJECT_ENCODING:216:invalid object encoding
ASN1_R_INVALID_SCRYPT_PARAMETERS:227:invalid scrypt parameters
ASN1_R_INVALID_SEPARATOR:131:invalid separator
ASN1_R_INVALID_STRING_TABLE_VALUE:218:invalid string table value
ASN1_R_INVALID_UNIVERSALSTRING_LENGTH:133:invalid universalstring length
ASN1_R_INVALID_UTF8STRING:134:invalid utf8string
ASN1_R_INVALID_VALUE:219:invalid value
ASN1_R_LIST_ERROR:188:list error
ASN1_R_MIME_NO_CONTENT_TYPE:206:mime no content type
ASN1_R_MIME_PARSE_ERROR:207:mime parse error
ASN1_R_MIME_SIG_PARSE_ERROR:208:mime sig parse error
ASN1_R_MISSING_EOC:137:missing eoc
ASN1_R_MISSING_SECOND_NUMBER:138:missing second number
ASN1_R_MISSING_VALUE:189:missing value
ASN1_R_MSTRING_NOT_UNIVERSAL:139:mstring not universal
ASN1_R_MSTRING_WRONG_TAG:140:mstring wrong tag
ASN1_R_NESTED_ASN1_STRING:197:nested asn1 string
ASN1_R_NESTED_TOO_DEEP:201:nested too deep
ASN1_R_NON_HEX_CHARACTERS:141:non hex characters
ASN1_R_NOT_ASCII_FORMAT:190:not ascii format
ASN1_R_NOT_ENOUGH_DATA:142:not enough data
ASN1_R_NO_CONTENT_TYPE:209:no content type
ASN1_R_NO_MATCHING_CHOICE_TYPE:143:no matching choice type
ASN1_R_NO_MULTIPART_BODY_FAILURE:210:no multipart body failure
ASN1_R_NO_MULTIPART_BOUNDARY:211:no multipart boundary
ASN1_R_NO_SIG_CONTENT_TYPE:212:no sig content type
ASN1_R_NULL_IS_WRONG_LENGTH:144:null is wrong length
ASN1_R_OBJECT_NOT_ASCII_FORMAT:191:object not ascii format
ASN1_R_ODD_NUMBER_OF_CHARS:145:odd number of chars
ASN1_R_SECOND_NUMBER_TOO_LARGE:147:second number too large
ASN1_R_SEQUENCE_LENGTH_MISMATCH:148:sequence length mismatch
ASN1_R_SEQUENCE_NOT_CONSTRUCTED:149:sequence not constructed
ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG:192:sequence or set needs config
ASN1_R_SHORT_LINE:150:short line
ASN1_R_SIG_INVALID_MIME_TYPE:213:sig invalid mime type
ASN1_R_STREAMING_NOT_SUPPORTED:202:streaming not supported
ASN1_R_STRING_TOO_LONG:151:string too long
ASN1_R_STRING_TOO_SHORT:152:string too short
ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD:154:\
the asn1 object identifier is not known for this md
ASN1_R_TIME_NOT_ASCII_FORMAT:193:time not ascii format
ASN1_R_TOO_LARGE:223:too large
ASN1_R_TOO_LONG:155:too long
ASN1_R_TOO_SMALL:224:too small
ASN1_R_TYPE_NOT_CONSTRUCTED:156:type not constructed
ASN1_R_TYPE_NOT_PRIMITIVE:195:type not primitive
ASN1_R_UNEXPECTED_EOC:159:unexpected eoc
ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH:215:universalstring is wrong length
ASN1_R_UNKNOWN_FORMAT:160:unknown format
ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:161:unknown message digest algorithm
ASN1_R_UNKNOWN_OBJECT_TYPE:162:unknown object type
ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE:163:unknown public key type
ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM:199:unknown signature algorithm
ASN1_R_UNKNOWN_TAG:194:unknown tag
ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE:164:unsupported any defined by type
ASN1_R_UNSUPPORTED_CIPHER:228:unsupported cipher
ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE:167:unsupported public key type
ASN1_R_UNSUPPORTED_TYPE:196:unsupported type
ASN1_R_WRONG_INTEGER_TYPE:225:wrong integer type
ASN1_R_WRONG_PUBLIC_KEY_TYPE:200:wrong public key type
ASN1_R_WRONG_TAG:168:wrong tag
ASYNC_R_FAILED_TO_SET_POOL:101:failed to set pool
ASYNC_R_FAILED_TO_SWAP_CONTEXT:102:failed to swap context
ASYNC_R_INIT_FAILED:105:init failed
ASYNC_R_INVALID_POOL_SIZE:103:invalid pool size
BIO_R_ACCEPT_ERROR:100:accept error
BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET:141:addrinfo addr is not af inet
BIO_R_AMBIGUOUS_HOST_OR_SERVICE:129:ambiguous host or service
BIO_R_BAD_FOPEN_MODE:101:bad fopen mode
BIO_R_BROKEN_PIPE:124:broken pipe
BIO_R_CONNECT_ERROR:103:connect error
BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET:107:gethostbyname addr is not af inet
BIO_R_GETSOCKNAME_ERROR:132:getsockname error
BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS:133:getsockname truncated address
BIO_R_GETTING_SOCKTYPE:134:getting socktype
BIO_R_INVALID_ARGUMENT:125:invalid argument
BIO_R_INVALID_SOCKET:135:invalid socket
BIO_R_IN_USE:123:in use
BIO_R_LENGTH_TOO_LONG:102:length too long
BIO_R_LISTEN_V6_ONLY:136:listen v6 only
BIO_R_LOOKUP_RETURNED_NOTHING:142:lookup returned nothing
BIO_R_MALFORMED_HOST_OR_SERVICE:130:malformed host or service
BIO_R_NBIO_CONNECT_ERROR:110:nbio connect error
BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED:143:\
no accept addr or service specified
BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED:144:no hostname or service specified
BIO_R_NO_PORT_DEFINED:113:no port defined
BIO_R_NO_SUCH_FILE:128:no such file
BIO_R_NULL_PARAMETER:115:null parameter
BIO_R_UNABLE_TO_BIND_SOCKET:117:unable to bind socket
BIO_R_UNABLE_TO_CREATE_SOCKET:118:unable to create socket
BIO_R_UNABLE_TO_KEEPALIVE:137:unable to keepalive
BIO_R_UNABLE_TO_LISTEN_SOCKET:119:unable to listen socket
BIO_R_UNABLE_TO_NODELAY:138:unable to nodelay
BIO_R_UNABLE_TO_REUSEADDR:139:unable to reuseaddr
BIO_R_UNAVAILABLE_IP_FAMILY:145:unavailable ip family
BIO_R_UNINITIALIZED:120:uninitialized
BIO_R_UNKNOWN_INFO_TYPE:140:unknown info type
BIO_R_UNSUPPORTED_IP_FAMILY:146:unsupported ip family
BIO_R_UNSUPPORTED_METHOD:121:unsupported method
BIO_R_UNSUPPORTED_PROTOCOL_FAMILY:131:unsupported protocol family
BIO_R_WRITE_TO_READ_ONLY_BIO:126:write to read only BIO
BIO_R_WSASTARTUP:122:WSAStartup
BN_R_ARG2_LT_ARG3:100:arg2 lt arg3
BN_R_BAD_RECIPROCAL:101:bad reciprocal
BN_R_BIGNUM_TOO_LONG:114:bignum too long
BN_R_BITS_TOO_SMALL:118:bits too small
BN_R_CALLED_WITH_EVEN_MODULUS:102:called with even modulus
BN_R_DIV_BY_ZERO:103:div by zero
BN_R_ENCODING_ERROR:104:encoding error
BN_R_EXPAND_ON_STATIC_BIGNUM_DATA:105:expand on static bignum data
BN_R_INPUT_NOT_REDUCED:110:input not reduced
BN_R_INVALID_LENGTH:106:invalid length
BN_R_INVALID_RANGE:115:invalid range
BN_R_INVALID_SHIFT:119:invalid shift
BN_R_NOT_A_SQUARE:111:not a square
BN_R_NOT_INITIALIZED:107:not initialized
BN_R_NO_INVERSE:108:no inverse
BN_R_NO_SOLUTION:116:no solution
BN_R_PRIVATE_KEY_TOO_LARGE:117:private key too large
BN_R_P_IS_NOT_PRIME:112:p is not prime
BN_R_TOO_MANY_ITERATIONS:113:too many iterations
BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables
CMS_R_ADD_SIGNER_ERROR:99:add signer error
CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present
CMS_R_CERTIFICATE_HAS_NO_KEYID:160:certificate has no keyid
CMS_R_CERTIFICATE_VERIFY_ERROR:100:certificate verify error
CMS_R_CIPHER_INITIALISATION_ERROR:101:cipher initialisation error
CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR:102:\
cipher parameter initialisation error
CMS_R_CMS_DATAFINAL_ERROR:103:cms datafinal error
CMS_R_CMS_LIB:104:cms lib
CMS_R_CONTENTIDENTIFIER_MISMATCH:170:contentidentifier mismatch
CMS_R_CONTENT_NOT_FOUND:105:content not found
CMS_R_CONTENT_TYPE_MISMATCH:171:content type mismatch
CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA:106:content type not compressed data
CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA:107:content type not enveloped data
CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA:108:content type not signed data
CMS_R_CONTENT_VERIFY_ERROR:109:content verify error
CMS_R_CTRL_ERROR:110:ctrl error
CMS_R_CTRL_FAILURE:111:ctrl failure
CMS_R_DECRYPT_ERROR:112:decrypt error
CMS_R_ERROR_GETTING_PUBLIC_KEY:113:error getting public key
CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE:114:\
error reading messagedigest attribute
CMS_R_ERROR_SETTING_KEY:115:error setting key
CMS_R_ERROR_SETTING_RECIPIENTINFO:116:error setting recipientinfo
CMS_R_INVALID_ENCRYPTED_KEY_LENGTH:117:invalid encrypted key length
CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER:176:invalid key encryption parameter
CMS_R_INVALID_KEY_LENGTH:118:invalid key length
CMS_R_MD_BIO_INIT_ERROR:119:md bio init error
CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH:120:\
messagedigest attribute wrong length
CMS_R_MESSAGEDIGEST_WRONG_LENGTH:121:messagedigest wrong length
CMS_R_MSGSIGDIGEST_ERROR:172:msgsigdigest error
CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE:162:msgsigdigest verification failure
CMS_R_MSGSIGDIGEST_WRONG_LENGTH:163:msgsigdigest wrong length
CMS_R_NEED_ONE_SIGNER:164:need one signer
CMS_R_NOT_A_SIGNED_RECEIPT:165:not a signed receipt
CMS_R_NOT_ENCRYPTED_DATA:122:not encrypted data
CMS_R_NOT_KEK:123:not kek
CMS_R_NOT_KEY_AGREEMENT:181:not key agreement
CMS_R_NOT_KEY_TRANSPORT:124:not key transport
CMS_R_NOT_PWRI:177:not pwri
CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE:125:not supported for this key type
CMS_R_NO_CIPHER:126:no cipher
CMS_R_NO_CONTENT:127:no content
CMS_R_NO_CONTENT_TYPE:173:no content type
CMS_R_NO_DEFAULT_DIGEST:128:no default digest
CMS_R_NO_DIGEST_SET:129:no digest set
CMS_R_NO_KEY:130:no key
CMS_R_NO_KEY_OR_CERT:174:no key or cert
CMS_R_NO_MATCHING_DIGEST:131:no matching digest
CMS_R_NO_MATCHING_RECIPIENT:132:no matching recipient
CMS_R_NO_MATCHING_SIGNATURE:166:no matching signature
CMS_R_NO_MSGSIGDIGEST:167:no msgsigdigest
CMS_R_NO_PASSWORD:178:no password
CMS_R_NO_PRIVATE_KEY:133:no private key
CMS_R_NO_PUBLIC_KEY:134:no public key
CMS_R_NO_RECEIPT_REQUEST:168:no receipt request
CMS_R_NO_SIGNERS:135:no signers
CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:136:\
private key does not match certificate
CMS_R_RECEIPT_DECODE_ERROR:169:receipt decode error
CMS_R_RECIPIENT_ERROR:137:recipient error
CMS_R_SIGNER_CERTIFICATE_NOT_FOUND:138:signer certificate not found
CMS_R_SIGNFINAL_ERROR:139:signfinal error
CMS_R_SMIME_TEXT_ERROR:140:smime text error
CMS_R_STORE_INIT_ERROR:141:store init error
CMS_R_TYPE_NOT_COMPRESSED_DATA:142:type not compressed data
CMS_R_TYPE_NOT_DATA:143:type not data
CMS_R_TYPE_NOT_DIGESTED_DATA:144:type not digested data
CMS_R_TYPE_NOT_ENCRYPTED_DATA:145:type not encrypted data
CMS_R_TYPE_NOT_ENVELOPED_DATA:146:type not enveloped data
CMS_R_UNABLE_TO_FINALIZE_CONTEXT:147:unable to finalize context
CMS_R_UNKNOWN_CIPHER:148:unknown cipher
CMS_R_UNKNOWN_DIGEST_ALGORITHM:149:unknown digest algorithm
CMS_R_UNKNOWN_ID:150:unknown id
CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM:151:unsupported compression algorithm
CMS_R_UNSUPPORTED_CONTENT_TYPE:152:unsupported content type
CMS_R_UNSUPPORTED_KEK_ALGORITHM:153:unsupported kek algorithm
CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM:179:\
unsupported key encryption algorithm
CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE:155:unsupported recipientinfo type
CMS_R_UNSUPPORTED_RECIPIENT_TYPE:154:unsupported recipient type
CMS_R_UNSUPPORTED_TYPE:156:unsupported type
CMS_R_UNWRAP_ERROR:157:unwrap error
CMS_R_UNWRAP_FAILURE:180:unwrap failure
CMS_R_VERIFICATION_FAILURE:158:verification failure
CMS_R_WRAP_ERROR:159:wrap error
COMP_R_ZLIB_DEFLATE_ERROR:99:zlib deflate error
COMP_R_ZLIB_INFLATE_ERROR:100:zlib inflate error
COMP_R_ZLIB_NOT_SUPPORTED:101:zlib not supported
CONF_R_ERROR_LOADING_DSO:110:error loading dso
CONF_R_LIST_CANNOT_BE_NULL:115:list cannot be null
CONF_R_MISSING_CLOSE_SQUARE_BRACKET:100:missing close square bracket
CONF_R_MISSING_EQUAL_SIGN:101:missing equal sign
CONF_R_MISSING_INIT_FUNCTION:112:missing init function
CONF_R_MODULE_INITIALIZATION_ERROR:109:module initialization error
CONF_R_NO_CLOSE_BRACE:102:no close brace
CONF_R_NO_CONF:105:no conf
CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE:106:no conf or environment variable
CONF_R_NO_SECTION:107:no section
CONF_R_NO_SUCH_FILE:114:no such file
CONF_R_NO_VALUE:108:no value
CONF_R_NUMBER_TOO_LARGE:121:number too large
CONF_R_RECURSIVE_DIRECTORY_INCLUDE:111:recursive directory include
CONF_R_SSL_COMMAND_SECTION_EMPTY:117:ssl command section empty
CONF_R_SSL_COMMAND_SECTION_NOT_FOUND:118:ssl command section not found
CONF_R_SSL_SECTION_EMPTY:119:ssl section empty
CONF_R_SSL_SECTION_NOT_FOUND:120:ssl section not found
CONF_R_UNABLE_TO_CREATE_NEW_SECTION:103:unable to create new section
CONF_R_UNKNOWN_MODULE_NAME:113:unknown module name
CONF_R_VARIABLE_EXPANSION_TOO_LONG:116:variable expansion too long
CONF_R_VARIABLE_HAS_NO_VALUE:104:variable has no value
CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported
CRYPTO_R_ILLEGAL_HEX_DIGIT:102:illegal hex digit
CRYPTO_R_ODD_NUMBER_OF_DIGITS:103:odd number of digits
CT_R_BASE64_DECODE_ERROR:108:base64 decode error
CT_R_INVALID_LOG_ID_LENGTH:100:invalid log id length
CT_R_LOG_CONF_INVALID:109:log conf invalid
CT_R_LOG_CONF_INVALID_KEY:110:log conf invalid key
CT_R_LOG_CONF_MISSING_DESCRIPTION:111:log conf missing description
CT_R_LOG_CONF_MISSING_KEY:112:log conf missing key
CT_R_LOG_KEY_INVALID:113:log key invalid
CT_R_SCT_FUTURE_TIMESTAMP:116:sct future timestamp
CT_R_SCT_INVALID:104:sct invalid
CT_R_SCT_INVALID_SIGNATURE:107:sct invalid signature
CT_R_SCT_LIST_INVALID:105:sct list invalid
CT_R_SCT_LOG_ID_MISMATCH:114:sct log id mismatch
CT_R_SCT_NOT_SET:106:sct not set
CT_R_SCT_UNSUPPORTED_VERSION:115:sct unsupported version
CT_R_UNRECOGNIZED_SIGNATURE_NID:101:unrecognized signature nid
CT_R_UNSUPPORTED_ENTRY_TYPE:102:unsupported entry type
CT_R_UNSUPPORTED_VERSION:103:unsupported version
DH_R_BAD_GENERATOR:101:bad generator
DH_R_BN_DECODE_ERROR:109:bn decode error
DH_R_BN_ERROR:106:bn error
DH_R_CHECK_INVALID_J_VALUE:115:check invalid j value
DH_R_CHECK_INVALID_Q_VALUE:116:check invalid q value
DH_R_CHECK_PUBKEY_INVALID:122:check pubkey invalid
DH_R_CHECK_PUBKEY_TOO_LARGE:123:check pubkey too large
DH_R_CHECK_PUBKEY_TOO_SMALL:124:check pubkey too small
DH_R_CHECK_P_NOT_PRIME:117:check p not prime
DH_R_CHECK_P_NOT_SAFE_PRIME:118:check p not safe prime
DH_R_CHECK_Q_NOT_PRIME:119:check q not prime
DH_R_DECODE_ERROR:104:decode error
DH_R_INVALID_PARAMETER_NAME:110:invalid parameter name
DH_R_INVALID_PARAMETER_NID:114:invalid parameter nid
DH_R_INVALID_PUBKEY:102:invalid public key
DH_R_KDF_PARAMETER_ERROR:112:kdf parameter error
DH_R_KEYS_NOT_SET:108:keys not set
DH_R_MISSING_PUBKEY:125:missing pubkey
DH_R_MODULUS_TOO_LARGE:103:modulus too large
DH_R_NOT_SUITABLE_GENERATOR:120:not suitable generator
DH_R_NO_PARAMETERS_SET:107:no parameters set
DH_R_NO_PRIVATE_VALUE:100:no private value
DH_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error
DH_R_PEER_KEY_ERROR:111:peer key error
DH_R_SHARED_INFO_ERROR:113:shared info error
DH_R_UNABLE_TO_CHECK_GENERATOR:121:unable to check generator
DSA_R_BAD_Q_VALUE:102:bad q value
DSA_R_BN_DECODE_ERROR:108:bn decode error
DSA_R_BN_ERROR:109:bn error
DSA_R_DECODE_ERROR:104:decode error
DSA_R_INVALID_DIGEST_TYPE:106:invalid digest type
DSA_R_INVALID_PARAMETERS:112:invalid parameters
DSA_R_MISSING_PARAMETERS:101:missing parameters
DSA_R_MODULUS_TOO_LARGE:103:modulus too large
DSA_R_NO_PARAMETERS_SET:107:no parameters set
DSA_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error
DSA_R_Q_NOT_PRIME:113:q not prime
DSA_R_SEED_LEN_SMALL:110:seed_len is less than the length of q
DSO_R_CTRL_FAILED:100:control command failed
DSO_R_DSO_ALREADY_LOADED:110:dso already loaded
DSO_R_EMPTY_FILE_STRUCTURE:113:empty file structure
DSO_R_FAILURE:114:failure
DSO_R_FILENAME_TOO_BIG:101:filename too big
DSO_R_FINISH_FAILED:102:cleanup method function failed
DSO_R_INCORRECT_FILE_SYNTAX:115:incorrect file syntax
DSO_R_LOAD_FAILED:103:could not load the shared library
DSO_R_NAME_TRANSLATION_FAILED:109:name translation failed
DSO_R_NO_FILENAME:111:no filename
DSO_R_NULL_HANDLE:104:a null shared library handle was used
DSO_R_SET_FILENAME_FAILED:112:set filename failed
DSO_R_STACK_ERROR:105:the meth_data stack is corrupt
DSO_R_SYM_FAILURE:106:could not bind to the requested symbol name
DSO_R_UNLOAD_FAILED:107:could not unload the shared library
DSO_R_UNSUPPORTED:108:functionality not supported
EC_R_ASN1_ERROR:115:asn1 error
EC_R_BAD_SIGNATURE:156:bad signature
EC_R_BIGNUM_OUT_OF_RANGE:144:bignum out of range
EC_R_BUFFER_TOO_SMALL:100:buffer too small
EC_R_COORDINATES_OUT_OF_RANGE:146:coordinates out of range
EC_R_CURVE_DOES_NOT_SUPPORT_ECDH:160:curve does not support ecdh
EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING:159:curve does not support signing
EC_R_D2I_ECPKPARAMETERS_FAILURE:117:d2i ecpkparameters failure
EC_R_DECODE_ERROR:142:decode error
EC_R_DISCRIMINANT_IS_ZERO:118:discriminant is zero
EC_R_EC_GROUP_NEW_BY_NAME_FAILURE:119:ec group new by name failure
EC_R_FIELD_TOO_LARGE:143:field too large
EC_R_GF2M_NOT_SUPPORTED:147:gf2m not supported
EC_R_GROUP2PKPARAMETERS_FAILURE:120:group2pkparameters failure
EC_R_I2D_ECPKPARAMETERS_FAILURE:121:i2d ecpkparameters failure
EC_R_INCOMPATIBLE_OBJECTS:101:incompatible objects
EC_R_INVALID_ARGUMENT:112:invalid argument
EC_R_INVALID_COMPRESSED_POINT:110:invalid compressed point
EC_R_INVALID_COMPRESSION_BIT:109:invalid compression bit
EC_R_INVALID_CURVE:141:invalid curve
EC_R_INVALID_DIGEST:151:invalid digest
EC_R_INVALID_DIGEST_TYPE:138:invalid digest type
EC_R_INVALID_ENCODING:102:invalid encoding
EC_R_INVALID_FIELD:103:invalid field
EC_R_INVALID_FORM:104:invalid form
EC_R_INVALID_GROUP_ORDER:122:invalid group order
EC_R_INVALID_KEY:116:invalid key
EC_R_INVALID_OUTPUT_LENGTH:161:invalid output length
EC_R_INVALID_PEER_KEY:133:invalid peer key
EC_R_INVALID_PENTANOMIAL_BASIS:132:invalid pentanomial basis
EC_R_INVALID_PRIVATE_KEY:123:invalid private key
EC_R_INVALID_TRINOMIAL_BASIS:137:invalid trinomial basis
EC_R_KDF_PARAMETER_ERROR:148:kdf parameter error
EC_R_KEYS_NOT_SET:140:keys not set
EC_R_LADDER_POST_FAILURE:136:ladder post failure
EC_R_LADDER_PRE_FAILURE:153:ladder pre failure
EC_R_LADDER_STEP_FAILURE:162:ladder step failure
EC_R_MISSING_PARAMETERS:124:missing parameters
EC_R_MISSING_PRIVATE_KEY:125:missing private key
EC_R_NEED_NEW_SETUP_VALUES:157:need new setup values
EC_R_NOT_A_NIST_PRIME:135:not a NIST prime
EC_R_NOT_IMPLEMENTED:126:not implemented
EC_R_NOT_INITIALIZED:111:not initialized
EC_R_NO_PARAMETERS_SET:139:no parameters set
EC_R_NO_PRIVATE_VALUE:154:no private value
EC_R_OPERATION_NOT_SUPPORTED:152:operation not supported
EC_R_PASSED_NULL_PARAMETER:134:passed null parameter
EC_R_PEER_KEY_ERROR:149:peer key error
EC_R_PKPARAMETERS2GROUP_FAILURE:127:pkparameters2group failure
EC_R_POINT_ARITHMETIC_FAILURE:155:point arithmetic failure
EC_R_POINT_AT_INFINITY:106:point at infinity
EC_R_POINT_COORDINATES_BLIND_FAILURE:163:point coordinates blind failure
EC_R_POINT_IS_NOT_ON_CURVE:107:point is not on curve
EC_R_RANDOM_NUMBER_GENERATION_FAILED:158:random number generation failed
EC_R_SHARED_INFO_ERROR:150:shared info error
EC_R_SLOT_FULL:108:slot full
EC_R_UNDEFINED_GENERATOR:113:undefined generator
EC_R_UNDEFINED_ORDER:128:undefined order
EC_R_UNKNOWN_COFACTOR:164:unknown cofactor
EC_R_UNKNOWN_GROUP:129:unknown group
EC_R_UNKNOWN_ORDER:114:unknown order
EC_R_UNSUPPORTED_FIELD:131:unsupported field
EC_R_WRONG_CURVE_PARAMETERS:145:wrong curve parameters
EC_R_WRONG_ORDER:130:wrong order
ENGINE_R_ALREADY_LOADED:100:already loaded
ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER:133:argument is not a number
ENGINE_R_CMD_NOT_EXECUTABLE:134:cmd not executable
ENGINE_R_COMMAND_TAKES_INPUT:135:command takes input
ENGINE_R_COMMAND_TAKES_NO_INPUT:136:command takes no input
ENGINE_R_CONFLICTING_ENGINE_ID:103:conflicting engine id
ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED:119:ctrl command not implemented
ENGINE_R_DSO_FAILURE:104:DSO failure
ENGINE_R_DSO_NOT_FOUND:132:dso not found
ENGINE_R_ENGINES_SECTION_ERROR:148:engines section error
ENGINE_R_ENGINE_CONFIGURATION_ERROR:102:engine configuration error
ENGINE_R_ENGINE_IS_NOT_IN_LIST:105:engine is not in the list
ENGINE_R_ENGINE_SECTION_ERROR:149:engine section error
ENGINE_R_FAILED_LOADING_PRIVATE_KEY:128:failed loading private key
ENGINE_R_FAILED_LOADING_PUBLIC_KEY:129:failed loading public key
ENGINE_R_FINISH_FAILED:106:finish failed
ENGINE_R_ID_OR_NAME_MISSING:108:'id' or 'name' missing
ENGINE_R_INIT_FAILED:109:init failed
ENGINE_R_INTERNAL_LIST_ERROR:110:internal list error
ENGINE_R_INVALID_ARGUMENT:143:invalid argument
ENGINE_R_INVALID_CMD_NAME:137:invalid cmd name
ENGINE_R_INVALID_CMD_NUMBER:138:invalid cmd number
ENGINE_R_INVALID_INIT_VALUE:151:invalid init value
ENGINE_R_INVALID_STRING:150:invalid string
ENGINE_R_NOT_INITIALISED:117:not initialised
ENGINE_R_NOT_LOADED:112:not loaded
ENGINE_R_NO_CONTROL_FUNCTION:120:no control function
ENGINE_R_NO_INDEX:144:no index
ENGINE_R_NO_LOAD_FUNCTION:125:no load function
ENGINE_R_NO_REFERENCE:130:no reference
ENGINE_R_NO_SUCH_ENGINE:116:no such engine
ENGINE_R_UNIMPLEMENTED_CIPHER:146:unimplemented cipher
ENGINE_R_UNIMPLEMENTED_DIGEST:147:unimplemented digest
ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD:101:unimplemented public key method
ENGINE_R_VERSION_INCOMPATIBILITY:145:version incompatibility
EVP_R_AES_KEY_SETUP_FAILED:143:aes key setup failed
EVP_R_ARIA_KEY_SETUP_FAILED:176:aria key setup failed
EVP_R_BAD_DECRYPT:100:bad decrypt
EVP_R_BUFFER_TOO_SMALL:155:buffer too small
EVP_R_CAMELLIA_KEY_SETUP_FAILED:157:camellia key setup failed
EVP_R_CIPHER_PARAMETER_ERROR:122:cipher parameter error
EVP_R_COMMAND_NOT_SUPPORTED:147:command not supported
EVP_R_COPY_ERROR:173:copy error
EVP_R_CTRL_NOT_IMPLEMENTED:132:ctrl not implemented
EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED:133:ctrl operation not implemented
EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:138:data not multiple of block length
EVP_R_DECODE_ERROR:114:decode error
EVP_R_DIFFERENT_KEY_TYPES:101:different key types
EVP_R_DIFFERENT_PARAMETERS:153:different parameters
EVP_R_ERROR_LOADING_SECTION:165:error loading section
EVP_R_ERROR_SETTING_FIPS_MODE:166:error setting fips mode
EVP_R_EXPECTING_AN_HMAC_KEY:174:expecting an hmac key
EVP_R_EXPECTING_AN_RSA_KEY:127:expecting an rsa key
EVP_R_EXPECTING_A_DH_KEY:128:expecting a dh key
EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key
EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key
EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key
EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported
EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
EVP_R_INITIALIZATION_ERROR:134:initialization error
EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized
EVP_R_INVALID_DIGEST:152:invalid digest
EVP_R_INVALID_FIPS_MODE:168:invalid fips mode
EVP_R_INVALID_KEY:163:invalid key
EVP_R_INVALID_KEY_LENGTH:130:invalid key length
EVP_R_INVALID_OPERATION:148:invalid operation
EVP_R_KEYGEN_FAILURE:120:keygen failure
EVP_R_KEY_SETUP_FAILED:180:key setup failed
EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded
EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null
EVP_R_METHOD_NOT_SUPPORTED:144:method not supported
EVP_R_MISSING_PARAMETERS:103:missing parameters
EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length
EVP_R_NO_CIPHER_SET:131:no cipher set
EVP_R_NO_DEFAULT_DIGEST:158:no default digest
EVP_R_NO_DIGEST_SET:139:no digest set
EVP_R_NO_KEY_SET:154:no key set
EVP_R_NO_OPERATION_SET:149:no operation set
EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\
operation not supported for this keytype
EVP_R_OPERATON_NOT_INITIALIZED:151:operaton not initialized
EVP_R_PARTIALLY_OVERLAPPING:162:partially overlapping buffers
EVP_R_PBKDF2_ERROR:181:pbkdf2 error
EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\
pkey application asn1 method already registered
EVP_R_PRIVATE_KEY_DECODE_ERROR:145:private key decode error
EVP_R_PRIVATE_KEY_ENCODE_ERROR:146:private key encode error
EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa
EVP_R_UNKNOWN_CIPHER:160:unknown cipher
EVP_R_UNKNOWN_DIGEST:161:unknown digest
EVP_R_UNKNOWN_OPTION:169:unknown option
EVP_R_UNKNOWN_PBE_ALGORITHM:121:unknown pbe algorithm
EVP_R_UNSUPPORTED_ALGORITHM:156:unsupported algorithm
EVP_R_UNSUPPORTED_CIPHER:107:unsupported cipher
EVP_R_UNSUPPORTED_KEYLENGTH:123:unsupported keylength
EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION:124:\
unsupported key derivation function
EVP_R_UNSUPPORTED_KEY_SIZE:108:unsupported key size
EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS:135:unsupported number of rounds
EVP_R_UNSUPPORTED_PRF:125:unsupported prf
EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM:118:unsupported private key algorithm
EVP_R_UNSUPPORTED_SALT_TYPE:126:unsupported salt type
EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed
EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length
KDF_R_INVALID_DIGEST:100:invalid digest
KDF_R_MISSING_ITERATION_COUNT:109:missing iteration count
KDF_R_MISSING_KEY:104:missing key
KDF_R_MISSING_MESSAGE_DIGEST:105:missing message digest
KDF_R_MISSING_PARAMETER:101:missing parameter
KDF_R_MISSING_PASS:110:missing pass
KDF_R_MISSING_SALT:111:missing salt
KDF_R_MISSING_SECRET:107:missing secret
KDF_R_MISSING_SEED:106:missing seed
KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type
KDF_R_VALUE_ERROR:108:value error
KDF_R_VALUE_MISSING:102:value missing
OBJ_R_OID_EXISTS:102:oid exists
OBJ_R_UNKNOWN_NID:101:unknown nid
OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error
OCSP_R_DIGEST_ERR:102:digest err
OCSP_R_ERROR_IN_NEXTUPDATE_FIELD:122:error in nextupdate field
OCSP_R_ERROR_IN_THISUPDATE_FIELD:123:error in thisupdate field
OCSP_R_ERROR_PARSING_URL:121:error parsing url
OCSP_R_MISSING_OCSPSIGNING_USAGE:103:missing ocspsigning usage
OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE:124:nextupdate before thisupdate
OCSP_R_NOT_BASIC_RESPONSE:104:not basic response
OCSP_R_NO_CERTIFICATES_IN_CHAIN:105:no certificates in chain
OCSP_R_NO_RESPONSE_DATA:108:no response data
OCSP_R_NO_REVOKED_TIME:109:no revoked time
OCSP_R_NO_SIGNER_KEY:130:no signer key
OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:110:\
private key does not match certificate
OCSP_R_REQUEST_NOT_SIGNED:128:request not signed
OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA:111:\
response contains no revocation data
OCSP_R_ROOT_CA_NOT_TRUSTED:112:root ca not trusted
OCSP_R_SERVER_RESPONSE_ERROR:114:server response error
OCSP_R_SERVER_RESPONSE_PARSE_ERROR:115:server response parse error
OCSP_R_SIGNATURE_FAILURE:117:signature failure
OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND:118:signer certificate not found
OCSP_R_STATUS_EXPIRED:125:status expired
OCSP_R_STATUS_NOT_YET_VALID:126:status not yet valid
OCSP_R_STATUS_TOO_OLD:127:status too old
OCSP_R_UNKNOWN_MESSAGE_DIGEST:119:unknown message digest
OCSP_R_UNKNOWN_NID:120:unknown nid
OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE:129:unsupported requestorname type
OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type
OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read
OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac
OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST:121:\
fingerprint size does not match digest
OSSL_STORE_R_INVALID_SCHEME:106:invalid scheme
OSSL_STORE_R_IS_NOT_A:112:is not a
OSSL_STORE_R_LOADER_INCOMPLETE:116:loader incomplete
OSSL_STORE_R_LOADING_STARTED:117:loading started
OSSL_STORE_R_NOT_A_CERTIFICATE:100:not a certificate
OSSL_STORE_R_NOT_A_CRL:101:not a crl
OSSL_STORE_R_NOT_A_KEY:102:not a key
OSSL_STORE_R_NOT_A_NAME:103:not a name
OSSL_STORE_R_NOT_PARAMETERS:104:not parameters
OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error
OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE:108:path must be absolute
OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:119:\
search only supported for directories
OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED:109:\
ui process interrupted or cancelled
OSSL_STORE_R_UNREGISTERED_SCHEME:105:unregistered scheme
OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE:110:unsupported content type
OSSL_STORE_R_UNSUPPORTED_OPERATION:118:unsupported operation
OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE:120:unsupported search type
OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED:111:uri authority unsupported
PEM_R_BAD_BASE64_DECODE:100:bad base64 decode
PEM_R_BAD_DECRYPT:101:bad decrypt
PEM_R_BAD_END_LINE:102:bad end line
PEM_R_BAD_IV_CHARS:103:bad iv chars
PEM_R_BAD_MAGIC_NUMBER:116:bad magic number
PEM_R_BAD_PASSWORD_READ:104:bad password read
PEM_R_BAD_VERSION_NUMBER:117:bad version number
PEM_R_BIO_WRITE_FAILURE:118:bio write failure
PEM_R_CIPHER_IS_NULL:127:cipher is null
PEM_R_ERROR_CONVERTING_PRIVATE_KEY:115:error converting private key
PEM_R_EXPECTING_PRIVATE_KEY_BLOB:119:expecting private key blob
PEM_R_EXPECTING_PUBLIC_KEY_BLOB:120:expecting public key blob
PEM_R_HEADER_TOO_LONG:128:header too long
PEM_R_INCONSISTENT_HEADER:121:inconsistent header
PEM_R_KEYBLOB_HEADER_PARSE_ERROR:122:keyblob header parse error
PEM_R_KEYBLOB_TOO_SHORT:123:keyblob too short
PEM_R_MISSING_DEK_IV:129:missing dek iv
PEM_R_NOT_DEK_INFO:105:not dek info
PEM_R_NOT_ENCRYPTED:106:not encrypted
PEM_R_NOT_PROC_TYPE:107:not proc type
PEM_R_NO_START_LINE:108:no start line
PEM_R_PROBLEMS_GETTING_PASSWORD:109:problems getting password
PEM_R_PVK_DATA_TOO_SHORT:124:pvk data too short
PEM_R_PVK_TOO_SHORT:125:pvk too short
PEM_R_READ_KEY:111:read key
PEM_R_SHORT_HEADER:112:short header
PEM_R_UNEXPECTED_DEK_IV:130:unexpected dek iv
PEM_R_UNSUPPORTED_CIPHER:113:unsupported cipher
PEM_R_UNSUPPORTED_ENCRYPTION:114:unsupported encryption
PEM_R_UNSUPPORTED_KEY_COMPONENTS:126:unsupported key components
PKCS12_R_CANT_PACK_STRUCTURE:100:cant pack structure
PKCS12_R_CONTENT_TYPE_NOT_DATA:121:content type not data
PKCS12_R_DECODE_ERROR:101:decode error
PKCS12_R_ENCODE_ERROR:102:encode error
PKCS12_R_ENCRYPT_ERROR:103:encrypt error
PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE:120:error setting encrypted data type
PKCS12_R_INVALID_NULL_ARGUMENT:104:invalid null argument
PKCS12_R_INVALID_NULL_PKCS12_POINTER:105:invalid null pkcs12 pointer
PKCS12_R_IV_GEN_ERROR:106:iv gen error
PKCS12_R_KEY_GEN_ERROR:107:key gen error
PKCS12_R_MAC_ABSENT:108:mac absent
PKCS12_R_MAC_GENERATION_ERROR:109:mac generation error
PKCS12_R_MAC_SETUP_ERROR:110:mac setup error
PKCS12_R_MAC_STRING_SET_ERROR:111:mac string set error
PKCS12_R_MAC_VERIFY_FAILURE:113:mac verify failure
PKCS12_R_PARSE_ERROR:114:parse error
PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR:115:pkcs12 algor cipherinit error
PKCS12_R_PKCS12_CIPHERFINAL_ERROR:116:pkcs12 cipherfinal error
PKCS12_R_PKCS12_PBE_CRYPT_ERROR:117:pkcs12 pbe crypt error
PKCS12_R_UNKNOWN_DIGEST_ALGORITHM:118:unknown digest algorithm
PKCS12_R_UNSUPPORTED_PKCS12_MODE:119:unsupported pkcs12 mode
PKCS7_R_CERTIFICATE_VERIFY_ERROR:117:certificate verify error
PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER:144:cipher has no object identifier
PKCS7_R_CIPHER_NOT_INITIALIZED:116:cipher not initialized
PKCS7_R_CONTENT_AND_DATA_PRESENT:118:content and data present
PKCS7_R_CTRL_ERROR:152:ctrl error
PKCS7_R_DECRYPT_ERROR:119:decrypt error
PKCS7_R_DIGEST_FAILURE:101:digest failure
PKCS7_R_ENCRYPTION_CTRL_FAILURE:149:encryption ctrl failure
PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE:150:\
encryption not supported for this key type
PKCS7_R_ERROR_ADDING_RECIPIENT:120:error adding recipient
PKCS7_R_ERROR_SETTING_CIPHER:121:error setting cipher
PKCS7_R_INVALID_NULL_POINTER:143:invalid null pointer
PKCS7_R_INVALID_SIGNED_DATA_TYPE:155:invalid signed data type
PKCS7_R_NO_CONTENT:122:no content
PKCS7_R_NO_DEFAULT_DIGEST:151:no default digest
PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND:154:no matching digest type found
PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE:115:no recipient matches certificate
PKCS7_R_NO_SIGNATURES_ON_DATA:123:no signatures on data
PKCS7_R_NO_SIGNERS:142:no signers
PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE:104:\
operation not supported on this type
PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR:124:pkcs7 add signature error
PKCS7_R_PKCS7_ADD_SIGNER_ERROR:153:pkcs7 add signer error
PKCS7_R_PKCS7_DATASIGN:145:pkcs7 datasign
PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:127:\
private key does not match certificate
PKCS7_R_SIGNATURE_FAILURE:105:signature failure
PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND:128:signer certificate not found
PKCS7_R_SIGNING_CTRL_FAILURE:147:signing ctrl failure
PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE:148:\
signing not supported for this key type
PKCS7_R_SMIME_TEXT_ERROR:129:smime text error
PKCS7_R_UNABLE_TO_FIND_CERTIFICATE:106:unable to find certificate
PKCS7_R_UNABLE_TO_FIND_MEM_BIO:107:unable to find mem bio
PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST:108:unable to find message digest
PKCS7_R_UNKNOWN_DIGEST_TYPE:109:unknown digest type
PKCS7_R_UNKNOWN_OPERATION:110:unknown operation
PKCS7_R_UNSUPPORTED_CIPHER_TYPE:111:unsupported cipher type
PKCS7_R_UNSUPPORTED_CONTENT_TYPE:112:unsupported content type
PKCS7_R_WRONG_CONTENT_TYPE:113:wrong content type
PKCS7_R_WRONG_PKCS7_TYPE:114:wrong pkcs7 type
RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long
RAND_R_ALREADY_INSTANTIATED:103:already instantiated
RAND_R_ARGUMENT_OUT_OF_RANGE:105:argument out of range
RAND_R_CANNOT_OPEN_FILE:121:Cannot open file
RAND_R_DRBG_ALREADY_INITIALIZED:129:drbg already initialized
RAND_R_DRBG_NOT_INITIALISED:104:drbg not initialised
RAND_R_ENTROPY_INPUT_TOO_LONG:106:entropy input too long
RAND_R_ENTROPY_OUT_OF_RANGE:124:entropy out of range
RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED:127:error entropy pool was ignored
RAND_R_ERROR_INITIALISING_DRBG:107:error initialising drbg
RAND_R_ERROR_INSTANTIATING_DRBG:108:error instantiating drbg
RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT:109:error retrieving additional input
RAND_R_ERROR_RETRIEVING_ENTROPY:110:error retrieving entropy
RAND_R_ERROR_RETRIEVING_NONCE:111:error retrieving nonce
RAND_R_FAILED_TO_CREATE_LOCK:126:failed to create lock
RAND_R_FUNC_NOT_IMPLEMENTED:101:Function not implemented
RAND_R_FWRITE_ERROR:123:Error writing file
RAND_R_GENERATE_ERROR:112:generate error
RAND_R_INTERNAL_ERROR:113:internal error
RAND_R_IN_ERROR_STATE:114:in error state
RAND_R_NOT_A_REGULAR_FILE:122:Not a regular file
RAND_R_NOT_INSTANTIATED:115:not instantiated
RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED:128:no drbg implementation selected
RAND_R_PARENT_LOCKING_NOT_ENABLED:130:parent locking not enabled
RAND_R_PARENT_STRENGTH_TOO_WEAK:131:parent strength too weak
RAND_R_PERSONALISATION_STRING_TOO_LONG:116:personalisation string too long
RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED:133:\
prediction resistance not supported
RAND_R_PRNG_NOT_SEEDED:100:PRNG not seeded
RAND_R_RANDOM_POOL_OVERFLOW:125:random pool overflow
RAND_R_RANDOM_POOL_UNDERFLOW:134:random pool underflow
RAND_R_REQUEST_TOO_LARGE_FOR_DRBG:117:request too large for drbg
RAND_R_RESEED_ERROR:118:reseed error
RAND_R_SELFTEST_FAILURE:119:selftest failure
RAND_R_TOO_LITTLE_NONCE_REQUESTED:135:too little nonce requested
RAND_R_TOO_MUCH_NONCE_REQUESTED:136:too much nonce requested
RAND_R_UNSUPPORTED_DRBG_FLAGS:132:unsupported drbg flags
RAND_R_UNSUPPORTED_DRBG_TYPE:120:unsupported drbg type
RSA_R_ALGORITHM_MISMATCH:100:algorithm mismatch
RSA_R_BAD_E_VALUE:101:bad e value
RSA_R_BAD_FIXED_HEADER_DECRYPT:102:bad fixed header decrypt
RSA_R_BAD_PAD_BYTE_COUNT:103:bad pad byte count
RSA_R_BAD_SIGNATURE:104:bad signature
RSA_R_BLOCK_TYPE_IS_NOT_01:106:block type is not 01
RSA_R_BLOCK_TYPE_IS_NOT_02:107:block type is not 02
RSA_R_DATA_GREATER_THAN_MOD_LEN:108:data greater than mod len
RSA_R_DATA_TOO_LARGE:109:data too large
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:110:data too large for key size
RSA_R_DATA_TOO_LARGE_FOR_MODULUS:132:data too large for modulus
RSA_R_DATA_TOO_SMALL:111:data too small
RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE:122:data too small for key size
RSA_R_DIGEST_DOES_NOT_MATCH:158:digest does not match
RSA_R_DIGEST_NOT_ALLOWED:145:digest not allowed
RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY:112:digest too big for rsa key
RSA_R_DMP1_NOT_CONGRUENT_TO_D:124:dmp1 not congruent to d
RSA_R_DMQ1_NOT_CONGRUENT_TO_D:125:dmq1 not congruent to d
RSA_R_D_E_NOT_CONGRUENT_TO_1:123:d e not congruent to 1
RSA_R_FIRST_OCTET_INVALID:133:first octet invalid
RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:144:\
illegal or unsupported padding mode
RSA_R_INVALID_DIGEST:157:invalid digest
RSA_R_INVALID_DIGEST_LENGTH:143:invalid digest length
RSA_R_INVALID_HEADER:137:invalid header
RSA_R_INVALID_LABEL:160:invalid label
RSA_R_INVALID_MESSAGE_LENGTH:131:invalid message length
RSA_R_INVALID_MGF1_MD:156:invalid mgf1 md
RSA_R_INVALID_MULTI_PRIME_KEY:167:invalid multi prime key
RSA_R_INVALID_OAEP_PARAMETERS:161:invalid oaep parameters
RSA_R_INVALID_PADDING:138:invalid padding
RSA_R_INVALID_PADDING_MODE:141:invalid padding mode
RSA_R_INVALID_PSS_PARAMETERS:149:invalid pss parameters
RSA_R_INVALID_PSS_SALTLEN:146:invalid pss saltlen
RSA_R_INVALID_SALT_LENGTH:150:invalid salt length
RSA_R_INVALID_TRAILER:139:invalid trailer
RSA_R_INVALID_X931_DIGEST:142:invalid x931 digest
RSA_R_IQMP_NOT_INVERSE_OF_Q:126:iqmp not inverse of q
RSA_R_KEY_PRIME_NUM_INVALID:165:key prime num invalid
RSA_R_KEY_SIZE_TOO_SMALL:120:key size too small
RSA_R_LAST_OCTET_INVALID:134:last octet invalid
RSA_R_MGF1_DIGEST_NOT_ALLOWED:152:mgf1 digest not allowed
RSA_R_MODULUS_TOO_LARGE:105:modulus too large
RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R:168:mp coefficient not inverse of r
RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D:169:mp exponent not congruent to d
RSA_R_MP_R_NOT_PRIME:170:mp r not prime
RSA_R_NO_PUBLIC_EXPONENT:140:no public exponent
RSA_R_NULL_BEFORE_BLOCK_MISSING:113:null before block missing
RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES:172:n does not equal product of primes
RSA_R_N_DOES_NOT_EQUAL_P_Q:127:n does not equal p q
RSA_R_OAEP_DECODING_ERROR:121:oaep decoding error
RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:148:\
operation not supported for this keytype
RSA_R_PADDING_CHECK_FAILED:114:padding check failed
RSA_R_PKCS_DECODING_ERROR:159:pkcs decoding error
RSA_R_PSS_SALTLEN_TOO_SMALL:164:pss saltlen too small
RSA_R_P_NOT_PRIME:128:p not prime
RSA_R_Q_NOT_PRIME:129:q not prime
RSA_R_RSA_OPERATIONS_NOT_SUPPORTED:130:rsa operations not supported
RSA_R_SLEN_CHECK_FAILED:136:salt length check failed
RSA_R_SLEN_RECOVERY_FAILED:135:salt length recovery failed
RSA_R_SSLV3_ROLLBACK_ATTACK:115:sslv3 rollback attack
RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD:116:\
the asn1 object identifier is not known for this md
RSA_R_UNKNOWN_ALGORITHM_TYPE:117:unknown algorithm type
RSA_R_UNKNOWN_DIGEST:166:unknown digest
RSA_R_UNKNOWN_MASK_DIGEST:151:unknown mask digest
RSA_R_UNKNOWN_PADDING_TYPE:118:unknown padding type
RSA_R_UNSUPPORTED_ENCRYPTION_TYPE:162:unsupported encryption type
RSA_R_UNSUPPORTED_LABEL_SOURCE:163:unsupported label source
RSA_R_UNSUPPORTED_MASK_ALGORITHM:153:unsupported mask algorithm
RSA_R_UNSUPPORTED_MASK_PARAMETER:154:unsupported mask parameter
RSA_R_UNSUPPORTED_SIGNATURE_TYPE:155:unsupported signature type
RSA_R_VALUE_MISSING:147:value missing
RSA_R_WRONG_SIGNATURE_LENGTH:119:wrong signature length
SM2_R_ASN1_ERROR:100:asn1 error
SM2_R_BAD_SIGNATURE:101:bad signature
SM2_R_BUFFER_TOO_SMALL:107:buffer too small
SM2_R_DIST_ID_TOO_LARGE:110:dist id too large
SM2_R_ID_NOT_SET:112:id not set
SM2_R_ID_TOO_LARGE:111:id too large
SM2_R_INVALID_CURVE:108:invalid curve
SM2_R_INVALID_DIGEST:102:invalid digest
SM2_R_INVALID_DIGEST_TYPE:103:invalid digest type
SM2_R_INVALID_ENCODING:104:invalid encoding
SM2_R_INVALID_FIELD:105:invalid field
SM2_R_NO_PARAMETERS_SET:109:no parameters set
SM2_R_USER_ID_TOO_LARGE:106:user id too large
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY:291:\
application data after close notify
SSL_R_APP_DATA_IN_HANDSHAKE:100:app data in handshake
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT:272:\
attempt to reuse session in different context
SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE:143:\
at least TLS 1.0 needed in FIPS mode
SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE:158:\
at least (D)TLS 1.2 needed in Suite B mode
SSL_R_BAD_CHANGE_CIPHER_SPEC:103:bad change cipher spec
SSL_R_BAD_CIPHER:186:bad cipher
SSL_R_BAD_DATA:390:bad data
SSL_R_BAD_DATA_RETURNED_BY_CALLBACK:106:bad data returned by callback
SSL_R_BAD_DECOMPRESSION:107:bad decompression
SSL_R_BAD_DH_VALUE:102:bad dh value
SSL_R_BAD_DIGEST_LENGTH:111:bad digest length
SSL_R_BAD_EARLY_DATA:233:bad early data
SSL_R_BAD_ECC_CERT:304:bad ecc cert
SSL_R_BAD_ECPOINT:306:bad ecpoint
SSL_R_BAD_EXTENSION:110:bad extension
SSL_R_BAD_HANDSHAKE_LENGTH:332:bad handshake length
SSL_R_BAD_HANDSHAKE_STATE:236:bad handshake state
SSL_R_BAD_HELLO_REQUEST:105:bad hello request
SSL_R_BAD_HRR_VERSION:263:bad hrr version
SSL_R_BAD_KEY_SHARE:108:bad key share
SSL_R_BAD_KEY_UPDATE:122:bad key update
SSL_R_BAD_LEGACY_VERSION:292:bad legacy version
SSL_R_BAD_LENGTH:271:bad length
SSL_R_BAD_PACKET:240:bad packet
SSL_R_BAD_PACKET_LENGTH:115:bad packet length
SSL_R_BAD_PROTOCOL_VERSION_NUMBER:116:bad protocol version number
SSL_R_BAD_PSK:219:bad psk
SSL_R_BAD_PSK_IDENTITY:114:bad psk identity
SSL_R_BAD_RECORD_TYPE:443:bad record type
SSL_R_BAD_RSA_ENCRYPT:119:bad rsa encrypt
SSL_R_BAD_SIGNATURE:123:bad signature
SSL_R_BAD_SRP_A_LENGTH:347:bad srp a length
SSL_R_BAD_SRP_PARAMETERS:371:bad srp parameters
SSL_R_BAD_SRTP_MKI_VALUE:352:bad srtp mki value
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST:353:bad srtp protection profile list
SSL_R_BAD_SSL_FILETYPE:124:bad ssl filetype
SSL_R_BAD_VALUE:384:bad value
SSL_R_BAD_WRITE_RETRY:127:bad write retry
SSL_R_BINDER_DOES_NOT_VERIFY:253:binder does not verify
SSL_R_BIO_NOT_SET:128:bio not set
SSL_R_BLOCK_CIPHER_PAD_IS_WRONG:129:block cipher pad is wrong
SSL_R_BN_LIB:130:bn lib
SSL_R_CALLBACK_FAILED:234:callback failed
SSL_R_CANNOT_CHANGE_CIPHER:109:cannot change cipher
SSL_R_CA_DN_LENGTH_MISMATCH:131:ca dn length mismatch
SSL_R_CA_KEY_TOO_SMALL:397:ca key too small
SSL_R_CA_MD_TOO_WEAK:398:ca md too weak
SSL_R_CCS_RECEIVED_EARLY:133:ccs received early
SSL_R_CERTIFICATE_VERIFY_FAILED:134:certificate verify failed
SSL_R_CERT_CB_ERROR:377:cert cb error
SSL_R_CERT_LENGTH_MISMATCH:135:cert length mismatch
SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED:218:ciphersuite digest has changed
SSL_R_CIPHER_CODE_WRONG_LENGTH:137:cipher code wrong length
SSL_R_CIPHER_OR_HASH_UNAVAILABLE:138:cipher or hash unavailable
SSL_R_CLIENTHELLO_TLSEXT:226:clienthello tlsext
SSL_R_COMPRESSED_LENGTH_TOO_LONG:140:compressed length too long
SSL_R_COMPRESSION_DISABLED:343:compression disabled
SSL_R_COMPRESSION_FAILURE:141:compression failure
SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE:307:\
compression id not within private range
SSL_R_COMPRESSION_LIBRARY_ERROR:142:compression library error
SSL_R_CONNECTION_TYPE_NOT_SET:144:connection type not set
SSL_R_CONTEXT_NOT_DANE_ENABLED:167:context not dane enabled
SSL_R_COOKIE_GEN_CALLBACK_FAILURE:400:cookie gen callback failure
SSL_R_COOKIE_MISMATCH:308:cookie mismatch
SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED:206:\
custom ext handler already installed
SSL_R_DANE_ALREADY_ENABLED:172:dane already enabled
SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL:173:dane cannot override mtype full
SSL_R_DANE_NOT_ENABLED:175:dane not enabled
SSL_R_DANE_TLSA_BAD_CERTIFICATE:180:dane tlsa bad certificate
SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE:184:dane tlsa bad certificate usage
SSL_R_DANE_TLSA_BAD_DATA_LENGTH:189:dane tlsa bad data length
SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH:192:dane tlsa bad digest length
SSL_R_DANE_TLSA_BAD_MATCHING_TYPE:200:dane tlsa bad matching type
SSL_R_DANE_TLSA_BAD_PUBLIC_KEY:201:dane tlsa bad public key
SSL_R_DANE_TLSA_BAD_SELECTOR:202:dane tlsa bad selector
SSL_R_DANE_TLSA_NULL_DATA:203:dane tlsa null data
SSL_R_DATA_BETWEEN_CCS_AND_FINISHED:145:data between ccs and finished
SSL_R_DATA_LENGTH_TOO_LONG:146:data length too long
SSL_R_DECRYPTION_FAILED:147:decryption failed
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:281:\
decryption failed or bad record mac
SSL_R_DH_KEY_TOO_SMALL:394:dh key too small
SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:148:dh public value length is wrong
SSL_R_DIGEST_CHECK_FAILED:149:digest check failed
SSL_R_DTLS_MESSAGE_TOO_BIG:334:dtls message too big
SSL_R_DUPLICATE_COMPRESSION_ID:309:duplicate compression id
SSL_R_ECC_CERT_NOT_FOR_SIGNING:318:ecc cert not for signing
SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE:374:ecdh required for suiteb mode
SSL_R_EE_KEY_TOO_SMALL:399:ee key too small
SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST:354:empty srtp protection profile list
SSL_R_ENCRYPTED_LENGTH_TOO_LONG:150:encrypted length too long
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:151:error in received cipher list
SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN:204:error setting tlsa base domain
SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE:194:exceeds max fragment size
SSL_R_EXCESSIVE_MESSAGE_SIZE:152:excessive message size
SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received
SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message
SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch
SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async
SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello
SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs
SSL_R_HTTPS_PROXY_REQUEST:155:https proxy request
SSL_R_HTTP_REQUEST:156:http request
SSL_R_ILLEGAL_POINT_COMPRESSION:162:illegal point compression
SSL_R_ILLEGAL_SUITEB_DIGEST:380:illegal Suite B digest
SSL_R_INAPPROPRIATE_FALLBACK:373:inappropriate fallback
SSL_R_INCONSISTENT_COMPRESSION:340:inconsistent compression
SSL_R_INCONSISTENT_EARLY_DATA_ALPN:222:inconsistent early data alpn
SSL_R_INCONSISTENT_EARLY_DATA_SNI:231:inconsistent early data sni
SSL_R_INCONSISTENT_EXTMS:104:inconsistent extms
SSL_R_INSUFFICIENT_SECURITY:241:insufficient security
SSL_R_INVALID_ALERT:205:invalid alert
SSL_R_INVALID_CCS_MESSAGE:260:invalid ccs message
SSL_R_INVALID_CERTIFICATE_OR_ALG:238:invalid certificate or alg
SSL_R_INVALID_COMMAND:280:invalid command
SSL_R_INVALID_COMPRESSION_ALGORITHM:341:invalid compression algorithm
SSL_R_INVALID_CONFIG:283:invalid config
SSL_R_INVALID_CONFIGURATION_NAME:113:invalid configuration name
SSL_R_INVALID_CONTEXT:282:invalid context
SSL_R_INVALID_CT_VALIDATION_TYPE:212:invalid ct validation type
SSL_R_INVALID_KEY_UPDATE_TYPE:120:invalid key update type
SSL_R_INVALID_MAX_EARLY_DATA:174:invalid max early data
SSL_R_INVALID_NULL_CMD_NAME:385:invalid null cmd name
SSL_R_INVALID_SEQUENCE_NUMBER:402:invalid sequence number
SSL_R_INVALID_SERVERINFO_DATA:388:invalid serverinfo data
SSL_R_INVALID_SESSION_ID:999:invalid session id
SSL_R_INVALID_SRP_USERNAME:357:invalid srp username
SSL_R_INVALID_STATUS_RESPONSE:328:invalid status response
SSL_R_INVALID_TICKET_KEYS_LENGTH:325:invalid ticket keys length
SSL_R_LENGTH_MISMATCH:159:length mismatch
SSL_R_LENGTH_TOO_LONG:404:length too long
SSL_R_LENGTH_TOO_SHORT:160:length too short
SSL_R_LIBRARY_BUG:274:library bug
SSL_R_LIBRARY_HAS_NO_CIPHERS:161:library has no ciphers
SSL_R_MISSING_DSA_SIGNING_CERT:165:missing dsa signing cert
SSL_R_MISSING_ECDSA_SIGNING_CERT:381:missing ecdsa signing cert
SSL_R_MISSING_FATAL:256:missing fatal
SSL_R_MISSING_PARAMETERS:290:missing parameters
SSL_R_MISSING_RSA_CERTIFICATE:168:missing rsa certificate
SSL_R_MISSING_RSA_ENCRYPTING_CERT:169:missing rsa encrypting cert
SSL_R_MISSING_RSA_SIGNING_CERT:170:missing rsa signing cert
SSL_R_MISSING_SIGALGS_EXTENSION:112:missing sigalgs extension
SSL_R_MISSING_SIGNING_CERT:221:missing signing cert
SSL_R_MISSING_SRP_PARAM:358:can't find SRP server param
SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION:209:missing supported groups extension
SSL_R_MISSING_TMP_DH_KEY:171:missing tmp dh key
SSL_R_MISSING_TMP_ECDH_KEY:311:missing tmp ecdh key
SSL_R_NOT_ON_RECORD_BOUNDARY:182:not on record boundary
SSL_R_NOT_REPLACING_CERTIFICATE:289:not replacing certificate
SSL_R_NOT_SERVER:284:not server
SSL_R_NO_APPLICATION_PROTOCOL:235:no application protocol
SSL_R_NO_CERTIFICATES_RETURNED:176:no certificates returned
SSL_R_NO_CERTIFICATE_ASSIGNED:177:no certificate assigned
SSL_R_NO_CERTIFICATE_SET:179:no certificate set
SSL_R_NO_CHANGE_FOLLOWING_HRR:214:no change following hrr
SSL_R_NO_CIPHERS_AVAILABLE:181:no ciphers available
SSL_R_NO_CIPHERS_SPECIFIED:183:no ciphers specified
SSL_R_NO_CIPHER_MATCH:185:no cipher match
SSL_R_NO_CLIENT_CERT_METHOD:331:no client cert method
SSL_R_NO_COMPRESSION_SPECIFIED:187:no compression specified
SSL_R_NO_COOKIE_CALLBACK_SET:287:no cookie callback set
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER:330:\
Peer haven't sent GOST certificate, required for selected ciphersuite
SSL_R_NO_METHOD_SPECIFIED:188:no method specified
SSL_R_NO_PEM_EXTENSIONS:389:no pem extensions
SSL_R_NO_PRIVATE_KEY_ASSIGNED:190:no private key assigned
SSL_R_NO_PROTOCOLS_AVAILABLE:191:no protocols available
SSL_R_NO_RENEGOTIATION:339:no renegotiation
SSL_R_NO_REQUIRED_DIGEST:324:no required digest
SSL_R_NO_SHARED_CIPHER:193:no shared cipher
SSL_R_NO_SHARED_GROUPS:410:no shared groups
SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS:376:no shared signature algorithms
SSL_R_NO_SRTP_PROFILES:359:no srtp profiles
SSL_R_NO_SUITABLE_KEY_SHARE:101:no suitable key share
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM:118:no suitable signature algorithm
SSL_R_NO_VALID_SCTS:216:no valid scts
SSL_R_NO_VERIFY_COOKIE_CALLBACK:403:no verify cookie callback
SSL_R_NULL_SSL_CTX:195:null ssl ctx
SSL_R_NULL_SSL_METHOD_PASSED:196:null ssl method passed
SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED:197:old session cipher not returned
SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED:344:\
old session compression algorithm not returned
SSL_R_OVERFLOW_ERROR:237:overflow error
SSL_R_PACKET_LENGTH_TOO_LONG:198:packet length too long
SSL_R_PARSE_TLSEXT:227:parse tlsext
SSL_R_PATH_TOO_LONG:270:path too long
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE:199:peer did not return a certificate
SSL_R_PEM_NAME_BAD_PREFIX:391:pem name bad prefix
SSL_R_PEM_NAME_TOO_SHORT:392:pem name too short
SSL_R_PIPELINE_FAILURE:406:pipeline failure
SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR:278:post handshake auth encoding err
SSL_R_PRIVATE_KEY_MISMATCH:288:private key mismatch
SSL_R_PROTOCOL_IS_SHUTDOWN:207:protocol is shutdown
SSL_R_PSK_IDENTITY_NOT_FOUND:223:psk identity not found
SSL_R_PSK_NO_CLIENT_CB:224:psk no client cb
SSL_R_PSK_NO_SERVER_CB:225:psk no server cb
SSL_R_READ_BIO_NOT_SET:211:read bio not set
SSL_R_READ_TIMEOUT_EXPIRED:312:read timeout expired
SSL_R_RECORD_LENGTH_MISMATCH:213:record length mismatch
SSL_R_RECORD_TOO_SMALL:298:record too small
SSL_R_RENEGOTIATE_EXT_TOO_LONG:335:renegotiate ext too long
SSL_R_RENEGOTIATION_ENCODING_ERR:336:renegotiation encoding err
SSL_R_RENEGOTIATION_MISMATCH:337:renegotiation mismatch
SSL_R_REQUEST_PENDING:285:request pending
SSL_R_REQUEST_SENT:286:request sent
SSL_R_REQUIRED_CIPHER_MISSING:215:required cipher missing
SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING:342:\
required compression algorithm missing
SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING:345:scsv received when renegotiating
SSL_R_SCT_VERIFICATION_FAILED:208:sct verification failed
SSL_R_SERVERHELLO_TLSEXT:275:serverhello tlsext
SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED:277:session id context uninitialized
SSL_R_SHUTDOWN_WHILE_IN_INIT:407:shutdown while in init
SSL_R_SIGNATURE_ALGORITHMS_ERROR:360:signature algorithms error
SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE:220:\
signature for non signing certificate
SSL_R_SRP_A_CALC:361:error with the srp params
SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES:362:srtp could not allocate profiles
SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG:363:\
srtp protection profile list too long
SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE:364:srtp unknown protection profile
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH:232:\
ssl3 ext invalid max fragment length
SSL_R_SSL3_EXT_INVALID_SERVERNAME:319:ssl3 ext invalid servername
SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE:320:ssl3 ext invalid servername type
SSL_R_SSL3_SESSION_ID_TOO_LONG:300:ssl3 session id too long
SSL_R_SSL_COMMAND_SECTION_EMPTY:117:ssl command section empty
SSL_R_SSL_COMMAND_SECTION_NOT_FOUND:125:ssl command section not found
SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION:228:ssl ctx has no default ssl version
SSL_R_SSL_HANDSHAKE_FAILURE:229:ssl handshake failure
SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS:230:ssl library has no ciphers
SSL_R_SSL_NEGATIVE_LENGTH:372:ssl negative length
SSL_R_SSL_SECTION_EMPTY:126:ssl section empty
SSL_R_SSL_SECTION_NOT_FOUND:136:ssl section not found
SSL_R_SSL_SESSION_ID_CALLBACK_FAILED:301:ssl session id callback failed
SSL_R_SSL_SESSION_ID_CONFLICT:302:ssl session id conflict
SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG:273:ssl session id context too long
SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH:303:ssl session id has bad length
SSL_R_SSL_SESSION_ID_TOO_LONG:408:ssl session id too long
SSL_R_SSL_SESSION_VERSION_MISMATCH:210:ssl session version mismatch
SSL_R_STILL_IN_INIT:121:still in init
SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT:365:peer does not accept heartbeats
SSL_R_TLS_HEARTBEAT_PENDING:366:heartbeat request already pending
SSL_R_TLS_ILLEGAL_EXPORTER_LABEL:367:tls illegal exporter label
SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST:157:tls invalid ecpointformat list
SSL_R_TOO_MANY_KEY_UPDATES:132:too many key updates
SSL_R_TOO_MANY_WARN_ALERTS:409:too many warn alerts
SSL_R_TOO_MUCH_EARLY_DATA:164:too much early data
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS:314:unable to find ecdh parameters
SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS:239:\
unable to find public key parameters
SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES:242:unable to load ssl3 md5 routines
SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines
SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message
SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data
SSL_R_UNEXPECTED_MESSAGE:244:unexpected message
SSL_R_UNEXPECTED_RECORD:245:unexpected record
SSL_R_UNINITIALIZED:276:uninitialized
SSL_R_UNKNOWN_ALERT_TYPE:246:unknown alert type
SSL_R_UNKNOWN_CERTIFICATE_TYPE:247:unknown certificate type
SSL_R_UNKNOWN_CIPHER_RETURNED:248:unknown cipher returned
SSL_R_UNKNOWN_CIPHER_TYPE:249:unknown cipher type
SSL_R_UNKNOWN_CMD_NAME:386:unknown cmd name
SSL_R_UNKNOWN_COMMAND:139:unknown command
SSL_R_UNKNOWN_DIGEST:368:unknown digest
SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:250:unknown key exchange type
SSL_R_UNKNOWN_PKEY_TYPE:251:unknown pkey type
SSL_R_UNKNOWN_PROTOCOL:252:unknown protocol
SSL_R_UNKNOWN_SSL_VERSION:254:unknown ssl version
SSL_R_UNKNOWN_STATE:255:unknown state
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:338:\
unsafe legacy renegotiation disabled
SSL_R_UNSOLICITED_EXTENSION:217:unsolicited extension
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM:257:unsupported compression algorithm
SSL_R_UNSUPPORTED_ELLIPTIC_CURVE:315:unsupported elliptic curve
SSL_R_UNSUPPORTED_PROTOCOL:258:unsupported protocol
SSL_R_UNSUPPORTED_SSL_VERSION:259:unsupported ssl version
SSL_R_UNSUPPORTED_STATUS_TYPE:329:unsupported status type
SSL_R_USE_SRTP_NOT_NEGOTIATED:369:use srtp not negotiated
SSL_R_VERSION_TOO_HIGH:166:version too high
SSL_R_VERSION_TOO_LOW:396:version too low
SSL_R_WRONG_CERTIFICATE_TYPE:383:wrong certificate type
SSL_R_WRONG_CIPHER_RETURNED:261:wrong cipher returned
SSL_R_WRONG_CURVE:378:wrong curve
SSL_R_WRONG_SIGNATURE_LENGTH:264:wrong signature length
SSL_R_WRONG_SIGNATURE_SIZE:265:wrong signature size
SSL_R_WRONG_SIGNATURE_TYPE:370:wrong signature type
SSL_R_WRONG_SSL_VERSION:266:wrong ssl version
SSL_R_WRONG_VERSION_NUMBER:267:wrong version number
SSL_R_X509_LIB:268:x509 lib
SSL_R_X509_VERIFICATION_SETUP_PROBLEMS:269:x509 verification setup problems
TS_R_BAD_PKCS7_TYPE:132:bad pkcs7 type
TS_R_BAD_TYPE:133:bad type
TS_R_CANNOT_LOAD_CERT:137:cannot load certificate
TS_R_CANNOT_LOAD_KEY:138:cannot load private key
TS_R_CERTIFICATE_VERIFY_ERROR:100:certificate verify error
TS_R_COULD_NOT_SET_ENGINE:127:could not set engine
TS_R_COULD_NOT_SET_TIME:115:could not set time
TS_R_DETACHED_CONTENT:134:detached content
TS_R_ESS_ADD_SIGNING_CERT_ERROR:116:ess add signing cert error
TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR:139:ess add signing cert v2 error
TS_R_ESS_SIGNING_CERTIFICATE_ERROR:101:ess signing certificate error
TS_R_INVALID_NULL_POINTER:102:invalid null pointer
TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE:117:invalid signer certificate purpose
TS_R_MESSAGE_IMPRINT_MISMATCH:103:message imprint mismatch
TS_R_NONCE_MISMATCH:104:nonce mismatch
TS_R_NONCE_NOT_RETURNED:105:nonce not returned
TS_R_NO_CONTENT:106:no content
TS_R_NO_TIME_STAMP_TOKEN:107:no time stamp token
TS_R_PKCS7_ADD_SIGNATURE_ERROR:118:pkcs7 add signature error
TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR:119:pkcs7 add signed attr error
TS_R_PKCS7_TO_TS_TST_INFO_FAILED:129:pkcs7 to ts tst info failed
TS_R_POLICY_MISMATCH:108:policy mismatch
TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:120:\
private key does not match certificate
TS_R_RESPONSE_SETUP_ERROR:121:response setup error
TS_R_SIGNATURE_FAILURE:109:signature failure
TS_R_THERE_MUST_BE_ONE_SIGNER:110:there must be one signer
TS_R_TIME_SYSCALL_ERROR:122:time syscall error
TS_R_TOKEN_NOT_PRESENT:130:token not present
TS_R_TOKEN_PRESENT:131:token present
TS_R_TSA_NAME_MISMATCH:111:tsa name mismatch
TS_R_TSA_UNTRUSTED:112:tsa untrusted
TS_R_TST_INFO_SETUP_ERROR:123:tst info setup error
TS_R_TS_DATASIGN:124:ts datasign
TS_R_UNACCEPTABLE_POLICY:125:unacceptable policy
TS_R_UNSUPPORTED_MD_ALGORITHM:126:unsupported md algorithm
TS_R_UNSUPPORTED_VERSION:113:unsupported version
TS_R_VAR_BAD_VALUE:135:var bad value
TS_R_VAR_LOOKUP_FAILURE:136:cannot find config variable
TS_R_WRONG_CONTENT_TYPE:114:wrong content type
UI_R_COMMON_OK_AND_CANCEL_CHARACTERS:104:common ok and cancel characters
UI_R_INDEX_TOO_LARGE:102:index too large
UI_R_INDEX_TOO_SMALL:103:index too small
UI_R_NO_RESULT_BUFFER:105:no result buffer
UI_R_PROCESSING_ERROR:107:processing error
UI_R_RESULT_TOO_LARGE:100:result too large
UI_R_RESULT_TOO_SMALL:101:result too small
UI_R_SYSASSIGN_ERROR:109:sys$assign error
UI_R_SYSDASSGN_ERROR:110:sys$dassgn error
UI_R_SYSQIOW_ERROR:111:sys$qiow error
UI_R_UNKNOWN_CONTROL_COMMAND:106:unknown control command
UI_R_UNKNOWN_TTYGET_ERRNO_VALUE:108:unknown ttyget errno value
UI_R_USER_DATA_DUPLICATION_UNSUPPORTED:112:user data duplication unsupported
X509V3_R_BAD_IP_ADDRESS:118:bad ip address
X509V3_R_BAD_OBJECT:119:bad object
X509V3_R_BN_DEC2BN_ERROR:100:bn dec2bn error
X509V3_R_BN_TO_ASN1_INTEGER_ERROR:101:bn to asn1 integer error
X509V3_R_DIRNAME_ERROR:149:dirname error
X509V3_R_DISTPOINT_ALREADY_SET:160:distpoint already set
X509V3_R_DUPLICATE_ZONE_ID:133:duplicate zone id
X509V3_R_ERROR_CONVERTING_ZONE:131:error converting zone
X509V3_R_ERROR_CREATING_EXTENSION:144:error creating extension
X509V3_R_ERROR_IN_EXTENSION:128:error in extension
X509V3_R_EXPECTED_A_SECTION_NAME:137:expected a section name
X509V3_R_EXTENSION_EXISTS:145:extension exists
X509V3_R_EXTENSION_NAME_ERROR:115:extension name error
X509V3_R_EXTENSION_NOT_FOUND:102:extension not found
X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED:103:extension setting not supported
X509V3_R_EXTENSION_VALUE_ERROR:116:extension value error
X509V3_R_ILLEGAL_EMPTY_EXTENSION:151:illegal empty extension
X509V3_R_INCORRECT_POLICY_SYNTAX_TAG:152:incorrect policy syntax tag
X509V3_R_INVALID_ASNUMBER:162:invalid asnumber
X509V3_R_INVALID_ASRANGE:163:invalid asrange
X509V3_R_INVALID_BOOLEAN_STRING:104:invalid boolean string
X509V3_R_INVALID_EXTENSION_STRING:105:invalid extension string
X509V3_R_INVALID_INHERITANCE:165:invalid inheritance
X509V3_R_INVALID_IPADDRESS:166:invalid ipaddress
X509V3_R_INVALID_MULTIPLE_RDNS:161:invalid multiple rdns
X509V3_R_INVALID_NAME:106:invalid name
X509V3_R_INVALID_NULL_ARGUMENT:107:invalid null argument
X509V3_R_INVALID_NULL_NAME:108:invalid null name
X509V3_R_INVALID_NULL_VALUE:109:invalid null value
X509V3_R_INVALID_NUMBER:140:invalid number
X509V3_R_INVALID_NUMBERS:141:invalid numbers
X509V3_R_INVALID_OBJECT_IDENTIFIER:110:invalid object identifier
X509V3_R_INVALID_OPTION:138:invalid option
X509V3_R_INVALID_POLICY_IDENTIFIER:134:invalid policy identifier
X509V3_R_INVALID_PROXY_POLICY_SETTING:153:invalid proxy policy setting
X509V3_R_INVALID_PURPOSE:146:invalid purpose
X509V3_R_INVALID_SAFI:164:invalid safi
X509V3_R_INVALID_SECTION:135:invalid section
X509V3_R_INVALID_SYNTAX:143:invalid syntax
X509V3_R_ISSUER_DECODE_ERROR:126:issuer decode error
X509V3_R_MISSING_VALUE:124:missing value
X509V3_R_NEED_ORGANIZATION_AND_NUMBERS:142:need organization and numbers
X509V3_R_NO_CONFIG_DATABASE:136:no config database
X509V3_R_NO_ISSUER_CERTIFICATE:121:no issuer certificate
X509V3_R_NO_ISSUER_DETAILS:127:no issuer details
X509V3_R_NO_POLICY_IDENTIFIER:139:no policy identifier
X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED:154:\
no proxy cert policy language defined
X509V3_R_NO_PUBLIC_KEY:114:no public key
X509V3_R_NO_SUBJECT_DETAILS:125:no subject details
X509V3_R_OPERATION_NOT_DEFINED:148:operation not defined
X509V3_R_OTHERNAME_ERROR:147:othername error
X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED:155:policy language already defined
X509V3_R_POLICY_PATH_LENGTH:156:policy path length
X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED:157:\
policy path length already defined
X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY:159:\
policy when proxy language requires no policy
X509V3_R_SECTION_NOT_FOUND:150:section not found
X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS:122:unable to get issuer details
X509V3_R_UNABLE_TO_GET_ISSUER_KEYID:123:unable to get issuer keyid
X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT:111:unknown bit string argument
X509V3_R_UNKNOWN_EXTENSION:129:unknown extension
X509V3_R_UNKNOWN_EXTENSION_NAME:130:unknown extension name
X509V3_R_UNKNOWN_OPTION:120:unknown option
X509V3_R_UNSUPPORTED_OPTION:117:unsupported option
X509V3_R_UNSUPPORTED_TYPE:167:unsupported type
X509V3_R_USER_TOO_LONG:132:user too long
X509_R_AKID_MISMATCH:110:akid mismatch
X509_R_BAD_SELECTOR:133:bad selector
X509_R_BAD_X509_FILETYPE:100:bad x509 filetype
X509_R_BASE64_DECODE_ERROR:118:base64 decode error
X509_R_CANT_CHECK_DH_KEY:114:cant check dh key
X509_R_CERT_ALREADY_IN_HASH_TABLE:101:cert already in hash table
X509_R_CRL_ALREADY_DELTA:127:crl already delta
X509_R_CRL_VERIFY_FAILURE:131:crl verify failure
X509_R_IDP_MISMATCH:128:idp mismatch
X509_R_INVALID_DIRECTORY:113:invalid directory
X509_R_INVALID_FIELD_NAME:119:invalid field name
X509_R_INVALID_TRUST:123:invalid trust
X509_R_ISSUER_MISMATCH:129:issuer mismatch
X509_R_KEY_TYPE_MISMATCH:115:key type mismatch
X509_R_KEY_VALUES_MISMATCH:116:key values mismatch
X509_R_LOADING_CERT_DIR:103:loading cert dir
X509_R_LOADING_DEFAULTS:104:loading defaults
X509_R_METHOD_NOT_SUPPORTED:124:method not supported
X509_R_NAME_TOO_LONG:134:name too long
X509_R_NEWER_CRL_NOT_NEWER:132:newer crl not newer
X509_R_NO_CERTIFICATE_FOUND:135:no certificate found
X509_R_NO_CERTIFICATE_OR_CRL_FOUND:136:no certificate or crl found
X509_R_NO_CERT_SET_FOR_US_TO_VERIFY:105:no cert set for us to verify
X509_R_NO_CRL_FOUND:137:no crl found
X509_R_NO_CRL_NUMBER:130:no crl number
X509_R_PUBLIC_KEY_DECODE_ERROR:125:public key decode error
X509_R_PUBLIC_KEY_ENCODE_ERROR:126:public key encode error
X509_R_SHOULD_RETRY:106:should retry
X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN:107:unable to find parameters in chain
X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY:108:unable to get certs public key
X509_R_UNKNOWN_KEY_TYPE:117:unknown key type
X509_R_UNKNOWN_NID:109:unknown nid
X509_R_UNKNOWN_PURPOSE_ID:121:unknown purpose id
X509_R_UNKNOWN_TRUST_ID:120:unknown trust id
X509_R_UNSUPPORTED_ALGORITHM:111:unsupported algorithm
X509_R_WRONG_LOOKUP_TYPE:112:wrong lookup type
X509_R_WRONG_TYPE:122:wrong type
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index 0add393276bc..39eb4f379a99 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -1,4210 +1,4210 @@
/*
* Copyright 2001-2018 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;
}
/* Update(): Process message. */
if (!cctx->aes.ccm.len_set) {
/*-
- * In case message length was not previously set explicitely via
+ * 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;
}
/* 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_rc2.c b/crypto/evp/e_rc2.c
index 80afe316d764..aa0d14018687 100644
--- a/crypto/evp/e_rc2.c
+++ b/crypto/evp/e_rc2.c
@@ -1,189 +1,191 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 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_RC2
# include <openssl/evp.h>
# include <openssl/objects.h>
# include "internal/evp_int.h"
# include <openssl/rc2.h>
static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx);
static int rc2_magic_to_meth(int i);
static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
typedef struct {
int key_bits; /* effective key bits */
RC2_KEY ks; /* key schedule */
} EVP_RC2_KEY;
# define data(ctx) EVP_C_DATA(EVP_RC2_KEY,ctx)
IMPLEMENT_BLOCK_CIPHER(rc2, ks, RC2, EVP_RC2_KEY, NID_rc2,
8,
RC2_KEY_LENGTH, 8, 64,
EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
rc2_init_key, NULL,
rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv,
rc2_ctrl)
# define RC2_40_MAGIC 0xa0
# define RC2_64_MAGIC 0x78
# define RC2_128_MAGIC 0x3a
static const EVP_CIPHER r2_64_cbc_cipher = {
NID_rc2_64_cbc,
8, 8 /* 64 bit */ , 8,
EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
rc2_init_key,
rc2_cbc_cipher,
NULL,
sizeof(EVP_RC2_KEY),
rc2_set_asn1_type_and_iv,
rc2_get_asn1_type_and_iv,
rc2_ctrl,
NULL
};
static const EVP_CIPHER r2_40_cbc_cipher = {
NID_rc2_40_cbc,
8, 5 /* 40 bit */ , 8,
EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
rc2_init_key,
rc2_cbc_cipher,
NULL,
sizeof(EVP_RC2_KEY),
rc2_set_asn1_type_and_iv,
rc2_get_asn1_type_and_iv,
rc2_ctrl,
NULL
};
const EVP_CIPHER *EVP_rc2_64_cbc(void)
{
return &r2_64_cbc_cipher;
}
const EVP_CIPHER *EVP_rc2_40_cbc(void)
{
return &r2_40_cbc_cipher;
}
static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
RC2_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx),
key, data(ctx)->key_bits);
return 1;
}
static int rc2_meth_to_magic(EVP_CIPHER_CTX *e)
{
int i;
- EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i);
+ if (EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i) <= 0)
+ return 0;
if (i == 128)
return RC2_128_MAGIC;
else if (i == 64)
return RC2_64_MAGIC;
else if (i == 40)
return RC2_40_MAGIC;
else
return 0;
}
static int rc2_magic_to_meth(int i)
{
if (i == RC2_128_MAGIC)
return 128;
else if (i == RC2_64_MAGIC)
return 64;
else if (i == RC2_40_MAGIC)
return 40;
else {
EVPerr(EVP_F_RC2_MAGIC_TO_METH, EVP_R_UNSUPPORTED_KEY_SIZE);
return 0;
}
}
static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
{
long num = 0;
int i = 0;
int key_bits;
unsigned int l;
unsigned char iv[EVP_MAX_IV_LENGTH];
if (type != NULL) {
l = EVP_CIPHER_CTX_iv_length(c);
OPENSSL_assert(l <= sizeof(iv));
i = ASN1_TYPE_get_int_octetstring(type, &num, iv, l);
if (i != (int)l)
return -1;
key_bits = rc2_magic_to_meth((int)num);
if (!key_bits)
return -1;
if (i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1))
return -1;
- EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL);
- if (EVP_CIPHER_CTX_set_key_length(c, key_bits / 8) <= 0)
+ if (EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits,
+ NULL) <= 0
+ || EVP_CIPHER_CTX_set_key_length(c, key_bits / 8) <= 0)
return -1;
}
return i;
}
static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
{
long num;
int i = 0, j;
if (type != NULL) {
num = rc2_meth_to_magic(c);
j = EVP_CIPHER_CTX_iv_length(c);
i = ASN1_TYPE_set_int_octetstring(type, num,
(unsigned char *)EVP_CIPHER_CTX_original_iv(c),
j);
}
return i;
}
static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
switch (type) {
case EVP_CTRL_INIT:
data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8;
return 1;
case EVP_CTRL_GET_RC2_KEY_BITS:
*(int *)ptr = data(c)->key_bits;
return 1;
case EVP_CTRL_SET_RC2_KEY_BITS:
if (arg > 0) {
data(c)->key_bits = arg;
return 1;
}
return 0;
# ifdef PBE_PRF_TEST
case EVP_CTRL_PBE_PRF_NID:
*(int *)ptr = NID_hmacWithMD5;
return 1;
# endif
default:
return -1;
}
}
#endif
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 633cb8863d6d..7fbf895e0732 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -1,864 +1,864 @@
/*
* Copyright 2006-2018 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 "internal/cryptlib.h"
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#include "internal/numbers.h"
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL;
/* This array needs to be in order of NIDs */
static const EVP_PKEY_METHOD *standard_methods[] = {
#ifndef OPENSSL_NO_RSA
&rsa_pkey_meth,
#endif
#ifndef OPENSSL_NO_DH
&dh_pkey_meth,
#endif
#ifndef OPENSSL_NO_DSA
&dsa_pkey_meth,
#endif
#ifndef OPENSSL_NO_EC
&ec_pkey_meth,
#endif
&hmac_pkey_meth,
#ifndef OPENSSL_NO_CMAC
&cmac_pkey_meth,
#endif
#ifndef OPENSSL_NO_RSA
&rsa_pss_pkey_meth,
#endif
#ifndef OPENSSL_NO_DH
&dhx_pkey_meth,
#endif
#ifndef OPENSSL_NO_SCRYPT
&scrypt_pkey_meth,
#endif
&tls1_prf_pkey_meth,
#ifndef OPENSSL_NO_EC
&ecx25519_pkey_meth,
&ecx448_pkey_meth,
#endif
&hkdf_pkey_meth,
#ifndef OPENSSL_NO_POLY1305
&poly1305_pkey_meth,
#endif
#ifndef OPENSSL_NO_SIPHASH
&siphash_pkey_meth,
#endif
#ifndef OPENSSL_NO_EC
&ed25519_pkey_meth,
&ed448_pkey_meth,
#endif
#ifndef OPENSSL_NO_SM2
&sm2_pkey_meth,
#endif
};
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *,
pmeth);
static int pmeth_cmp(const EVP_PKEY_METHOD *const *a,
const EVP_PKEY_METHOD *const *b)
{
return ((*a)->pkey_id - (*b)->pkey_id);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *,
pmeth);
const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
{
EVP_PKEY_METHOD tmp;
const EVP_PKEY_METHOD *t = &tmp, **ret;
tmp.pkey_id = type;
if (app_pkey_methods) {
int idx;
idx = sk_EVP_PKEY_METHOD_find(app_pkey_methods, &tmp);
if (idx >= 0)
return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx);
}
ret = OBJ_bsearch_pmeth(&t, standard_methods,
sizeof(standard_methods) /
sizeof(EVP_PKEY_METHOD *));
if (!ret || !*ret)
return NULL;
return *ret;
}
static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
{
EVP_PKEY_CTX *ret;
const EVP_PKEY_METHOD *pmeth;
if (id == -1) {
if (pkey == NULL)
return 0;
id = pkey->type;
}
#ifndef OPENSSL_NO_ENGINE
if (e == NULL && pkey != NULL)
e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine;
/* Try to find an ENGINE which implements this method */
if (e) {
if (!ENGINE_init(e)) {
EVPerr(EVP_F_INT_CTX_NEW, ERR_R_ENGINE_LIB);
return NULL;
}
} else {
e = ENGINE_get_pkey_meth_engine(id);
}
/*
* If an ENGINE handled this method look it up. Otherwise use internal
* tables.
*/
if (e)
pmeth = ENGINE_get_pkey_meth(e, id);
else
#endif
pmeth = EVP_PKEY_meth_find(id);
if (pmeth == NULL) {
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(e);
#endif
EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(e);
#endif
EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->engine = e;
ret->pmeth = pmeth;
ret->operation = EVP_PKEY_OP_UNDEFINED;
ret->pkey = pkey;
if (pkey != NULL)
EVP_PKEY_up_ref(pkey);
if (pmeth->init) {
if (pmeth->init(ret) <= 0) {
ret->pmeth = NULL;
EVP_PKEY_CTX_free(ret);
return NULL;
}
}
return ret;
}
EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
{
EVP_PKEY_METHOD *pmeth;
pmeth = OPENSSL_zalloc(sizeof(*pmeth));
if (pmeth == NULL) {
EVPerr(EVP_F_EVP_PKEY_METH_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
pmeth->pkey_id = id;
pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
return pmeth;
}
void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
const EVP_PKEY_METHOD *meth)
{
if (ppkey_id)
*ppkey_id = meth->pkey_id;
if (pflags)
*pflags = meth->flags;
}
void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src)
{
dst->init = src->init;
dst->copy = src->copy;
dst->cleanup = src->cleanup;
dst->paramgen_init = src->paramgen_init;
dst->paramgen = src->paramgen;
dst->keygen_init = src->keygen_init;
dst->keygen = src->keygen;
dst->sign_init = src->sign_init;
dst->sign = src->sign;
dst->verify_init = src->verify_init;
dst->verify = src->verify;
dst->verify_recover_init = src->verify_recover_init;
dst->verify_recover = src->verify_recover;
dst->signctx_init = src->signctx_init;
dst->signctx = src->signctx;
dst->verifyctx_init = src->verifyctx_init;
dst->verifyctx = src->verifyctx;
dst->encrypt_init = src->encrypt_init;
dst->encrypt = src->encrypt;
dst->decrypt_init = src->decrypt_init;
dst->decrypt = src->decrypt;
dst->derive_init = src->derive_init;
dst->derive = src->derive;
dst->ctrl = src->ctrl;
dst->ctrl_str = src->ctrl_str;
dst->check = src->check;
}
void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
{
if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC))
OPENSSL_free(pmeth);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
{
return int_ctx_new(pkey, e, -1);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
{
return int_ctx_new(NULL, e, id);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx)
{
EVP_PKEY_CTX *rctx;
if (!pctx->pmeth || !pctx->pmeth->copy)
return NULL;
#ifndef OPENSSL_NO_ENGINE
/* Make sure it's safe to copy a pkey context using an ENGINE */
if (pctx->engine && !ENGINE_init(pctx->engine)) {
EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_ENGINE_LIB);
return 0;
}
#endif
rctx = OPENSSL_malloc(sizeof(*rctx));
if (rctx == NULL) {
EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_MALLOC_FAILURE);
return NULL;
}
rctx->pmeth = pctx->pmeth;
#ifndef OPENSSL_NO_ENGINE
rctx->engine = pctx->engine;
#endif
if (pctx->pkey)
EVP_PKEY_up_ref(pctx->pkey);
rctx->pkey = pctx->pkey;
if (pctx->peerkey)
EVP_PKEY_up_ref(pctx->peerkey);
rctx->peerkey = pctx->peerkey;
rctx->data = NULL;
rctx->app_data = NULL;
rctx->operation = pctx->operation;
if (pctx->pmeth->copy(rctx, pctx) > 0)
return rctx;
rctx->pmeth = NULL;
EVP_PKEY_CTX_free(rctx);
return NULL;
}
int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth)
{
if (app_pkey_methods == NULL) {
app_pkey_methods = sk_EVP_PKEY_METHOD_new(pmeth_cmp);
if (app_pkey_methods == NULL){
EVPerr(EVP_F_EVP_PKEY_METH_ADD0, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth)) {
EVPerr(EVP_F_EVP_PKEY_METH_ADD0, ERR_R_MALLOC_FAILURE);
return 0;
}
sk_EVP_PKEY_METHOD_sort(app_pkey_methods);
return 1;
}
void evp_app_cleanup_int(void)
{
if (app_pkey_methods != NULL)
sk_EVP_PKEY_METHOD_pop_free(app_pkey_methods, EVP_PKEY_meth_free);
}
int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth)
{
const EVP_PKEY_METHOD *ret;
ret = sk_EVP_PKEY_METHOD_delete_ptr(app_pkey_methods, pmeth);
return ret == NULL ? 0 : 1;
}
size_t EVP_PKEY_meth_get_count(void)
{
size_t rv = OSSL_NELEM(standard_methods);
if (app_pkey_methods)
rv += sk_EVP_PKEY_METHOD_num(app_pkey_methods);
return rv;
}
const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx)
{
if (idx < OSSL_NELEM(standard_methods))
return standard_methods[idx];
if (app_pkey_methods == NULL)
return NULL;
idx -= OSSL_NELEM(standard_methods);
if (idx >= (size_t)sk_EVP_PKEY_METHOD_num(app_pkey_methods))
return NULL;
return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx);
}
void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
{
if (ctx == NULL)
return;
if (ctx->pmeth && ctx->pmeth->cleanup)
ctx->pmeth->cleanup(ctx);
EVP_PKEY_free(ctx->pkey);
EVP_PKEY_free(ctx->peerkey);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(ctx->engine);
#endif
OPENSSL_free(ctx);
}
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, int p1, void *p2)
{
int ret;
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
return -1;
/* Skip the operation checks since this is called in a very early stage */
if (ctx->pmeth->digest_custom != NULL)
goto doit;
if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET);
return -1;
}
if ((optype != -1) && !(ctx->operation & optype)) {
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION);
return -1;
}
doit:
ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
if (ret == -2)
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, uint64_t value)
{
return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, &value);
}
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
const char *name, const char *value)
{
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (strcmp(name, "digest") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD,
value);
return ctx->pmeth->ctrl_str(ctx, name, value);
}
/* Utility functions to send a string of hex string to a ctrl */
int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str)
{
size_t len;
len = strlen(str);
if (len > INT_MAX)
return -1;
return ctx->pmeth->ctrl(ctx, cmd, len, (void *)str);
}
int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex)
{
unsigned char *bin;
long binlen;
int rv = -1;
bin = OPENSSL_hexstr2buf(hex, &binlen);
if (bin == NULL)
return 0;
if (binlen <= INT_MAX)
rv = ctx->pmeth->ctrl(ctx, cmd, binlen, bin);
OPENSSL_free(bin);
return rv;
}
/* Pass a message digest to a ctrl */
int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md)
{
const EVP_MD *m;
if (md == NULL || (m = EVP_get_digestbyname(md)) == NULL) {
EVPerr(EVP_F_EVP_PKEY_CTX_MD, EVP_R_INVALID_DIGEST);
return 0;
}
return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, 0, (void *)m);
}
int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx)
{
return ctx->operation;
}
void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen)
{
ctx->keygen_info = dat;
ctx->keygen_info_count = datlen;
}
void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data)
{
ctx->data = data;
}
void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx)
{
return ctx->data;
}
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx)
{
return ctx->pkey;
}
EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx)
{
return ctx->peerkey;
}
void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
{
ctx->app_data = data;
}
void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx)
{
return ctx->app_data;
}
void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
int (*init) (EVP_PKEY_CTX *ctx))
{
pmeth->init = init;
}
void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
int (*copy) (EVP_PKEY_CTX *dst,
EVP_PKEY_CTX *src))
{
pmeth->copy = copy;
}
void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
void (*cleanup) (EVP_PKEY_CTX *ctx))
{
pmeth->cleanup = cleanup;
}
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))
{
pmeth->paramgen_init = paramgen_init;
pmeth->paramgen = paramgen;
}
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))
{
pmeth->keygen_init = keygen_init;
pmeth->keygen = keygen;
}
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))
{
pmeth->sign_init = sign_init;
pmeth->sign = sign;
}
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))
{
pmeth->verify_init = verify_init;
pmeth->verify = verify;
}
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))
{
pmeth->verify_recover_init = verify_recover_init;
pmeth->verify_recover = verify_recover;
}
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))
{
pmeth->signctx_init = signctx_init;
pmeth->signctx = signctx;
}
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))
{
pmeth->verifyctx_init = verifyctx_init;
pmeth->verifyctx = verifyctx;
}
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))
{
pmeth->encrypt_init = encrypt_init;
pmeth->encrypt = encryptfn;
}
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))
{
pmeth->decrypt_init = decrypt_init;
pmeth->decrypt = decrypt;
}
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))
{
pmeth->derive_init = derive_init;
pmeth->derive = derive;
}
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))
{
pmeth->ctrl = ctrl;
pmeth->ctrl_str = ctrl_str;
}
void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey))
{
pmeth->check = check;
}
void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey))
{
pmeth->public_check = check;
}
void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey))
{
pmeth->param_check = check;
}
void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth,
int (*digest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx))
{
pmeth->digest_custom = digest_custom;
}
void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth,
int (**pinit) (EVP_PKEY_CTX *ctx))
{
*pinit = pmeth->init;
}
void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth,
int (**pcopy) (EVP_PKEY_CTX *dst,
EVP_PKEY_CTX *src))
{
*pcopy = pmeth->copy;
}
void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth,
void (**pcleanup) (EVP_PKEY_CTX *ctx))
{
*pcleanup = pmeth->cleanup;
}
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))
{
if (pparamgen_init)
*pparamgen_init = pmeth->paramgen_init;
if (pparamgen)
*pparamgen = pmeth->paramgen;
}
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))
{
if (pkeygen_init)
*pkeygen_init = pmeth->keygen_init;
if (pkeygen)
*pkeygen = pmeth->keygen;
}
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))
{
if (psign_init)
*psign_init = pmeth->sign_init;
if (psign)
*psign = pmeth->sign;
}
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))
{
if (pverify_init)
*pverify_init = pmeth->verify_init;
if (pverify)
*pverify = pmeth->verify;
}
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))
{
if (pverify_recover_init)
*pverify_recover_init = pmeth->verify_recover_init;
if (pverify_recover)
*pverify_recover = pmeth->verify_recover;
}
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))
{
if (psignctx_init)
*psignctx_init = pmeth->signctx_init;
if (psignctx)
*psignctx = pmeth->signctx;
}
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))
{
if (pverifyctx_init)
*pverifyctx_init = pmeth->verifyctx_init;
if (pverifyctx)
*pverifyctx = pmeth->verifyctx;
}
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))
{
if (pencrypt_init)
*pencrypt_init = pmeth->encrypt_init;
if (pencryptfn)
*pencryptfn = pmeth->encrypt;
}
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))
{
if (pdecrypt_init)
*pdecrypt_init = pmeth->decrypt_init;
if (pdecrypt)
*pdecrypt = pmeth->decrypt;
}
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))
{
if (pderive_init)
*pderive_init = pmeth->derive_init;
if (pderive)
*pderive = pmeth->derive;
}
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))
{
if (pctrl)
*pctrl = pmeth->ctrl;
if (pctrl_str)
*pctrl_str = pmeth->ctrl_str;
}
void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey))
{
- if (*pcheck)
+ if (pcheck != NULL)
*pcheck = pmeth->check;
}
void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey))
{
- if (*pcheck)
+ if (pcheck != NULL)
*pcheck = pmeth->public_check;
}
void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey))
{
- if (*pcheck)
+ if (pcheck != NULL)
*pcheck = pmeth->param_check;
}
void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth,
int (**pdigest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx))
{
if (pdigest_custom != NULL)
*pdigest_custom = pmeth->digest_custom;
}
diff --git a/crypto/getenv.c b/crypto/getenv.c
new file mode 100644
index 000000000000..7e98b645b0d1
--- /dev/null
+++ b/crypto/getenv.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2018 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 <stdlib.h>
+#include "internal/cryptlib.h"
+
+char *ossl_safe_getenv(const char *name)
+{
+#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+# if __GLIBC_PREREQ(2, 17)
+# define SECURE_GETENV
+ return secure_getenv(name);
+# endif
+#endif
+
+#ifndef SECURE_GETENV
+ if (OPENSSL_issetugid())
+ return NULL;
+ return getenv(name);
+#endif
+}
diff --git a/crypto/include/internal/ec_int.h b/crypto/include/internal/ec_int.h
index bb4b5129d001..182c39cc8056 100644
--- a/crypto/include/internal/ec_int.h
+++ b/crypto/include/internal/ec_int.h
@@ -1,45 +1,53 @@
/*
* Copyright 2018 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
*/
/* Internal EC functions for other submodules: not for application use */
#ifndef HEADER_OSSL_EC_INTERNAL_H
# define HEADER_OSSL_EC_INTERNAL_H
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_EC
# include <openssl/ec.h>
/*-
* Computes the multiplicative inverse of x in the range
* [1,EC_GROUP::order), where EC_GROUP::order is the cardinality of the
* subgroup generated by the generator G:
*
* res := x^(-1) (mod EC_GROUP::order).
*
* This function expects the following two conditions to hold:
* - the EC_GROUP order is prime, and
* - x is included in the range [1, EC_GROUP::order).
*
* This function returns 1 on success, 0 on error.
*
* If the EC_GROUP order is even, this function explicitly returns 0 as
* an error.
* In case any of the two conditions stated above is not satisfied,
* the correctness of its output is not guaranteed, even if the return
* value could still be 1 (as primality testing and a conditional modular
* reduction round on the input can be omitted by the underlying
* implementations for better SCA properties on regular input values).
*/
__owur int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
const BIGNUM *x, BN_CTX *ctx);
+/*-
+ * ECDH Key Derivation Function as defined in ANSI X9.63
+ */
+int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ const unsigned char *sinfo, size_t sinfolen,
+ const EVP_MD *md);
+
# endif /* OPENSSL_NO_EC */
#endif
diff --git a/crypto/include/internal/rand_int.h b/crypto/include/internal/rand_int.h
index d91ee4c9342c..888cab1b8f66 100644
--- a/crypto/include/internal/rand_int.h
+++ b/crypto/include/internal/rand_int.h
@@ -1,131 +1,134 @@
/*
* Copyright 2016-2018 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
*/
/*
* Licensed under the OpenSSL licenses, (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* https://www.openssl.org/source/license.html
* or in the file LICENSE in the source distribution.
*/
#ifndef HEADER_RAND_INT_H
# define HEADER_RAND_INT_H
# include <openssl/rand.h>
/* forward declaration */
typedef struct rand_pool_st RAND_POOL;
void rand_cleanup_int(void);
void rand_drbg_cleanup_int(void);
void drbg_delete_thread_state(void);
void rand_fork(void);
/* Hardware-based seeding functions. */
size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool);
size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool);
/* DRBG entropy callbacks. */
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);
void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
unsigned char *out, size_t outlen);
size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
unsigned char **pout,
int entropy, size_t min_len, size_t max_len);
void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
unsigned char *out, size_t outlen);
-size_t rand_drbg_get_additional_data(unsigned char **pout, size_t max_len);
+size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout);
-void rand_drbg_cleanup_additional_data(unsigned char *out, size_t outlen);
+void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out);
/*
* RAND_POOL functions
*/
RAND_POOL *rand_pool_new(int entropy_requested, size_t min_len, size_t max_len);
+RAND_POOL *rand_pool_attach(const unsigned char *buffer, size_t len,
+ size_t entropy);
void rand_pool_free(RAND_POOL *pool);
const unsigned char *rand_pool_buffer(RAND_POOL *pool);
unsigned char *rand_pool_detach(RAND_POOL *pool);
+void rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer);
size_t rand_pool_entropy(RAND_POOL *pool);
size_t rand_pool_length(RAND_POOL *pool);
size_t rand_pool_entropy_available(RAND_POOL *pool);
size_t rand_pool_entropy_needed(RAND_POOL *pool);
/* |entropy_factor| expresses how many bits of data contain 1 bit of entropy */
size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor);
size_t rand_pool_bytes_remaining(RAND_POOL *pool);
int rand_pool_add(RAND_POOL *pool,
const unsigned char *buffer, size_t len, size_t entropy);
unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len);
int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy);
/*
* Add random bytes to the pool to acquire requested amount of entropy
*
* This function is platform specific and tries to acquire the requested
* amount of entropy by polling platform specific entropy sources.
*
* If the function succeeds in acquiring at least |entropy_requested| bits
* of entropy, the total entropy count is returned. If it fails, it returns
* an entropy count of 0.
*/
size_t rand_pool_acquire_entropy(RAND_POOL *pool);
/*
* Add some application specific nonce data
*
* This function is platform specific and adds some application specific
* data to the nonce used for instantiating the drbg.
*
* This data currently consists of the process and thread id, and a high
* resolution timestamp. The data does not include an atomic counter,
* because that is added by the calling function rand_drbg_get_nonce().
*
* Returns 1 on success and 0 on failure.
*/
int rand_pool_add_nonce_data(RAND_POOL *pool);
/*
* Add some platform specific additional data
*
* This function is platform specific and adds some random noise to the
* additional data used for generating random bytes and for reseeding
* the drbg.
*
* Returns 1 on success and 0 on failure.
*/
int rand_pool_add_additional_data(RAND_POOL *pool);
/*
* Initialise the random pool reseeding sources.
*
* Returns 1 on success and 0 on failure.
*/
int rand_pool_init(void);
/*
* Finalise the random pool reseeding sources.
*/
void rand_pool_cleanup(void);
/*
* Control the random pool use of open file descriptors.
*/
void rand_pool_keep_random_devices_open(int keep);
#endif
diff --git a/crypto/kdf/hkdf.c b/crypto/kdf/hkdf.c
index ec6090ad6a7b..ae46fad609ac 100644
--- a/crypto/kdf/hkdf.c
+++ b/crypto/kdf/hkdf.c
@@ -1,340 +1,352 @@
/*
* Copyright 2016-2018 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 <stdlib.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include "internal/cryptlib.h"
#include "internal/evp_int.h"
#define HKDF_MAXBUF 1024
static unsigned char *HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t *prk_len);
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
typedef struct {
int mode;
const EVP_MD *md;
unsigned char *salt;
size_t salt_len;
unsigned char *key;
size_t key_len;
unsigned char info[HKDF_MAXBUF];
size_t info_len;
} HKDF_PKEY_CTX;
static int pkey_hkdf_init(EVP_PKEY_CTX *ctx)
{
HKDF_PKEY_CTX *kctx;
if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->data = kctx;
return 1;
}
static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
{
HKDF_PKEY_CTX *kctx = ctx->data;
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
OPENSSL_clear_free(kctx->key, kctx->key_len);
OPENSSL_cleanse(kctx->info, kctx->info_len);
OPENSSL_free(kctx);
}
static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
HKDF_PKEY_CTX *kctx = ctx->data;
switch (type) {
case EVP_PKEY_CTRL_HKDF_MD:
if (p2 == NULL)
return 0;
kctx->md = p2;
return 1;
case EVP_PKEY_CTRL_HKDF_MODE:
kctx->mode = p1;
return 1;
case EVP_PKEY_CTRL_HKDF_SALT:
if (p1 == 0 || p2 == NULL)
return 1;
if (p1 < 0)
return 0;
if (kctx->salt != NULL)
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
kctx->salt = OPENSSL_memdup(p2, p1);
if (kctx->salt == NULL)
return 0;
kctx->salt_len = p1;
return 1;
case EVP_PKEY_CTRL_HKDF_KEY:
if (p1 < 0)
return 0;
if (kctx->key != NULL)
OPENSSL_clear_free(kctx->key, kctx->key_len);
kctx->key = OPENSSL_memdup(p2, p1);
if (kctx->key == NULL)
return 0;
kctx->key_len = p1;
return 1;
case EVP_PKEY_CTRL_HKDF_INFO:
if (p1 == 0 || p2 == NULL)
return 1;
if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
return 0;
memcpy(kctx->info + kctx->info_len, p2, p1);
kctx->info_len += p1;
return 1;
default:
return -2;
}
}
static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value)
{
if (strcmp(type, "mode") == 0) {
int mode;
if (strcmp(value, "EXTRACT_AND_EXPAND") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND;
else if (strcmp(value, "EXTRACT_ONLY") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
else if (strcmp(value, "EXPAND_ONLY") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
else
return 0;
return EVP_PKEY_CTX_hkdf_mode(ctx, mode);
}
if (strcmp(type, "md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_MD, value);
if (strcmp(type, "salt") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
if (strcmp(type, "hexsalt") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
if (strcmp(type, "key") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
if (strcmp(type, "hexkey") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
if (strcmp(type, "info") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
if (strcmp(type, "hexinfo") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
return -2;
}
+static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
+{
+ HKDF_PKEY_CTX *kctx = ctx->data;
+
+ OPENSSL_clear_free(kctx->key, kctx->key_len);
+ OPENSSL_clear_free(kctx->salt, kctx->salt_len);
+ OPENSSL_cleanse(kctx->info, kctx->info_len);
+ memset(kctx, 0, sizeof(*kctx));
+
+ return 1;
+}
+
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
{
HKDF_PKEY_CTX *kctx = ctx->data;
if (kctx->md == NULL) {
KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
return 0;
}
if (kctx->key == NULL) {
KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
return 0;
}
switch (kctx->mode) {
case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
kctx->key_len, kctx->info, kctx->info_len, key,
*keylen) != NULL;
case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
if (key == NULL) {
*keylen = EVP_MD_size(kctx->md);
return 1;
}
return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
kctx->key_len, key, keylen) != NULL;
case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
kctx->info_len, key, *keylen) != NULL;
default:
return 0;
}
}
const EVP_PKEY_METHOD hkdf_pkey_meth = {
EVP_PKEY_HKDF,
0,
pkey_hkdf_init,
0,
pkey_hkdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
- 0,
+ pkey_hkdf_derive_init,
pkey_hkdf_derive,
pkey_hkdf_ctrl,
pkey_hkdf_ctrl_str
};
static unsigned char *HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
{
unsigned char prk[EVP_MAX_MD_SIZE];
unsigned char *ret;
size_t prk_len;
if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
return NULL;
ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
OPENSSL_cleanse(prk, sizeof(prk));
return ret;
}
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t *prk_len)
{
unsigned int tmp_len;
if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
return NULL;
*prk_len = tmp_len;
return prk;
}
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
{
HMAC_CTX *hmac;
unsigned char *ret = NULL;
unsigned int i;
unsigned char prev[EVP_MAX_MD_SIZE];
size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
size_t n = okm_len / dig_len;
if (okm_len % dig_len)
n++;
if (n > 255 || okm == NULL)
return NULL;
if ((hmac = HMAC_CTX_new()) == NULL)
return NULL;
if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
goto err;
for (i = 1; i <= n; i++) {
size_t copy_len;
const unsigned char ctr = i;
if (i > 1) {
if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
goto err;
if (!HMAC_Update(hmac, prev, dig_len))
goto err;
}
if (!HMAC_Update(hmac, info, info_len))
goto err;
if (!HMAC_Update(hmac, &ctr, 1))
goto err;
if (!HMAC_Final(hmac, prev, NULL))
goto err;
copy_len = (done_len + dig_len > okm_len) ?
okm_len - done_len :
dig_len;
memcpy(okm + done_len, prev, copy_len);
done_len += copy_len;
}
ret = okm;
err:
OPENSSL_cleanse(prev, sizeof(prev));
HMAC_CTX_free(hmac);
return ret;
}
diff --git a/crypto/mem_sec.c b/crypto/mem_sec.c
index c4190bed3348..9e0f6702f406 100644
--- a/crypto/mem_sec.c
+++ b/crypto/mem_sec.c
@@ -1,650 +1,646 @@
/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2004-2014, Akamai Technologies. 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
*/
/*
* This file is in two halves. The first half implements the public API
* to be used by external consumers, and to be used by OpenSSL to store
* data in a "secure arena." The second half implements the secure arena.
* For details on that implementation, see below (look for uppercase
* "SECURE HEAP IMPLEMENTATION").
*/
#include "e_os.h"
#include <openssl/crypto.h>
#include <string.h>
-/* e_os.h includes unistd.h, which 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 IMPLEMENTED
+/* e_os.h defines OPENSSL_SECURE_MEMORY if secure memory can be implemented */
+#ifdef OPENSSL_SECURE_MEMORY
# include <stdlib.h>
# include <assert.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/mman.h>
# if defined(OPENSSL_SYS_LINUX)
# include <sys/syscall.h>
# if defined(SYS_mlock2)
# include <linux/mman.h>
# include <errno.h>
# endif
# endif
# include <sys/param.h>
# include <sys/stat.h>
# include <fcntl.h>
#endif
#define CLEAR(p, s) OPENSSL_cleanse(p, s)
#ifndef PAGE_SIZE
# define PAGE_SIZE 4096
#endif
#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
# define MAP_ANON MAP_ANONYMOUS
#endif
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
static size_t secure_mem_used;
static int secure_mem_initialized;
static CRYPTO_RWLOCK *sec_malloc_lock = NULL;
/*
* These are the functions that must be implemented by a secure heap (sh).
*/
static int sh_init(size_t size, int minsize);
static void *sh_malloc(size_t size);
static void sh_free(void *ptr);
static void sh_done(void);
static size_t sh_actual_size(char *ptr);
static int sh_allocated(const char *ptr);
#endif
int CRYPTO_secure_malloc_init(size_t size, int minsize)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
int ret = 0;
if (!secure_mem_initialized) {
sec_malloc_lock = CRYPTO_THREAD_lock_new();
if (sec_malloc_lock == NULL)
return 0;
if ((ret = sh_init(size, minsize)) != 0) {
secure_mem_initialized = 1;
} else {
CRYPTO_THREAD_lock_free(sec_malloc_lock);
sec_malloc_lock = NULL;
}
}
return ret;
#else
return 0;
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
}
int CRYPTO_secure_malloc_done(void)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
if (secure_mem_used == 0) {
sh_done();
secure_mem_initialized = 0;
CRYPTO_THREAD_lock_free(sec_malloc_lock);
sec_malloc_lock = NULL;
return 1;
}
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
return 0;
}
int CRYPTO_secure_malloc_initialized(void)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
return secure_mem_initialized;
#else
return 0;
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
}
void *CRYPTO_secure_malloc(size_t num, const char *file, int line)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
void *ret;
size_t actual_size;
if (!secure_mem_initialized) {
return CRYPTO_malloc(num, file, line);
}
CRYPTO_THREAD_write_lock(sec_malloc_lock);
ret = sh_malloc(num);
actual_size = ret ? sh_actual_size(ret) : 0;
secure_mem_used += actual_size;
CRYPTO_THREAD_unlock(sec_malloc_lock);
return ret;
#else
return CRYPTO_malloc(num, file, line);
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
}
void *CRYPTO_secure_zalloc(size_t num, const char *file, int line)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
if (secure_mem_initialized)
/* CRYPTO_secure_malloc() zeroes allocations when it is implemented */
return CRYPTO_secure_malloc(num, file, line);
#endif
return CRYPTO_zalloc(num, file, line);
}
void CRYPTO_secure_free(void *ptr, const char *file, int line)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
size_t actual_size;
if (ptr == NULL)
return;
if (!CRYPTO_secure_allocated(ptr)) {
CRYPTO_free(ptr, file, line);
return;
}
CRYPTO_THREAD_write_lock(sec_malloc_lock);
actual_size = sh_actual_size(ptr);
CLEAR(ptr, actual_size);
secure_mem_used -= actual_size;
sh_free(ptr);
CRYPTO_THREAD_unlock(sec_malloc_lock);
#else
CRYPTO_free(ptr, file, line);
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
}
void CRYPTO_secure_clear_free(void *ptr, size_t num,
const char *file, int line)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
size_t actual_size;
if (ptr == NULL)
return;
if (!CRYPTO_secure_allocated(ptr)) {
OPENSSL_cleanse(ptr, num);
CRYPTO_free(ptr, file, line);
return;
}
CRYPTO_THREAD_write_lock(sec_malloc_lock);
actual_size = sh_actual_size(ptr);
CLEAR(ptr, actual_size);
secure_mem_used -= actual_size;
sh_free(ptr);
CRYPTO_THREAD_unlock(sec_malloc_lock);
#else
if (ptr == NULL)
return;
OPENSSL_cleanse(ptr, num);
CRYPTO_free(ptr, file, line);
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
}
int CRYPTO_secure_allocated(const void *ptr)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
int ret;
if (!secure_mem_initialized)
return 0;
CRYPTO_THREAD_write_lock(sec_malloc_lock);
ret = sh_allocated(ptr);
CRYPTO_THREAD_unlock(sec_malloc_lock);
return ret;
#else
return 0;
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
}
size_t CRYPTO_secure_used(void)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
return secure_mem_used;
#else
return 0;
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
}
size_t CRYPTO_secure_actual_size(void *ptr)
{
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
size_t actual_size;
CRYPTO_THREAD_write_lock(sec_malloc_lock);
actual_size = sh_actual_size(ptr);
CRYPTO_THREAD_unlock(sec_malloc_lock);
return actual_size;
#else
return 0;
#endif
}
/* END OF PAGE ...
... START OF PAGE */
/*
* SECURE HEAP IMPLEMENTATION
*/
-#ifdef IMPLEMENTED
+#ifdef OPENSSL_SECURE_MEMORY
/*
* The implementation provided here uses a fixed-sized mmap() heap,
* which is locked into memory, not written to core files, and protected
* on either side by an unmapped page, which will catch pointer overruns
* (or underruns) and an attempt to read data out of the secure heap.
* Free'd memory is zero'd or otherwise cleansed.
*
* This is a pretty standard buddy allocator. We keep areas in a multiple
* of "sh.minsize" units. The freelist and bitmaps are kept separately,
* so all (and only) data is kept in the mmap'd heap.
*
* This code assumes eight-bit bytes. The numbers 3 and 7 are all over the
* place.
*/
#define ONE ((size_t)1)
# define TESTBIT(t, b) (t[(b) >> 3] & (ONE << ((b) & 7)))
# define SETBIT(t, b) (t[(b) >> 3] |= (ONE << ((b) & 7)))
# define CLEARBIT(t, b) (t[(b) >> 3] &= (0xFF & ~(ONE << ((b) & 7))))
#define WITHIN_ARENA(p) \
((char*)(p) >= sh.arena && (char*)(p) < &sh.arena[sh.arena_size])
#define WITHIN_FREELIST(p) \
((char*)(p) >= (char*)sh.freelist && (char*)(p) < (char*)&sh.freelist[sh.freelist_size])
typedef struct sh_list_st
{
struct sh_list_st *next;
struct sh_list_st **p_next;
} SH_LIST;
typedef struct sh_st
{
char* map_result;
size_t map_size;
char *arena;
size_t arena_size;
char **freelist;
ossl_ssize_t freelist_size;
size_t minsize;
unsigned char *bittable;
unsigned char *bitmalloc;
size_t bittable_size; /* size in bits */
} SH;
static SH sh;
static size_t sh_getlist(char *ptr)
{
ossl_ssize_t list = sh.freelist_size - 1;
size_t bit = (sh.arena_size + ptr - sh.arena) / sh.minsize;
for (; bit; bit >>= 1, list--) {
if (TESTBIT(sh.bittable, bit))
break;
OPENSSL_assert((bit & 1) == 0);
}
return list;
}
static int sh_testbit(char *ptr, int list, unsigned char *table)
{
size_t bit;
OPENSSL_assert(list >= 0 && list < sh.freelist_size);
OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
return TESTBIT(table, bit);
}
static void sh_clearbit(char *ptr, int list, unsigned char *table)
{
size_t bit;
OPENSSL_assert(list >= 0 && list < sh.freelist_size);
OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
OPENSSL_assert(TESTBIT(table, bit));
CLEARBIT(table, bit);
}
static void sh_setbit(char *ptr, int list, unsigned char *table)
{
size_t bit;
OPENSSL_assert(list >= 0 && list < sh.freelist_size);
OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
OPENSSL_assert(!TESTBIT(table, bit));
SETBIT(table, bit);
}
static void sh_add_to_list(char **list, char *ptr)
{
SH_LIST *temp;
OPENSSL_assert(WITHIN_FREELIST(list));
OPENSSL_assert(WITHIN_ARENA(ptr));
temp = (SH_LIST *)ptr;
temp->next = *(SH_LIST **)list;
OPENSSL_assert(temp->next == NULL || WITHIN_ARENA(temp->next));
temp->p_next = (SH_LIST **)list;
if (temp->next != NULL) {
OPENSSL_assert((char **)temp->next->p_next == list);
temp->next->p_next = &(temp->next);
}
*list = ptr;
}
static void sh_remove_from_list(char *ptr)
{
SH_LIST *temp, *temp2;
temp = (SH_LIST *)ptr;
if (temp->next != NULL)
temp->next->p_next = temp->p_next;
*temp->p_next = temp->next;
if (temp->next == NULL)
return;
temp2 = temp->next;
OPENSSL_assert(WITHIN_FREELIST(temp2->p_next) || WITHIN_ARENA(temp2->p_next));
}
static int sh_init(size_t size, int minsize)
{
int ret;
size_t i;
size_t pgsize;
size_t aligned;
memset(&sh, 0, sizeof(sh));
/* make sure size and minsize are powers of 2 */
OPENSSL_assert(size > 0);
OPENSSL_assert((size & (size - 1)) == 0);
OPENSSL_assert(minsize > 0);
OPENSSL_assert((minsize & (minsize - 1)) == 0);
if (size <= 0 || (size & (size - 1)) != 0)
goto err;
if (minsize <= 0 || (minsize & (minsize - 1)) != 0)
goto err;
while (minsize < (int)sizeof(SH_LIST))
minsize *= 2;
sh.arena_size = size;
sh.minsize = minsize;
sh.bittable_size = (sh.arena_size / sh.minsize) * 2;
/* Prevent allocations of size 0 later on */
if (sh.bittable_size >> 3 == 0)
goto err;
sh.freelist_size = -1;
for (i = sh.bittable_size; i; i >>= 1)
sh.freelist_size++;
sh.freelist = OPENSSL_zalloc(sh.freelist_size * sizeof(char *));
OPENSSL_assert(sh.freelist != NULL);
if (sh.freelist == NULL)
goto err;
sh.bittable = OPENSSL_zalloc(sh.bittable_size >> 3);
OPENSSL_assert(sh.bittable != NULL);
if (sh.bittable == NULL)
goto err;
sh.bitmalloc = OPENSSL_zalloc(sh.bittable_size >> 3);
OPENSSL_assert(sh.bitmalloc != NULL);
if (sh.bitmalloc == NULL)
goto err;
/* Allocate space for heap, and two extra pages as guards */
#if defined(_SC_PAGE_SIZE) || defined (_SC_PAGESIZE)
{
# if defined(_SC_PAGE_SIZE)
long tmppgsize = sysconf(_SC_PAGE_SIZE);
# else
long tmppgsize = sysconf(_SC_PAGESIZE);
# endif
if (tmppgsize < 1)
pgsize = PAGE_SIZE;
else
pgsize = (size_t)tmppgsize;
}
#else
pgsize = PAGE_SIZE;
#endif
sh.map_size = pgsize + sh.arena_size + pgsize;
if (1) {
#ifdef MAP_ANON
sh.map_result = mmap(NULL, sh.map_size,
PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
} else {
#endif
int fd;
sh.map_result = MAP_FAILED;
if ((fd = open("/dev/zero", O_RDWR)) >= 0) {
sh.map_result = mmap(NULL, sh.map_size,
PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
close(fd);
}
}
if (sh.map_result == MAP_FAILED)
goto err;
sh.arena = (char *)(sh.map_result + pgsize);
sh_setbit(sh.arena, 0, sh.bittable);
sh_add_to_list(&sh.freelist[0], sh.arena);
/* Now try to add guard pages and lock into memory. */
ret = 1;
/* Starting guard is already aligned from mmap. */
if (mprotect(sh.map_result, pgsize, PROT_NONE) < 0)
ret = 2;
/* Ending guard page - need to round up to page boundary */
aligned = (pgsize + sh.arena_size + (pgsize - 1)) & ~(pgsize - 1);
if (mprotect(sh.map_result + aligned, pgsize, PROT_NONE) < 0)
ret = 2;
#if defined(OPENSSL_SYS_LINUX) && defined(MLOCK_ONFAULT) && defined(SYS_mlock2)
if (syscall(SYS_mlock2, sh.arena, sh.arena_size, MLOCK_ONFAULT) < 0) {
if (errno == ENOSYS) {
if (mlock(sh.arena, sh.arena_size) < 0)
ret = 2;
} else {
ret = 2;
}
}
#else
if (mlock(sh.arena, sh.arena_size) < 0)
ret = 2;
#endif
#ifdef MADV_DONTDUMP
if (madvise(sh.arena, sh.arena_size, MADV_DONTDUMP) < 0)
ret = 2;
#endif
return ret;
err:
sh_done();
return 0;
}
static void sh_done(void)
{
OPENSSL_free(sh.freelist);
OPENSSL_free(sh.bittable);
OPENSSL_free(sh.bitmalloc);
if (sh.map_result != NULL && sh.map_size)
munmap(sh.map_result, sh.map_size);
memset(&sh, 0, sizeof(sh));
}
static int sh_allocated(const char *ptr)
{
return WITHIN_ARENA(ptr) ? 1 : 0;
}
static char *sh_find_my_buddy(char *ptr, int list)
{
size_t bit;
char *chunk = NULL;
bit = (ONE << list) + (ptr - sh.arena) / (sh.arena_size >> list);
bit ^= 1;
if (TESTBIT(sh.bittable, bit) && !TESTBIT(sh.bitmalloc, bit))
chunk = sh.arena + ((bit & ((ONE << list) - 1)) * (sh.arena_size >> list));
return chunk;
}
static void *sh_malloc(size_t size)
{
ossl_ssize_t list, slist;
size_t i;
char *chunk;
if (size > sh.arena_size)
return NULL;
list = sh.freelist_size - 1;
for (i = sh.minsize; i < size; i <<= 1)
list--;
if (list < 0)
return NULL;
/* try to find a larger entry to split */
for (slist = list; slist >= 0; slist--)
if (sh.freelist[slist] != NULL)
break;
if (slist < 0)
return NULL;
/* split larger entry */
while (slist != list) {
char *temp = sh.freelist[slist];
/* remove from bigger list */
OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
sh_clearbit(temp, slist, sh.bittable);
sh_remove_from_list(temp);
OPENSSL_assert(temp != sh.freelist[slist]);
/* done with bigger list */
slist++;
/* add to smaller list */
OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
sh_setbit(temp, slist, sh.bittable);
sh_add_to_list(&sh.freelist[slist], temp);
OPENSSL_assert(sh.freelist[slist] == temp);
/* split in 2 */
temp += sh.arena_size >> slist;
OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
sh_setbit(temp, slist, sh.bittable);
sh_add_to_list(&sh.freelist[slist], temp);
OPENSSL_assert(sh.freelist[slist] == temp);
OPENSSL_assert(temp-(sh.arena_size >> slist) == sh_find_my_buddy(temp, slist));
}
/* peel off memory to hand back */
chunk = sh.freelist[list];
OPENSSL_assert(sh_testbit(chunk, list, sh.bittable));
sh_setbit(chunk, list, sh.bitmalloc);
sh_remove_from_list(chunk);
OPENSSL_assert(WITHIN_ARENA(chunk));
/* zero the free list header as a precaution against information leakage */
memset(chunk, 0, sizeof(SH_LIST));
return chunk;
}
static void sh_free(void *ptr)
{
size_t list;
void *buddy;
if (ptr == NULL)
return;
OPENSSL_assert(WITHIN_ARENA(ptr));
if (!WITHIN_ARENA(ptr))
return;
list = sh_getlist(ptr);
OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
sh_clearbit(ptr, list, sh.bitmalloc);
sh_add_to_list(&sh.freelist[list], ptr);
/* Try to coalesce two adjacent free areas. */
while ((buddy = sh_find_my_buddy(ptr, list)) != NULL) {
OPENSSL_assert(ptr == sh_find_my_buddy(buddy, list));
OPENSSL_assert(ptr != NULL);
OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
sh_clearbit(ptr, list, sh.bittable);
sh_remove_from_list(ptr);
OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
sh_clearbit(buddy, list, sh.bittable);
sh_remove_from_list(buddy);
list--;
/* Zero the higher addressed block's free list pointers */
memset(ptr > buddy ? ptr : buddy, 0, sizeof(SH_LIST));
if (ptr > buddy)
ptr = buddy;
OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
sh_setbit(ptr, list, sh.bittable);
sh_add_to_list(&sh.freelist[list], ptr);
OPENSSL_assert(sh.freelist[list] == ptr);
}
}
static size_t sh_actual_size(char *ptr)
{
int list;
OPENSSL_assert(WITHIN_ARENA(ptr));
if (!WITHIN_ARENA(ptr))
return 0;
list = sh_getlist(ptr);
OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
return sh.arena_size / (ONE << list);
}
-#endif /* IMPLEMENTED */
+#endif /* OPENSSL_SECURE_MEMORY */
diff --git a/crypto/o_fopen.c b/crypto/o_fopen.c
index f08f99b414f5..7d51ad725426 100644
--- a/crypto/o_fopen.c
+++ b/crypto/o_fopen.c
@@ -1,128 +1,126 @@
/*
* Copyright 2016-2018 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
*/
# if defined(__linux) || defined(__sun) || defined(__hpux)
/*
* Following definition aliases fopen to fopen64 on above mentioned
* platforms. This makes it possible to open and sequentially access files
* larger than 2GB from 32-bit application. It does not allow to traverse
* them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit
* platform permits that, not with fseek/ftell. Not to mention that breaking
* 2GB limit for seeking would require surgery to *our* API. But sequential
* access suffices for practical cases when you can run into large files,
* such as fingerprinting, so we can let API alone. For reference, the list
* of 32-bit platforms which allow for sequential access of large files
* without extra "magic" comprise *BSD, Darwin, IRIX...
*/
# ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
# endif
# endif
+#include "e_os.h"
#include "internal/cryptlib.h"
#if !defined(OPENSSL_NO_STDIO)
# include <stdio.h>
-# ifdef _WIN32
-# include <windows.h>
-# endif
# ifdef __DJGPP__
# include <unistd.h>
# endif
FILE *openssl_fopen(const char *filename, const char *mode)
{
FILE *file = NULL;
# if defined(_WIN32) && defined(CP_UTF8)
int sz, len_0 = (int)strlen(filename) + 1;
DWORD flags;
/*
* Basically there are three cases to cover: a) filename is
* pure ASCII string; b) actual UTF-8 encoded string and
* c) locale-ized string, i.e. one containing 8-bit
* characters that are meaningful in current system locale.
* If filename is pure ASCII or real UTF-8 encoded string,
* MultiByteToWideChar succeeds and _wfopen works. If
* filename is locale-ized string, chances are that
* MultiByteToWideChar fails reporting
* ERROR_NO_UNICODE_TRANSLATION, in which case we fall
* back to fopen...
*/
if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS),
filename, len_0, NULL, 0)) > 0 ||
(GetLastError() == ERROR_INVALID_FLAGS &&
(sz = MultiByteToWideChar(CP_UTF8, (flags = 0),
filename, len_0, NULL, 0)) > 0)
) {
WCHAR wmode[8];
WCHAR *wfilename = _alloca(sz * sizeof(WCHAR));
if (MultiByteToWideChar(CP_UTF8, flags,
filename, len_0, wfilename, sz) &&
MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1,
wmode, OSSL_NELEM(wmode)) &&
(file = _wfopen(wfilename, wmode)) == NULL &&
(errno == ENOENT || errno == EBADF)
) {
/*
* UTF-8 decode succeeded, but no file, filename
* could still have been locale-ized...
*/
file = fopen(filename, mode);
}
} else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
file = fopen(filename, mode);
}
# elif defined(__DJGPP__)
{
char *newname = NULL;
if (pathconf(filename, _PC_NAME_MAX) <= 12) { /* 8.3 file system? */
char *iterator;
char lastchar;
if ((newname = OPENSSL_malloc(strlen(filename) + 1)) == NULL) {
CRYPTOerr(CRYPTO_F_OPENSSL_FOPEN, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (iterator = newname, lastchar = '\0';
*filename; filename++, iterator++) {
if (lastchar == '/' && filename[0] == '.'
&& filename[1] != '.' && filename[1] != '/') {
/* Leading dots are not permitted in plain DOS. */
*iterator = '_';
} else {
*iterator = *filename;
}
lastchar = *filename;
}
*iterator = '\0';
filename = newname;
}
file = fopen(filename, mode);
OPENSSL_free(newname);
}
# else
file = fopen(filename, mode);
# endif
return file;
}
#else
void *openssl_fopen(const char *filename, const char *mode)
{
return NULL;
}
#endif
diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c
index 88d1d66324e3..0cbbed364a21 100644
--- a/crypto/pkcs12/p12_mutl.c
+++ b/crypto/pkcs12/p12_mutl.c
@@ -1,246 +1,246 @@
/*
* Copyright 1999-2018 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/crypto.h>
-# include <openssl/hmac.h>
-# include <openssl/rand.h>
-# include <openssl/pkcs12.h>
-# include "p12_lcl.h"
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/crypto.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+#include <openssl/pkcs12.h>
+#include "p12_lcl.h"
int PKCS12_mac_present(const PKCS12 *p12)
{
return p12->mac ? 1 : 0;
}
void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac,
const X509_ALGOR **pmacalg,
const ASN1_OCTET_STRING **psalt,
const ASN1_INTEGER **piter,
const PKCS12 *p12)
{
if (p12->mac) {
X509_SIG_get0(p12->mac->dinfo, pmacalg, pmac);
if (psalt)
*psalt = p12->mac->salt;
if (piter)
*piter = p12->mac->iter;
} else {
if (pmac)
*pmac = NULL;
if (pmacalg)
*pmacalg = NULL;
if (psalt)
*psalt = NULL;
if (piter)
*piter = NULL;
}
}
-# define TK26_MAC_KEY_LEN 32
+#define TK26_MAC_KEY_LEN 32
static int pkcs12_gen_gost_mac_key(const char *pass, int passlen,
const unsigned char *salt, int saltlen,
int iter, int keylen, unsigned char *key,
const EVP_MD *digest)
{
unsigned char out[96];
if (keylen != TK26_MAC_KEY_LEN) {
return 0;
}
if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter,
digest, sizeof(out), out)) {
return 0;
}
memcpy(key, out + sizeof(out) - TK26_MAC_KEY_LEN, TK26_MAC_KEY_LEN);
OPENSSL_cleanse(out, sizeof(out));
return 1;
}
/* Generate a MAC */
static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
unsigned char *mac, unsigned int *maclen,
int (*pkcs12_key_gen)(const char *pass, int passlen,
unsigned char *salt, int slen,
int id, int iter, int n,
unsigned char *out,
const EVP_MD *md_type))
{
int ret = 0;
const EVP_MD *md_type;
HMAC_CTX *hmac = NULL;
unsigned char key[EVP_MAX_MD_SIZE], *salt;
int saltlen, iter;
int md_size = 0;
int md_type_nid;
const X509_ALGOR *macalg;
const ASN1_OBJECT *macoid;
if (pkcs12_key_gen == NULL)
pkcs12_key_gen = PKCS12_key_gen_utf8;
if (!PKCS7_type_is_data(p12->authsafes)) {
PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_CONTENT_TYPE_NOT_DATA);
return 0;
}
salt = p12->mac->salt->data;
saltlen = p12->mac->salt->length;
if (!p12->mac->iter)
iter = 1;
else
iter = ASN1_INTEGER_get(p12->mac->iter);
X509_SIG_get0(p12->mac->dinfo, &macalg, NULL);
X509_ALGOR_get0(&macoid, NULL, NULL, macalg);
if ((md_type = EVP_get_digestbyobj(macoid)) == NULL) {
PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
return 0;
}
md_size = EVP_MD_size(md_type);
md_type_nid = EVP_MD_type(md_type);
if (md_size < 0)
return 0;
if ((md_type_nid == NID_id_GostR3411_94
|| md_type_nid == NID_id_GostR3411_2012_256
|| md_type_nid == NID_id_GostR3411_2012_512)
- && !getenv("LEGACY_GOST_PKCS12")) {
+ && ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) {
md_size = TK26_MAC_KEY_LEN;
if (!pkcs12_gen_gost_mac_key(pass, passlen, salt, saltlen, iter,
md_size, key, md_type)) {
PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR);
goto err;
}
} else
if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
iter, md_size, key, md_type)) {
PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR);
goto err;
}
if ((hmac = HMAC_CTX_new()) == NULL
|| !HMAC_Init_ex(hmac, key, md_size, md_type, NULL)
|| !HMAC_Update(hmac, p12->authsafes->d.data->data,
p12->authsafes->d.data->length)
|| !HMAC_Final(hmac, mac, maclen)) {
goto err;
}
ret = 1;
err:
OPENSSL_cleanse(key, sizeof(key));
HMAC_CTX_free(hmac);
return ret;
}
int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
unsigned char *mac, unsigned int *maclen)
{
return pkcs12_gen_mac(p12, pass, passlen, mac, maclen, NULL);
}
/* Verify the mac */
int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
{
unsigned char mac[EVP_MAX_MD_SIZE];
unsigned int maclen;
const ASN1_OCTET_STRING *macoct;
if (p12->mac == NULL) {
PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_ABSENT);
return 0;
}
if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen,
PKCS12_key_gen_utf8)) {
PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_GENERATION_ERROR);
return 0;
}
X509_SIG_get0(p12->mac->dinfo, NULL, &macoct);
if ((maclen != (unsigned int)ASN1_STRING_length(macoct))
|| CRYPTO_memcmp(mac, ASN1_STRING_get0_data(macoct), maclen) != 0)
return 0;
return 1;
}
/* Set a mac */
int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
unsigned char *salt, int saltlen, int iter,
const EVP_MD *md_type)
{
unsigned char mac[EVP_MAX_MD_SIZE];
unsigned int maclen;
ASN1_OCTET_STRING *macoct;
if (!md_type)
md_type = EVP_sha1();
if (PKCS12_setup_mac(p12, iter, salt, saltlen, md_type) == PKCS12_ERROR) {
PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_SETUP_ERROR);
return 0;
}
/*
* Note that output mac is forced to UTF-8...
*/
if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen,
PKCS12_key_gen_utf8)) {
PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_GENERATION_ERROR);
return 0;
}
X509_SIG_getm(p12->mac->dinfo, NULL, &macoct);
if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) {
PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_STRING_SET_ERROR);
return 0;
}
return 1;
}
/* Set up a mac structure */
int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
const EVP_MD *md_type)
{
X509_ALGOR *macalg;
PKCS12_MAC_DATA_free(p12->mac);
p12->mac = NULL;
if ((p12->mac = PKCS12_MAC_DATA_new()) == NULL)
return PKCS12_ERROR;
if (iter > 1) {
if ((p12->mac->iter = ASN1_INTEGER_new()) == NULL) {
PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ASN1_INTEGER_set(p12->mac->iter, iter)) {
PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (!saltlen)
saltlen = PKCS12_SALT_LEN;
if ((p12->mac->salt->data = OPENSSL_malloc(saltlen)) == NULL) {
PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
return 0;
}
p12->mac->salt->length = saltlen;
if (!salt) {
if (RAND_bytes(p12->mac->salt->data, saltlen) <= 0)
return 0;
} else
memcpy(p12->mac->salt->data, salt, saltlen);
X509_SIG_getm(p12->mac->dinfo, &macalg, NULL);
if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(EVP_MD_type(md_type)),
V_ASN1_NULL, NULL)) {
PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
diff --git a/crypto/poly1305/poly1305_ieee754.c b/crypto/poly1305/poly1305_ieee754.c
index 995a02e5c139..7cfd968645ff 100644
--- a/crypto/poly1305/poly1305_ieee754.c
+++ b/crypto/poly1305/poly1305_ieee754.c
@@ -1,488 +1,488 @@
/*
- * Copyright 2016-20018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2018 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
*/
/*
* This module is meant to be used as template for non-x87 floating-
* point assembly modules. The template itself is x86_64-specific
* though, as it was debugged on x86_64. So that implementor would
* have to recognize platform-specific parts, UxTOy and inline asm,
* and act accordingly.
*
* Huh? x86_64-specific code as template for non-x87? Note seven, which
* is not a typo, but reference to 80-bit precision. This module on the
* other hand relies on 64-bit precision operations, which are default
* for x86_64 code. And since we are at it, just for sense of it,
* large-block performance in cycles per processed byte for *this* code
* is:
* gcc-4.8 icc-15.0 clang-3.4(*)
*
* Westmere 4.96 5.09 4.37
* Sandy Bridge 4.95 4.90 4.17
* Haswell 4.92 4.87 3.78
* Bulldozer 4.67 4.49 4.68
* VIA Nano 7.07 7.05 5.98
* Silvermont 10.6 9.61 12.6
*
* (*) clang managed to discover parallelism and deployed SIMD;
*
* And for range of other platforms with unspecified gcc versions:
*
* Freescale e300 12.5
* PPC74x0 10.8
* POWER6 4.92
* POWER7 4.50
* POWER8 4.10
*
* z10 11.2
* z196+ 7.30
*
* UltraSPARC III 16.0
* SPARC T4 16.1
*/
#if !(defined(__GNUC__) && __GNUC__>=2)
# error "this is gcc-specific template"
#endif
#include <stdlib.h>
typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef union { double d; u64 u; } elem64;
#define TWO(p) ((double)(1ULL<<(p)))
#define TWO0 TWO(0)
#define TWO32 TWO(32)
#define TWO64 (TWO32*TWO(32))
#define TWO96 (TWO64*TWO(32))
#define TWO130 (TWO96*TWO(34))
#define EXP(p) ((1023ULL+(p))<<52)
#if defined(__x86_64__) || (defined(__PPC__) && defined(__LITTLE_ENDIAN__))
# define U8TOU32(p) (*(const u32 *)(p))
# define U32TO8(p,v) (*(u32 *)(p) = (v))
#elif defined(__PPC__)
# define U8TOU32(p) ({u32 ret; asm ("lwbrx %0,0,%1":"=r"(ret):"b"(p)); ret; })
# define U32TO8(p,v) asm ("stwbrx %0,0,%1"::"r"(v),"b"(p):"memory")
#elif defined(__s390x__)
# define U8TOU32(p) ({u32 ret; asm ("lrv %0,%1":"=d"(ret):"m"(*(u32 *)(p))); ret; })
# define U32TO8(p,v) asm ("strv %1,%0":"=m"(*(u32 *)(p)):"d"(v))
#endif
#ifndef U8TOU32
# define U8TOU32(p) ((u32)(p)[0] | (u32)(p)[1]<<8 | \
(u32)(p)[2]<<16 | (u32)(p)[3]<<24 )
#endif
#ifndef U32TO8
# define U32TO8(p,v) ((p)[0] = (u8)(v), (p)[1] = (u8)((v)>>8), \
(p)[2] = (u8)((v)>>16), (p)[3] = (u8)((v)>>24) )
#endif
typedef struct {
elem64 h[4];
double r[8];
double s[6];
} poly1305_internal;
/* "round toward zero (truncate), mask all exceptions" */
#if defined(__x86_64__)
static const u32 mxcsr = 0x7f80;
#elif defined(__PPC__)
static const u64 one = 1;
#elif defined(__s390x__)
static const u32 fpc = 1;
#elif defined(__sparc__)
static const u64 fsr = 1ULL<<30;
#elif defined(__mips__)
static const u32 fcsr = 1;
#else
#error "unrecognized platform"
#endif
int poly1305_init(void *ctx, const unsigned char key[16])
{
poly1305_internal *st = (poly1305_internal *) ctx;
elem64 r0, r1, r2, r3;
/* h = 0, biased */
#if 0
st->h[0].d = TWO(52)*TWO0;
st->h[1].d = TWO(52)*TWO32;
st->h[2].d = TWO(52)*TWO64;
st->h[3].d = TWO(52)*TWO96;
#else
st->h[0].u = EXP(52+0);
st->h[1].u = EXP(52+32);
st->h[2].u = EXP(52+64);
st->h[3].u = EXP(52+96);
#endif
if (key) {
/*
* set "truncate" rounding mode
*/
#if defined(__x86_64__)
u32 mxcsr_orig;
asm volatile ("stmxcsr %0":"=m"(mxcsr_orig));
asm volatile ("ldmxcsr %0"::"m"(mxcsr));
#elif defined(__PPC__)
double fpscr_orig, fpscr = *(double *)&one;
asm volatile ("mffs %0":"=f"(fpscr_orig));
asm volatile ("mtfsf 255,%0"::"f"(fpscr));
#elif defined(__s390x__)
u32 fpc_orig;
asm volatile ("stfpc %0":"=m"(fpc_orig));
asm volatile ("lfpc %0"::"m"(fpc));
#elif defined(__sparc__)
u64 fsr_orig;
asm volatile ("stx %%fsr,%0":"=m"(fsr_orig));
asm volatile ("ldx %0,%%fsr"::"m"(fsr));
#elif defined(__mips__)
u32 fcsr_orig;
asm volatile ("cfc1 %0,$31":"=r"(fcsr_orig));
asm volatile ("ctc1 %0,$31"::"r"(fcsr));
#endif
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
r0.u = EXP(52+0) | (U8TOU32(&key[0]) & 0x0fffffff);
r1.u = EXP(52+32) | (U8TOU32(&key[4]) & 0x0ffffffc);
r2.u = EXP(52+64) | (U8TOU32(&key[8]) & 0x0ffffffc);
r3.u = EXP(52+96) | (U8TOU32(&key[12]) & 0x0ffffffc);
st->r[0] = r0.d - TWO(52)*TWO0;
st->r[2] = r1.d - TWO(52)*TWO32;
st->r[4] = r2.d - TWO(52)*TWO64;
st->r[6] = r3.d - TWO(52)*TWO96;
st->s[0] = st->r[2] * (5.0/TWO130);
st->s[2] = st->r[4] * (5.0/TWO130);
st->s[4] = st->r[6] * (5.0/TWO130);
/*
* base 2^32 -> base 2^16
*/
st->r[1] = (st->r[0] + TWO(52)*TWO(16)*TWO0) -
TWO(52)*TWO(16)*TWO0;
st->r[0] -= st->r[1];
st->r[3] = (st->r[2] + TWO(52)*TWO(16)*TWO32) -
TWO(52)*TWO(16)*TWO32;
st->r[2] -= st->r[3];
st->r[5] = (st->r[4] + TWO(52)*TWO(16)*TWO64) -
TWO(52)*TWO(16)*TWO64;
st->r[4] -= st->r[5];
st->r[7] = (st->r[6] + TWO(52)*TWO(16)*TWO96) -
TWO(52)*TWO(16)*TWO96;
st->r[6] -= st->r[7];
st->s[1] = (st->s[0] + TWO(52)*TWO(16)*TWO0/TWO96) -
TWO(52)*TWO(16)*TWO0/TWO96;
st->s[0] -= st->s[1];
st->s[3] = (st->s[2] + TWO(52)*TWO(16)*TWO32/TWO96) -
TWO(52)*TWO(16)*TWO32/TWO96;
st->s[2] -= st->s[3];
st->s[5] = (st->s[4] + TWO(52)*TWO(16)*TWO64/TWO96) -
TWO(52)*TWO(16)*TWO64/TWO96;
st->s[4] -= st->s[5];
/*
* restore original FPU control register
*/
#if defined(__x86_64__)
asm volatile ("ldmxcsr %0"::"m"(mxcsr_orig));
#elif defined(__PPC__)
asm volatile ("mtfsf 255,%0"::"f"(fpscr_orig));
#elif defined(__s390x__)
asm volatile ("lfpc %0"::"m"(fpc_orig));
#elif defined(__sparc__)
asm volatile ("ldx %0,%%fsr"::"m"(fsr_orig));
#elif defined(__mips__)
asm volatile ("ctc1 %0,$31"::"r"(fcsr_orig));
#endif
}
return 0;
}
void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len,
int padbit)
{
poly1305_internal *st = (poly1305_internal *)ctx;
elem64 in0, in1, in2, in3;
u64 pad = (u64)padbit<<32;
double x0, x1, x2, x3;
double h0lo, h0hi, h1lo, h1hi, h2lo, h2hi, h3lo, h3hi;
double c0lo, c0hi, c1lo, c1hi, c2lo, c2hi, c3lo, c3hi;
const double r0lo = st->r[0];
const double r0hi = st->r[1];
const double r1lo = st->r[2];
const double r1hi = st->r[3];
const double r2lo = st->r[4];
const double r2hi = st->r[5];
const double r3lo = st->r[6];
const double r3hi = st->r[7];
const double s1lo = st->s[0];
const double s1hi = st->s[1];
const double s2lo = st->s[2];
const double s2hi = st->s[3];
const double s3lo = st->s[4];
const double s3hi = st->s[5];
/*
* set "truncate" rounding mode
*/
#if defined(__x86_64__)
u32 mxcsr_orig;
asm volatile ("stmxcsr %0":"=m"(mxcsr_orig));
asm volatile ("ldmxcsr %0"::"m"(mxcsr));
#elif defined(__PPC__)
double fpscr_orig, fpscr = *(double *)&one;
asm volatile ("mffs %0":"=f"(fpscr_orig));
asm volatile ("mtfsf 255,%0"::"f"(fpscr));
#elif defined(__s390x__)
u32 fpc_orig;
asm volatile ("stfpc %0":"=m"(fpc_orig));
asm volatile ("lfpc %0"::"m"(fpc));
#elif defined(__sparc__)
u64 fsr_orig;
asm volatile ("stx %%fsr,%0":"=m"(fsr_orig));
asm volatile ("ldx %0,%%fsr"::"m"(fsr));
#elif defined(__mips__)
u32 fcsr_orig;
asm volatile ("cfc1 %0,$31":"=r"(fcsr_orig));
asm volatile ("ctc1 %0,$31"::"r"(fcsr));
#endif
/*
* load base 2^32 and de-bias
*/
h0lo = st->h[0].d - TWO(52)*TWO0;
h1lo = st->h[1].d - TWO(52)*TWO32;
h2lo = st->h[2].d - TWO(52)*TWO64;
h3lo = st->h[3].d - TWO(52)*TWO96;
#ifdef __clang__
h0hi = 0;
h1hi = 0;
h2hi = 0;
h3hi = 0;
#else
in0.u = EXP(52+0) | U8TOU32(&inp[0]);
in1.u = EXP(52+32) | U8TOU32(&inp[4]);
in2.u = EXP(52+64) | U8TOU32(&inp[8]);
in3.u = EXP(52+96) | U8TOU32(&inp[12]) | pad;
x0 = in0.d - TWO(52)*TWO0;
x1 = in1.d - TWO(52)*TWO32;
x2 = in2.d - TWO(52)*TWO64;
x3 = in3.d - TWO(52)*TWO96;
x0 += h0lo;
x1 += h1lo;
x2 += h2lo;
x3 += h3lo;
goto fast_entry;
#endif
do {
in0.u = EXP(52+0) | U8TOU32(&inp[0]);
in1.u = EXP(52+32) | U8TOU32(&inp[4]);
in2.u = EXP(52+64) | U8TOU32(&inp[8]);
in3.u = EXP(52+96) | U8TOU32(&inp[12]) | pad;
x0 = in0.d - TWO(52)*TWO0;
x1 = in1.d - TWO(52)*TWO32;
x2 = in2.d - TWO(52)*TWO64;
x3 = in3.d - TWO(52)*TWO96;
/*
* note that there are multiple ways to accumulate input, e.g.
* one can as well accumulate to h0lo-h1lo-h1hi-h2hi...
*/
h0lo += x0;
h0hi += x1;
h2lo += x2;
h2hi += x3;
/*
* carries that cross 32n-bit (and 130-bit) boundaries
*/
c0lo = (h0lo + TWO(52)*TWO32) - TWO(52)*TWO32;
c1lo = (h1lo + TWO(52)*TWO64) - TWO(52)*TWO64;
c2lo = (h2lo + TWO(52)*TWO96) - TWO(52)*TWO96;
c3lo = (h3lo + TWO(52)*TWO130) - TWO(52)*TWO130;
c0hi = (h0hi + TWO(52)*TWO32) - TWO(52)*TWO32;
c1hi = (h1hi + TWO(52)*TWO64) - TWO(52)*TWO64;
c2hi = (h2hi + TWO(52)*TWO96) - TWO(52)*TWO96;
c3hi = (h3hi + TWO(52)*TWO130) - TWO(52)*TWO130;
/*
* base 2^48 -> base 2^32 with last reduction step
*/
x1 = (h1lo - c1lo) + c0lo;
x2 = (h2lo - c2lo) + c1lo;
x3 = (h3lo - c3lo) + c2lo;
x0 = (h0lo - c0lo) + c3lo * (5.0/TWO130);
x1 += (h1hi - c1hi) + c0hi;
x2 += (h2hi - c2hi) + c1hi;
x3 += (h3hi - c3hi) + c2hi;
x0 += (h0hi - c0hi) + c3hi * (5.0/TWO130);
#ifndef __clang__
fast_entry:
#endif
/*
* base 2^32 * base 2^16 = base 2^48
*/
h0lo = s3lo * x1 + s2lo * x2 + s1lo * x3 + r0lo * x0;
h1lo = r0lo * x1 + s3lo * x2 + s2lo * x3 + r1lo * x0;
h2lo = r1lo * x1 + r0lo * x2 + s3lo * x3 + r2lo * x0;
h3lo = r2lo * x1 + r1lo * x2 + r0lo * x3 + r3lo * x0;
h0hi = s3hi * x1 + s2hi * x2 + s1hi * x3 + r0hi * x0;
h1hi = r0hi * x1 + s3hi * x2 + s2hi * x3 + r1hi * x0;
h2hi = r1hi * x1 + r0hi * x2 + s3hi * x3 + r2hi * x0;
h3hi = r2hi * x1 + r1hi * x2 + r0hi * x3 + r3hi * x0;
inp += 16;
len -= 16;
} while (len >= 16);
/*
* carries that cross 32n-bit (and 130-bit) boundaries
*/
c0lo = (h0lo + TWO(52)*TWO32) - TWO(52)*TWO32;
c1lo = (h1lo + TWO(52)*TWO64) - TWO(52)*TWO64;
c2lo = (h2lo + TWO(52)*TWO96) - TWO(52)*TWO96;
c3lo = (h3lo + TWO(52)*TWO130) - TWO(52)*TWO130;
c0hi = (h0hi + TWO(52)*TWO32) - TWO(52)*TWO32;
c1hi = (h1hi + TWO(52)*TWO64) - TWO(52)*TWO64;
c2hi = (h2hi + TWO(52)*TWO96) - TWO(52)*TWO96;
c3hi = (h3hi + TWO(52)*TWO130) - TWO(52)*TWO130;
/*
* base 2^48 -> base 2^32 with last reduction step
*/
x1 = (h1lo - c1lo) + c0lo;
x2 = (h2lo - c2lo) + c1lo;
x3 = (h3lo - c3lo) + c2lo;
x0 = (h0lo - c0lo) + c3lo * (5.0/TWO130);
x1 += (h1hi - c1hi) + c0hi;
x2 += (h2hi - c2hi) + c1hi;
x3 += (h3hi - c3hi) + c2hi;
x0 += (h0hi - c0hi) + c3hi * (5.0/TWO130);
/*
* store base 2^32, with bias
*/
st->h[1].d = x1 + TWO(52)*TWO32;
st->h[2].d = x2 + TWO(52)*TWO64;
st->h[3].d = x3 + TWO(52)*TWO96;
st->h[0].d = x0 + TWO(52)*TWO0;
/*
* restore original FPU control register
*/
#if defined(__x86_64__)
asm volatile ("ldmxcsr %0"::"m"(mxcsr_orig));
#elif defined(__PPC__)
asm volatile ("mtfsf 255,%0"::"f"(fpscr_orig));
#elif defined(__s390x__)
asm volatile ("lfpc %0"::"m"(fpc_orig));
#elif defined(__sparc__)
asm volatile ("ldx %0,%%fsr"::"m"(fsr_orig));
#elif defined(__mips__)
asm volatile ("ctc1 %0,$31"::"r"(fcsr_orig));
#endif
}
void poly1305_emit(void *ctx, unsigned char mac[16], const u32 nonce[4])
{
poly1305_internal *st = (poly1305_internal *) ctx;
u64 h0, h1, h2, h3, h4;
u32 g0, g1, g2, g3, g4;
u64 t;
u32 mask;
/*
* thanks to bias masking exponent gives integer result
*/
h0 = st->h[0].u & 0x000fffffffffffffULL;
h1 = st->h[1].u & 0x000fffffffffffffULL;
h2 = st->h[2].u & 0x000fffffffffffffULL;
h3 = st->h[3].u & 0x000fffffffffffffULL;
/*
* can be partially reduced, so reduce...
*/
h4 = h3>>32; h3 &= 0xffffffffU;
g4 = h4&-4;
h4 &= 3;
g4 += g4>>2;
h0 += g4;
h1 += h0>>32; h0 &= 0xffffffffU;
h2 += h1>>32; h1 &= 0xffffffffU;
h3 += h2>>32; h2 &= 0xffffffffU;
/* compute h + -p */
g0 = (u32)(t = h0 + 5);
g1 = (u32)(t = h1 + (t >> 32));
g2 = (u32)(t = h2 + (t >> 32));
g3 = (u32)(t = h3 + (t >> 32));
g4 = h4 + (u32)(t >> 32);
/* if there was carry, select g0-g3 */
mask = 0 - (g4 >> 2);
g0 &= mask;
g1 &= mask;
g2 &= mask;
g3 &= mask;
mask = ~mask;
g0 |= (h0 & mask);
g1 |= (h1 & mask);
g2 |= (h2 & mask);
g3 |= (h3 & mask);
/* mac = (h + nonce) % (2^128) */
g0 = (u32)(t = (u64)g0 + nonce[0]);
g1 = (u32)(t = (u64)g1 + (t >> 32) + nonce[1]);
g2 = (u32)(t = (u64)g2 + (t >> 32) + nonce[2]);
g3 = (u32)(t = (u64)g3 + (t >> 32) + nonce[3]);
U32TO8(mac + 0, g0);
U32TO8(mac + 4, g1);
U32TO8(mac + 8, g2);
U32TO8(mac + 12, g3);
}
diff --git a/crypto/rand/drbg_ctr.c b/crypto/rand/drbg_ctr.c
index fe15164451e8..a243361b56e4 100644
--- a/crypto/rand/drbg_ctr.c
+++ b/crypto/rand/drbg_ctr.c
@@ -1,438 +1,438 @@
/*
* Copyright 2011-2018 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 <stdlib.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "internal/thread_once.h"
#include "internal/thread_once.h"
#include "rand_lcl.h"
/*
* Implementation of NIST SP 800-90A CTR DRBG.
*/
static void inc_128(RAND_DRBG_CTR *ctr)
{
int i;
unsigned char c;
unsigned char *p = &ctr->V[15];
for (i = 0; i < 16; i++, p--) {
c = *p;
c++;
*p = c;
if (c != 0) {
/* If we didn't wrap around, we're done. */
break;
}
}
}
static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
{
size_t i, n;
if (in == NULL || inlen == 0)
return;
/*
* Any zero padding will have no effect on the result as we
* are XORing. So just process however much input we have.
*/
n = inlen < ctr->keylen ? inlen : ctr->keylen;
for (i = 0; i < n; i++)
ctr->K[i] ^= in[i];
if (inlen <= ctr->keylen)
return;
n = inlen - ctr->keylen;
if (n > 16) {
/* Should never happen */
n = 16;
}
for (i = 0; i < n; i++)
ctr->V[i] ^= in[i + ctr->keylen];
}
/*
* Process a complete block using BCC algorithm of SP 800-90A 10.3.3
*/
__owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out,
const unsigned char *in)
{
int i, outlen = AES_BLOCK_SIZE;
for (i = 0; i < 16; i++)
out[i] ^= in[i];
if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, AES_BLOCK_SIZE)
|| outlen != AES_BLOCK_SIZE)
return 0;
return 1;
}
/*
* Handle several BCC operations for as much data as we need for K and X
*/
__owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in)
{
if (!ctr_BCC_block(ctr, ctr->KX, in)
|| !ctr_BCC_block(ctr, ctr->KX + 16, in))
return 0;
if (ctr->keylen != 16 && !ctr_BCC_block(ctr, ctr->KX + 32, in))
return 0;
return 1;
}
/*
* Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:
* see 10.3.1 stage 7.
*/
__owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr)
{
memset(ctr->KX, 0, 48);
memset(ctr->bltmp, 0, 16);
if (!ctr_BCC_block(ctr, ctr->KX, ctr->bltmp))
return 0;
ctr->bltmp[3] = 1;
if (!ctr_BCC_block(ctr, ctr->KX + 16, ctr->bltmp))
return 0;
if (ctr->keylen != 16) {
ctr->bltmp[3] = 2;
if (!ctr_BCC_block(ctr, ctr->KX + 32, ctr->bltmp))
return 0;
}
return 1;
}
/*
* Process several blocks into BCC algorithm, some possibly partial
*/
__owur static int ctr_BCC_update(RAND_DRBG_CTR *ctr,
const unsigned char *in, size_t inlen)
{
if (in == NULL || inlen == 0)
return 1;
/* If we have partial block handle it first */
if (ctr->bltmp_pos) {
size_t left = 16 - ctr->bltmp_pos;
/* If we now have a complete block process it */
if (inlen >= left) {
memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);
if (!ctr_BCC_blocks(ctr, ctr->bltmp))
return 0;
ctr->bltmp_pos = 0;
inlen -= left;
in += left;
}
}
/* Process zero or more complete blocks */
for (; inlen >= 16; in += 16, inlen -= 16) {
if (!ctr_BCC_blocks(ctr, in))
return 0;
}
/* Copy any remaining partial block to the temporary buffer */
if (inlen > 0) {
memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);
ctr->bltmp_pos += inlen;
}
return 1;
}
__owur static int ctr_BCC_final(RAND_DRBG_CTR *ctr)
{
if (ctr->bltmp_pos) {
memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
if (!ctr_BCC_blocks(ctr, ctr->bltmp))
return 0;
}
return 1;
}
__owur static int ctr_df(RAND_DRBG_CTR *ctr,
const unsigned char *in1, size_t in1len,
const unsigned char *in2, size_t in2len,
const unsigned char *in3, size_t in3len)
{
static unsigned char c80 = 0x80;
size_t inlen;
unsigned char *p = ctr->bltmp;
int outlen = AES_BLOCK_SIZE;
if (!ctr_BCC_init(ctr))
return 0;
if (in1 == NULL)
in1len = 0;
if (in2 == NULL)
in2len = 0;
if (in3 == NULL)
in3len = 0;
inlen = in1len + in2len + in3len;
/* Initialise L||N in temporary block */
*p++ = (inlen >> 24) & 0xff;
*p++ = (inlen >> 16) & 0xff;
*p++ = (inlen >> 8) & 0xff;
*p++ = inlen & 0xff;
/* NB keylen is at most 32 bytes */
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p = (unsigned char)((ctr->keylen + 16) & 0xff);
ctr->bltmp_pos = 8;
if (!ctr_BCC_update(ctr, in1, in1len)
|| !ctr_BCC_update(ctr, in2, in2len)
|| !ctr_BCC_update(ctr, in3, in3len)
|| !ctr_BCC_update(ctr, &c80, 1)
|| !ctr_BCC_final(ctr))
return 0;
/* Set up key K */
if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->KX, NULL, 1))
return 0;
/* X follows key K */
if (!EVP_CipherUpdate(ctr->ctx, ctr->KX, &outlen, ctr->KX + ctr->keylen,
AES_BLOCK_SIZE)
|| outlen != AES_BLOCK_SIZE)
return 0;
if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 16, &outlen, ctr->KX,
AES_BLOCK_SIZE)
|| outlen != AES_BLOCK_SIZE)
return 0;
if (ctr->keylen != 16)
if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 32, &outlen, ctr->KX + 16,
AES_BLOCK_SIZE)
|| outlen != AES_BLOCK_SIZE)
return 0;
return 1;
}
/*
* NB the no-df Update in SP800-90A specifies a constant input length
* of seedlen, however other uses of this algorithm pad the input with
* zeroes if necessary and have up to two parameters XORed together,
* so we handle both cases in this function instead.
*/
__owur static int ctr_update(RAND_DRBG *drbg,
const unsigned char *in1, size_t in1len,
const unsigned char *in2, size_t in2len,
const unsigned char *nonce, size_t noncelen)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
int outlen = AES_BLOCK_SIZE;
/* correct key is already set up. */
inc_128(ctr);
if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outlen, ctr->V, AES_BLOCK_SIZE)
|| outlen != AES_BLOCK_SIZE)
return 0;
/* If keylen longer than 128 bits need extra encrypt */
if (ctr->keylen != 16) {
inc_128(ctr);
if (!EVP_CipherUpdate(ctr->ctx, ctr->K+16, &outlen, ctr->V,
AES_BLOCK_SIZE)
|| outlen != AES_BLOCK_SIZE)
return 0;
}
inc_128(ctr);
if (!EVP_CipherUpdate(ctr->ctx, ctr->V, &outlen, ctr->V, AES_BLOCK_SIZE)
|| outlen != AES_BLOCK_SIZE)
return 0;
/* If 192 bit key part of V is on end of K */
if (ctr->keylen == 24) {
memcpy(ctr->V + 8, ctr->V, 8);
memcpy(ctr->V, ctr->K + 24, 8);
}
if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
/* If no input reuse existing derived value */
if (in1 != NULL || nonce != NULL || in2 != NULL)
if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
return 0;
/* If this a reuse input in1len != 0 */
if (in1len)
ctr_XOR(ctr, ctr->KX, drbg->seedlen);
} else {
ctr_XOR(ctr, in1, in1len);
ctr_XOR(ctr, in2, in2len);
}
if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1))
return 0;
return 1;
}
__owur static int drbg_ctr_instantiate(RAND_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *nonce, size_t noncelen,
const unsigned char *pers, size_t perslen)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
if (entropy == NULL)
return 0;
memset(ctr->K, 0, sizeof(ctr->K));
memset(ctr->V, 0, sizeof(ctr->V));
if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1))
return 0;
if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen))
return 0;
return 1;
}
__owur static int drbg_ctr_reseed(RAND_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *adin, size_t adinlen)
{
if (entropy == NULL)
return 0;
if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))
return 0;
return 1;
}
__owur static int drbg_ctr_generate(RAND_DRBG *drbg,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adinlen)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
if (adin != NULL && adinlen != 0) {
if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
return 0;
/* This means we reuse derived value */
if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
adin = NULL;
adinlen = 1;
}
} else {
adinlen = 0;
}
for ( ; ; ) {
int outl = AES_BLOCK_SIZE;
inc_128(ctr);
if (outlen < 16) {
/* Use K as temp space as it will be updated */
if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outl, ctr->V,
AES_BLOCK_SIZE)
|| outl != AES_BLOCK_SIZE)
return 0;
memcpy(out, ctr->K, outlen);
break;
}
if (!EVP_CipherUpdate(ctr->ctx, out, &outl, ctr->V, AES_BLOCK_SIZE)
|| outl != AES_BLOCK_SIZE)
return 0;
out += 16;
outlen -= 16;
if (outlen == 0)
break;
}
if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
return 0;
return 1;
}
static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
{
EVP_CIPHER_CTX_free(drbg->data.ctr.ctx);
EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
return 1;
}
static RAND_DRBG_METHOD drbg_ctr_meth = {
drbg_ctr_instantiate,
drbg_ctr_reseed,
drbg_ctr_generate,
drbg_ctr_uninstantiate
};
int drbg_ctr_init(RAND_DRBG *drbg)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
size_t keylen;
switch (drbg->type) {
default:
/* This can't happen, but silence the compiler warning. */
return 0;
case NID_aes_128_ctr:
keylen = 16;
ctr->cipher = EVP_aes_128_ecb();
break;
case NID_aes_192_ctr:
keylen = 24;
ctr->cipher = EVP_aes_192_ecb();
break;
case NID_aes_256_ctr:
keylen = 32;
ctr->cipher = EVP_aes_256_ecb();
break;
}
drbg->meth = &drbg_ctr_meth;
ctr->keylen = keylen;
if (ctr->ctx == NULL)
ctr->ctx = EVP_CIPHER_CTX_new();
if (ctr->ctx == NULL)
return 0;
drbg->strength = keylen * 8;
drbg->seedlen = keylen + 16;
if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
/* df initialisation */
static const unsigned char df_key[32] = {
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
- 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
- 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
if (ctr->ctx_df == NULL)
ctr->ctx_df = EVP_CIPHER_CTX_new();
if (ctr->ctx_df == NULL)
return 0;
/* Set key schedule for df_key */
if (!EVP_CipherInit_ex(ctr->ctx_df, ctr->cipher, NULL, df_key, NULL, 1))
return 0;
drbg->min_entropylen = ctr->keylen;
- drbg->max_entropylen = DRBG_MINMAX_FACTOR * drbg->min_entropylen;
+ drbg->max_entropylen = DRBG_MAX_LENGTH;
drbg->min_noncelen = drbg->min_entropylen / 2;
- drbg->max_noncelen = DRBG_MINMAX_FACTOR * drbg->min_noncelen;
+ drbg->max_noncelen = DRBG_MAX_LENGTH;
drbg->max_perslen = DRBG_MAX_LENGTH;
drbg->max_adinlen = DRBG_MAX_LENGTH;
} else {
drbg->min_entropylen = drbg->seedlen;
drbg->max_entropylen = drbg->seedlen;
/* Nonce not used */
drbg->min_noncelen = 0;
drbg->max_noncelen = 0;
drbg->max_perslen = drbg->seedlen;
drbg->max_adinlen = drbg->seedlen;
}
drbg->max_request = 1 << 16;
return 1;
}
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index 729b49c94372..a13282181d6d 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -1,1070 +1,1159 @@
/*
* Copyright 2011-2018 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)
+ 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) {
+ 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));
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:
- if (drbg->secure)
- OPENSSL_secure_free(drbg);
- else
- OPENSSL_free(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) {
+ || 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->generate_counter = 0;
+ drbg->reseed_gen_counter = 1;
drbg->reseed_time = time(NULL);
- if (drbg->reseed_counter > 0) {
- if (drbg->parent == NULL)
- drbg->reseed_counter++;
- else
- drbg->reseed_counter = drbg->parent->reseed_counter;
- }
+ tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
-end:
+ end:
if (entropy != NULL && drbg->cleanup_entropy != NULL)
drbg->cleanup_entropy(drbg, entropy, entropylen);
- if (nonce != NULL && drbg->cleanup_nonce!= NULL )
+ if (nonce != NULL && drbg->cleanup_nonce != NULL)
drbg->cleanup_nonce(drbg, nonce, noncelen);
- if (drbg->pool != NULL) {
- if (drbg->state == DRBG_READY) {
- RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
- RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED);
- drbg->state = DRBG_ERROR;
- }
- rand_pool_free(drbg->pool);
- drbg->pool = NULL;
- }
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) {
+ || 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->generate_counter = 0;
+ drbg->reseed_gen_counter = 1;
drbg->reseed_time = time(NULL);
- if (drbg->reseed_counter > 0) {
- if (drbg->parent == NULL)
- drbg->reseed_counter++;
- else
- drbg->reseed_counter = drbg->parent->reseed_counter;
- }
+ tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
-end:
+ 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->pool != NULL) {
+ if (drbg->seed_pool != NULL) {
RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
- rand_pool_free(drbg->pool);
- drbg->pool = NULL;
+ 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->pool = rand_pool_new(entropy, len, len);
- if (drbg->pool == NULL)
+ drbg->seed_pool = rand_pool_attach(buffer, len, entropy);
+ if (drbg->seed_pool == NULL)
return 0;
-
- rand_pool_add(drbg->pool, buffer, len, entropy);
} 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);
}
}
- /* check whether a given entropy pool was cleared properly during reseed */
- if (drbg->pool != NULL) {
- drbg->state = DRBG_ERROR;
- RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
- rand_pool_free(drbg->pool);
- drbg->pool = NULL;
- return 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->generate_counter >= drbg->reseed_interval)
+ 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->reseed_counter > 0 && drbg->parent != NULL) {
- if (drbg->reseed_counter != drbg->parent->reseed_counter)
+ 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->generate_counter++;
+ 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;
+ 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(&additional, drbg->max_adinlen);
+ 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_len != 0)
- OPENSSL_secure_clear_free(additional, additional_len);
+ 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)
+ 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 */
- drbg->reseed_counter = 1;
+ 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;
- if (randomness > (double)drbg->max_entropylen) {
+ 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.
+ * call below. Note that randomness is measured in bytes,
+ * not bits, so this value corresponds to eight times the
+ * security strength.
*/
- return 0;
+ randomness = (double)seedlen;
}
- rand_drbg_lock(drbg);
- ret = rand_drbg_restart(drbg, buf,
- (size_t)(unsigned int)num,
- (size_t)(8*randomness));
+ 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_err.c b/crypto/rand/rand_err.c
index 31480a682838..6a870455d50a 100644
--- a/crypto/rand/rand_err.c
+++ b/crypto/rand/rand_err.c
@@ -1,134 +1,135 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 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/err.h>
#include <openssl/randerr.h>
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA RAND_str_functs[] = {
{ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_BYTES, 0), "drbg_bytes"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_GET_ENTROPY, 0), "drbg_get_entropy"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_SETUP, 0), "drbg_setup"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_GET_ENTROPY, 0), "get_entropy"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_BYTES, 0), "RAND_bytes"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_ENABLE_LOCKING, 0),
"rand_drbg_enable_locking"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GENERATE, 0),
"RAND_DRBG_generate"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GET_ENTROPY, 0),
"rand_drbg_get_entropy"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GET_NONCE, 0),
"rand_drbg_get_nonce"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_INSTANTIATE, 0),
"RAND_DRBG_instantiate"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_NEW, 0), "RAND_DRBG_new"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESEED, 0), "RAND_DRBG_reseed"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESTART, 0), "rand_drbg_restart"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET, 0), "RAND_DRBG_set"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET_DEFAULTS, 0),
"RAND_DRBG_set_defaults"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_UNINSTANTIATE, 0),
"RAND_DRBG_uninstantiate"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_LOAD_FILE, 0), "RAND_load_file"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ACQUIRE_ENTROPY, 0),
"rand_pool_acquire_entropy"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD, 0), "rand_pool_add"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_BEGIN, 0),
"rand_pool_add_begin"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_END, 0), "rand_pool_add_end"},
+ {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ATTACH, 0), "rand_pool_attach"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_BYTES_NEEDED, 0),
"rand_pool_bytes_needed"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_NEW, 0), "rand_pool_new"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_WRITE_FILE, 0), "RAND_write_file"},
{0, NULL}
};
static const ERR_STRING_DATA RAND_str_reasons[] = {
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ADDITIONAL_INPUT_TOO_LONG),
"additional input too long"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ALREADY_INSTANTIATED),
"already instantiated"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ARGUMENT_OUT_OF_RANGE),
"argument out of range"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_CANNOT_OPEN_FILE), "Cannot open file"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_ALREADY_INITIALIZED),
"drbg already initialized"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_NOT_INITIALISED),
"drbg not initialised"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_INPUT_TOO_LONG),
"entropy input too long"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_OUT_OF_RANGE),
"entropy out of range"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED),
"error entropy pool was ignored"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_INITIALISING_DRBG),
"error initialising drbg"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_INSTANTIATING_DRBG),
"error instantiating drbg"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT),
"error retrieving additional input"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_ENTROPY),
"error retrieving entropy"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_NONCE),
"error retrieving nonce"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FAILED_TO_CREATE_LOCK),
"failed to create lock"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FUNC_NOT_IMPLEMENTED),
"Function not implemented"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FWRITE_ERROR), "Error writing file"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_GENERATE_ERROR), "generate error"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INTERNAL_ERROR), "internal error"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_IN_ERROR_STATE), "in error state"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE),
"Not a regular file"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_INSTANTIATED), "not instantiated"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED),
"no drbg implementation selected"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_LOCKING_NOT_ENABLED),
"parent locking not enabled"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_STRENGTH_TOO_WEAK),
"parent strength too weak"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PERSONALISATION_STRING_TOO_LONG),
"personalisation string too long"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED),
"prediction resistance not supported"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PRNG_NOT_SEEDED), "PRNG not seeded"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_OVERFLOW),
"random pool overflow"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_UNDERFLOW),
"random pool underflow"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG),
"request too large for drbg"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RESEED_ERROR), "reseed error"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_SELFTEST_FAILURE), "selftest failure"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_LITTLE_NONCE_REQUESTED),
"too little nonce requested"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_MUCH_NONCE_REQUESTED),
"too much nonce requested"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_FLAGS),
"unsupported drbg flags"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_TYPE),
"unsupported drbg type"},
{0, NULL}
};
#endif
int ERR_load_RAND_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(RAND_str_functs[0].error) == NULL) {
ERR_load_strings_const(RAND_str_functs);
ERR_load_strings_const(RAND_str_reasons);
}
#endif
return 1;
}
diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h
index 94ffc96f20e2..c3e9804dc07e 100755
--- a/crypto/rand/rand_lcl.h
+++ b/crypto/rand/rand_lcl.h
@@ -1,258 +1,293 @@
/*
* Copyright 1995-2018 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_RAND_LCL_H
# define HEADER_RAND_LCL_H
# include <openssl/aes.h>
# include <openssl/evp.h>
# include <openssl/sha.h>
# include <openssl/hmac.h>
# include <openssl/ec.h>
# include <openssl/rand_drbg.h>
+# include "internal/tsan_assist.h"
+
+# include "internal/numbers.h"
/* How many times to read the TSC as a randomness source. */
# define TSC_READ_COUNT 4
/* Maximum reseed intervals */
# define MAX_RESEED_INTERVAL (1 << 24)
# define MAX_RESEED_TIME_INTERVAL (1 << 20) /* approx. 12 days */
/* Default reseed intervals */
# define MASTER_RESEED_INTERVAL (1 << 8)
# define SLAVE_RESEED_INTERVAL (1 << 16)
# define MASTER_RESEED_TIME_INTERVAL (60*60) /* 1 hour */
# define SLAVE_RESEED_TIME_INTERVAL (7*60) /* 7 minutes */
-/* Max size of additional input and personalization string. */
-# define DRBG_MAX_LENGTH 4096
+/*
+ * Maximum input size for the DRBG (entropy, nonce, personalization string)
+ *
+ * NIST SP800 90Ar1 allows a maximum of (1 << 35) bits i.e., (1 << 32) bytes.
+ *
+ * We lower it to 'only' INT32_MAX bytes, which is equivalent to 2 gigabytes.
+ */
+# define DRBG_MAX_LENGTH INT32_MAX
+
+
/*
- * The quotient between max_{entropy,nonce}len and min_{entropy,nonce}len
+ * Maximum allocation size for RANDOM_POOL buffers
+ *
+ * The max_len value for the buffer provided to the rand_drbg_get_entropy()
+ * callback is currently 2^31 bytes (2 gigabytes), if a derivation function
+ * is used. Since this is much too large to be allocated, the rand_pool_new()
+ * function chooses more modest values as default pool length, bounded
+ * by RAND_POOL_MIN_LENGTH and RAND_POOL_MAX_LENGTH
*
- * The current factor is large enough that the RAND_POOL can store a
- * random input which has a lousy entropy rate of 0.0625 bits per byte.
- * This input will be sent through the derivation function which 'compresses'
- * the low quality input into a high quality output.
+ * The choice of the RAND_POOL_FACTOR is large enough such that the
+ * RAND_POOL can store a random input which has a lousy entropy rate of
+ * 8/256 (= 0.03125) bits per byte. This input will be sent through the
+ * derivation function which 'compresses' the low quality input into a
+ * high quality output.
+ *
+ * The factor 1.5 below is the pessimistic estimate for the extra amount
+ * of entropy required when no get_nonce() callback is defined.
+ */
+# define RAND_POOL_FACTOR 256
+# define RAND_POOL_MAX_LENGTH (RAND_POOL_FACTOR * \
+ 3 * (RAND_DRBG_STRENGTH / 16))
+/*
+ * = (RAND_POOL_FACTOR * \
+ * 1.5 * (RAND_DRBG_STRENGTH / 8))
*/
-# define DRBG_MINMAX_FACTOR 128
/* DRBG status values */
typedef enum drbg_status_e {
DRBG_UNINITIALISED,
DRBG_READY,
DRBG_ERROR
} DRBG_STATUS;
-/* intantiate */
+/* instantiate */
typedef int (*RAND_DRBG_instantiate_fn)(RAND_DRBG *ctx,
const unsigned char *ent,
size_t entlen,
const unsigned char *nonce,
size_t noncelen,
const unsigned char *pers,
size_t perslen);
/* reseed */
typedef int (*RAND_DRBG_reseed_fn)(RAND_DRBG *ctx,
const unsigned char *ent,
size_t entlen,
const unsigned char *adin,
size_t adinlen);
-/* generat output */
+/* generate output */
typedef int (*RAND_DRBG_generate_fn)(RAND_DRBG *ctx,
unsigned char *out,
size_t outlen,
const unsigned char *adin,
size_t adinlen);
/* uninstantiate */
typedef int (*RAND_DRBG_uninstantiate_fn)(RAND_DRBG *ctx);
/*
* The DRBG methods
*/
typedef struct rand_drbg_method_st {
RAND_DRBG_instantiate_fn instantiate;
RAND_DRBG_reseed_fn reseed;
RAND_DRBG_generate_fn generate;
RAND_DRBG_uninstantiate_fn uninstantiate;
} RAND_DRBG_METHOD;
/*
* The state of a DRBG AES-CTR.
*/
typedef struct rand_drbg_ctr_st {
EVP_CIPHER_CTX *ctx;
EVP_CIPHER_CTX *ctx_df;
const EVP_CIPHER *cipher;
size_t keylen;
unsigned char K[32];
unsigned char V[16];
/* Temporary block storage used by ctr_df */
unsigned char bltmp[16];
size_t bltmp_pos;
unsigned char KX[48];
} RAND_DRBG_CTR;
/*
* The 'random pool' acts as a dumb container for collecting random
* input from various entropy sources. The pool has no knowledge about
* whether its randomness is fed into a legacy RAND_METHOD via RAND_add()
* or into a new style RAND_DRBG. It is the callers duty to 1) initialize the
* random pool, 2) pass it to the polling callbacks, 3) seed the RNG, and
* 4) cleanup the random pool again.
*
* The random pool contains no locking mechanism because its scope and
* lifetime is intended to be restricted to a single stack frame.
*/
struct rand_pool_st {
unsigned char *buffer; /* points to the beginning of the random pool */
size_t len; /* current number of random bytes contained in the pool */
+ int attached; /* true pool was attached to existing buffer */
+
size_t min_len; /* minimum number of random bytes requested */
size_t max_len; /* maximum number of random bytes (allocated buffer size) */
size_t entropy; /* current entropy count in bits */
- size_t requested_entropy; /* requested entropy count in bits */
+ size_t entropy_requested; /* requested entropy count in bits */
};
/*
* The state of all types of DRBGs, even though we only have CTR mode
* right now.
*/
struct rand_drbg_st {
CRYPTO_RWLOCK *lock;
RAND_DRBG *parent;
int secure; /* 1: allocated on the secure heap, 0: otherwise */
int type; /* the nid of the underlying algorithm */
/*
* Stores the value of the rand_fork_count global as of when we last
- * reseeded. The DRG reseeds automatically whenever drbg->fork_count !=
+ * reseeded. The DRBG reseeds automatically whenever drbg->fork_count !=
* rand_fork_count. Used to provide fork-safety and reseed this DRBG in
* the child process.
*/
int fork_count;
unsigned short flags; /* various external flags */
/*
- * The random pool is used by RAND_add()/drbg_add() to attach random
+ * The random_data is used by RAND_add()/drbg_add() to attach random
* data to the global drbg, such that the rand_drbg_get_entropy() callback
* can pull it during instantiation and reseeding. This is necessary to
* reconcile the different philosophies of the RAND and the RAND_DRBG
* with respect to how randomness is added to the RNG during reseeding
* (see PR #4328).
*/
- struct rand_pool_st *pool;
+ struct rand_pool_st *seed_pool;
+
+ /*
+ * Auxiliary pool for additional data.
+ */
+ struct rand_pool_st *adin_pool;
/*
* The following parameters are setup by the per-type "init" function.
*
* Currently the only type is CTR_DRBG, its init function is drbg_ctr_init().
*
* The parameters are closely related to the ones described in
* section '10.2.1 CTR_DRBG' of [NIST SP 800-90Ar1], with one
* crucial difference: In the NIST standard, all counts are given
* in bits, whereas in OpenSSL entropy counts are given in bits
* and buffer lengths are given in bytes.
*
* Since this difference has lead to some confusion in the past,
* (see [GitHub Issue #2443], formerly [rt.openssl.org #4055])
* the 'len' suffix has been added to all buffer sizes for
* clarification.
*/
int strength;
size_t max_request;
size_t min_entropylen, max_entropylen;
size_t min_noncelen, max_noncelen;
size_t max_perslen, max_adinlen;
/* Counts the number of generate requests since the last reseed. */
- unsigned int generate_counter;
+ unsigned int reseed_gen_counter;
/*
* Maximum number of generate requests until a reseed is required.
* This value is ignored if it is zero.
*/
unsigned int reseed_interval;
/* Stores the time when the last reseeding occurred */
time_t reseed_time;
/*
* Specifies the maximum time interval (in seconds) between reseeds.
* This value is ignored if it is zero.
*/
time_t reseed_time_interval;
/*
* Counts the number of reseeds since instantiation.
* This value is ignored if it is zero.
*
* This counter is used only for seed propagation from the <master> DRBG
* to its two children, the <public> and <private> DRBG. This feature is
* very special and its sole purpose is to ensure that any randomness which
* is added by RAND_add() or RAND_seed() will have an immediate effect on
* the output of RAND_bytes() resp. RAND_priv_bytes().
*/
- unsigned int reseed_counter;
+ TSAN_QUALIFIER unsigned int reseed_prop_counter;
+ unsigned int reseed_next_counter;
size_t seedlen;
DRBG_STATUS state;
/* Application data, mainly used in the KATs. */
CRYPTO_EX_DATA ex_data;
/* Implementation specific data (currently only one implementation) */
union {
RAND_DRBG_CTR ctr;
} data;
/* Implementation specific methods */
RAND_DRBG_METHOD *meth;
/* Callback functions. See comments in rand_lib.c */
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;
};
/* The global RAND method, and the global buffer and DRBG instance. */
extern RAND_METHOD rand_meth;
/*
* A "generation count" of forks. Incremented in the child process after a
* fork. Since rand_fork_count is increment-only, and only ever written to in
* the child process of the fork, which is guaranteed to be single-threaded, no
* locking is needed for normal (read) accesses; the rest of pthread fork
* processing is assumed to introduce the necessary memory barriers. Sibling
* children of a given parent will produce duplicate values, but this is not
* problematic because the reseeding process pulls input from the system CSPRNG
* and/or other global sources, so the siblings will end up generating
* different output streams.
*/
extern int rand_fork_count;
/* DRBG helpers */
int rand_drbg_restart(RAND_DRBG *drbg,
const unsigned char *buffer, size_t len, size_t entropy);
-
+size_t rand_drbg_seedlen(RAND_DRBG *drbg);
/* locking api */
int rand_drbg_lock(RAND_DRBG *drbg);
int rand_drbg_unlock(RAND_DRBG *drbg);
int rand_drbg_enable_locking(RAND_DRBG *drbg);
/* initializes the AES-CTR DRBG implementation */
int drbg_ctr_init(RAND_DRBG *drbg);
#endif
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index e9bc9522101c..d8639c4a03f3 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -1,799 +1,859 @@
/*
* Copyright 1995-2018 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_cleaning_up = 0;
+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) {
/*
* 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;
}
- pool = rand_pool_new(entropy, min_len, max_len);
- if (pool == NULL)
- return 0;
-
- if (drbg->pool) {
- rand_pool_add(pool,
- rand_pool_buffer(drbg->pool),
- rand_pool_length(drbg->pool),
- rand_pool_entropy(drbg->pool));
- rand_pool_free(drbg->pool);
- drbg->pool = NULL;
+ 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) {
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:
- rand_pool_free(pool);
+ 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)
{
- OPENSSL_secure_clear_free(out, 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 };
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(unsigned char **pout, size_t max_len)
+size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout)
{
size_t ret = 0;
- RAND_POOL *pool;
-
- pool = rand_pool_new(0, 0, max_len);
- if (pool == NULL)
- return 0;
if (rand_pool_add_additional_data(pool) == 0)
goto err;
ret = rand_pool_length(pool);
*pout = rand_pool_detach(pool);
err:
- rand_pool_free(pool);
-
return ret;
}
-void rand_drbg_cleanup_additional_data(unsigned char *out, size_t outlen)
+void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out)
{
- OPENSSL_secure_clear_free(out, outlen);
+ 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_cleaning_up && !rand_pool_init())
+ if (!rand_pool_init())
goto err3;
+ rand_inited = 1;
return 1;
err3:
- rand_pool_cleanup();
+ 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;
- rand_cleaning_up = 1;
+ 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)
{
- rand_pool_keep_random_devices_open(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,
- DRBG_MINMAX_FACTOR * (RAND_DRBG_STRENGTH / 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, size_t min_len, size_t max_len)
+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);
- goto err;
+ return NULL;
}
pool->min_len = min_len;
- pool->max_len = max_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->requested_entropy = entropy;
+ 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;
- OPENSSL_secure_clear_free(pool->buffer, pool->max_len);
+ /*
+ * 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().
+ * 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->requested_entropy)
+ 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->requested_entropy)
- return pool->requested_entropy - pool->entropy;
+ 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 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 9c62a04ebf89..9d8ffdd53796 100644
--- a/crypto/rand/rand_unix.c
+++ b/crypto/rand/rand_unix.c
@@ -1,688 +1,686 @@
/*
* Copyright 1995-2018 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>
#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_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
|| defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \
|| defined(OPENSSL_SYS_UEFI))
-static ssize_t syscall_random(void *buf, size_t buflen);
-
# 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 * DRBG_MINMAX_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^13
+ * 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);
# 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_NONE) && defined(OPENSSL_RAND_SEED_DEVRANDOM)
+# 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;
}
-static void open_random_devices(void)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(random_devices); i++)
- (void)get_random_device(i);
-}
-
int rand_pool_init(void)
{
size_t i;
for (i = 0; i < OSSL_NELEM(random_devices); i++)
random_devices[i].fd = -1;
- open_random_devices();
+
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)
- open_random_devices();
- else
+ if (!keep)
rand_pool_cleanup();
+
keep_random_devices_open = keep;
}
-# else /* defined(OPENSSL_RAND_SEED_NONE)
- * || !defined(OPENSSL_RAND_SEED_DEVRANDOM)
- */
+# 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_NONE)
- * && defined(OPENSSL_RAND_SEED_DEVRANDOM)
- */
+# 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)
{
-# ifdef OPENSSL_RAND_SEED_NONE
+# 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;
-# ifdef OPENSSL_RAND_SEED_GETRANDOM
+# 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
-# ifdef OPENSSL_RAND_SEED_DEVRANDOM
+# if defined(OPENSSL_RAND_SEED_DEVRANDOM)
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
{
size_t i;
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
-# ifdef OPENSSL_RAND_SEED_RDTSC
+# if defined(OPENSSL_RAND_SEED_RDTSC)
entropy_available = rand_acquire_entropy_from_tsc(pool);
if (entropy_available > 0)
return entropy_available;
# endif
-# ifdef OPENSSL_RAND_SEED_RDCPU
+# if defined(OPENSSL_RAND_SEED_RDCPU)
entropy_available = rand_acquire_entropy_from_cpu(pool);
if (entropy_available > 0)
return entropy_available;
# endif
-# ifdef OPENSSL_RAND_SEED_EGD
+# 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 whith high probability for
+ * 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 c652ddcf1e6c..1b737d1ba2ba 100644
--- a/crypto/rand/randfile.c
+++ b/crypto/rand/randfile.c
@@ -1,296 +1,314 @@
/*
* Copyright 1995-2018 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_FILE_SIZE 1024
+#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)
{
- unsigned char buf[RAND_FILE_SIZE];
+ /*
+ * 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 (!S_ISREG(sb.st_mode) && bytes < 0)
- bytes = 256;
+ 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_FILE_SIZE) ? (int)bytes : RAND_FILE_SIZE;
+ n = (bytes <= RAND_LOAD_BUF_SIZE) ? (int)bytes : RAND_BUF_SIZE;
else
- n = RAND_FILE_SIZE;
+ 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_FILE_SIZE];
+ 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_FILE_SIZE, out);
+ ret = fwrite(buf, 1, RAND_BUF_SIZE, out);
fclose(out);
- OPENSSL_cleanse(buf, RAND_FILE_SIZE);
+ 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)
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 (OPENSSL_issetugid() != 0) {
- use_randfile = 0;
- } else if ((s = getenv("RANDFILE")) == NULL || *s == '\0') {
+ if ((s = ossl_safe_getenv("RANDFILE")) == NULL || *s == '\0') {
use_randfile = 0;
- s = getenv("HOME");
+ 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/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index 72d1b5e0715d..49c34b7c36c9 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -1,479 +1,479 @@
/*
* Copyright 1995-2018 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/refcount.h"
#include "internal/bn_int.h"
#include <openssl/engine.h>
#include <openssl/evp.h>
#include "internal/evp_int.h"
#include "rsa_locl.h"
RSA *RSA_new(void)
{
return RSA_new_method(NULL);
}
const RSA_METHOD *RSA_get_method(const RSA *rsa)
{
return rsa->meth;
}
int RSA_set_method(RSA *rsa, const RSA_METHOD *meth)
{
/*
* NB: The caller is specifically setting a method, so it's not up to us
* to deal with which ENGINE it comes from.
*/
const RSA_METHOD *mtmp;
mtmp = rsa->meth;
if (mtmp->finish)
mtmp->finish(rsa);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(rsa->engine);
rsa->engine = NULL;
#endif
rsa->meth = meth;
if (meth->init)
meth->init(rsa);
return 1;
}
RSA *RSA_new_method(ENGINE *engine)
{
RSA *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
ret->meth = RSA_get_default_method();
#ifndef OPENSSL_NO_ENGINE
ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
if (engine) {
if (!ENGINE_init(engine)) {
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB);
goto err;
}
ret->engine = engine;
} else {
ret->engine = ENGINE_get_default_RSA();
}
if (ret->engine) {
ret->meth = ENGINE_get_RSA(ret->engine);
if (ret->meth == NULL) {
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB);
goto err;
}
}
#endif
ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data)) {
goto err;
}
if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_INIT_FAIL);
goto err;
}
return ret;
err:
RSA_free(ret);
return NULL;
}
void RSA_free(RSA *r)
{
int i;
if (r == NULL)
return;
CRYPTO_DOWN_REF(&r->references, &i, r->lock);
REF_PRINT_COUNT("RSA", r);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
if (r->meth != NULL && r->meth->finish != NULL)
r->meth->finish(r);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(r->engine);
#endif
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
CRYPTO_THREAD_lock_free(r->lock);
- BN_clear_free(r->n);
- BN_clear_free(r->e);
+ BN_free(r->n);
+ BN_free(r->e);
BN_clear_free(r->d);
BN_clear_free(r->p);
BN_clear_free(r->q);
BN_clear_free(r->dmp1);
BN_clear_free(r->dmq1);
BN_clear_free(r->iqmp);
RSA_PSS_PARAMS_free(r->pss);
sk_RSA_PRIME_INFO_pop_free(r->prime_infos, rsa_multip_info_free);
BN_BLINDING_free(r->blinding);
BN_BLINDING_free(r->mt_blinding);
OPENSSL_free(r->bignum_data);
OPENSSL_free(r);
}
int RSA_up_ref(RSA *r)
{
int i;
if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0)
return 0;
REF_PRINT_COUNT("RSA", r);
REF_ASSERT_ISNT(i < 2);
return i > 1 ? 1 : 0;
}
int RSA_set_ex_data(RSA *r, int idx, void *arg)
{
return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
}
void *RSA_get_ex_data(const RSA *r, int idx)
{
return CRYPTO_get_ex_data(&r->ex_data, idx);
}
int RSA_security_bits(const RSA *rsa)
{
int bits = BN_num_bits(rsa->n);
if (rsa->version == RSA_ASN1_VERSION_MULTI) {
/* This ought to mean that we have private key at hand. */
int ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos);
if (ex_primes <= 0 || (ex_primes + 2) > rsa_multip_cap(bits))
return 0;
}
return BN_security_bits(bits, -1);
}
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
{
/* If the fields n and e in r are NULL, the corresponding input
* parameters MUST be non-NULL for n and e. d may be
* left NULL (in case only the public key is used).
*/
if ((r->n == NULL && n == NULL)
|| (r->e == NULL && e == NULL))
return 0;
if (n != NULL) {
BN_free(r->n);
r->n = n;
}
if (e != NULL) {
BN_free(r->e);
r->e = e;
}
if (d != NULL) {
- BN_free(r->d);
+ BN_clear_free(r->d);
r->d = d;
}
return 1;
}
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
{
/* If the fields p and q in r are NULL, the corresponding input
* parameters MUST be non-NULL.
*/
if ((r->p == NULL && p == NULL)
|| (r->q == NULL && q == NULL))
return 0;
if (p != NULL) {
- BN_free(r->p);
+ BN_clear_free(r->p);
r->p = p;
}
if (q != NULL) {
- BN_free(r->q);
+ BN_clear_free(r->q);
r->q = q;
}
return 1;
}
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
{
/* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
* parameters MUST be non-NULL.
*/
if ((r->dmp1 == NULL && dmp1 == NULL)
|| (r->dmq1 == NULL && dmq1 == NULL)
|| (r->iqmp == NULL && iqmp == NULL))
return 0;
if (dmp1 != NULL) {
- BN_free(r->dmp1);
+ BN_clear_free(r->dmp1);
r->dmp1 = dmp1;
}
if (dmq1 != NULL) {
- BN_free(r->dmq1);
+ BN_clear_free(r->dmq1);
r->dmq1 = dmq1;
}
if (iqmp != NULL) {
- BN_free(r->iqmp);
+ BN_clear_free(r->iqmp);
r->iqmp = iqmp;
}
return 1;
}
/*
* Is it better to export RSA_PRIME_INFO structure
* and related functions to let user pass a triplet?
*/
int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
BIGNUM *coeffs[], int pnum)
{
STACK_OF(RSA_PRIME_INFO) *prime_infos, *old = NULL;
RSA_PRIME_INFO *pinfo;
int i;
if (primes == NULL || exps == NULL || coeffs == NULL || pnum == 0)
return 0;
prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
if (prime_infos == NULL)
return 0;
if (r->prime_infos != NULL)
old = r->prime_infos;
for (i = 0; i < pnum; i++) {
pinfo = rsa_multip_info_new();
if (pinfo == NULL)
goto err;
if (primes[i] != NULL && exps[i] != NULL && coeffs[i] != NULL) {
BN_free(pinfo->r);
BN_free(pinfo->d);
BN_free(pinfo->t);
pinfo->r = primes[i];
pinfo->d = exps[i];
pinfo->t = coeffs[i];
} else {
rsa_multip_info_free(pinfo);
goto err;
}
(void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
}
r->prime_infos = prime_infos;
if (!rsa_multip_calc_product(r)) {
r->prime_infos = old;
goto err;
}
if (old != NULL) {
/*
* This is hard to deal with, since the old infos could
* also be set by this function and r, d, t should not
* be freed in that case. So currently, stay consistent
* with other *set0* functions: just free it...
*/
sk_RSA_PRIME_INFO_pop_free(old, rsa_multip_info_free);
}
r->version = RSA_ASN1_VERSION_MULTI;
return 1;
err:
/* r, d, t should not be freed */
sk_RSA_PRIME_INFO_pop_free(prime_infos, rsa_multip_info_free_ex);
return 0;
}
void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
{
if (n != NULL)
*n = r->n;
if (e != NULL)
*e = r->e;
if (d != NULL)
*d = r->d;
}
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
{
if (p != NULL)
*p = r->p;
if (q != NULL)
*q = r->q;
}
int RSA_get_multi_prime_extra_count(const RSA *r)
{
int pnum;
pnum = sk_RSA_PRIME_INFO_num(r->prime_infos);
if (pnum <= 0)
pnum = 0;
return pnum;
}
int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[])
{
int pnum, i;
RSA_PRIME_INFO *pinfo;
if ((pnum = RSA_get_multi_prime_extra_count(r)) == 0)
return 0;
/*
* return other primes
* it's caller's responsibility to allocate oth_primes[pnum]
*/
for (i = 0; i < pnum; i++) {
pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i);
primes[i] = pinfo->r;
}
return 1;
}
void RSA_get0_crt_params(const RSA *r,
const BIGNUM **dmp1, const BIGNUM **dmq1,
const BIGNUM **iqmp)
{
if (dmp1 != NULL)
*dmp1 = r->dmp1;
if (dmq1 != NULL)
*dmq1 = r->dmq1;
if (iqmp != NULL)
*iqmp = r->iqmp;
}
int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
const BIGNUM *coeffs[])
{
int pnum;
if ((pnum = RSA_get_multi_prime_extra_count(r)) == 0)
return 0;
/* return other primes */
if (exps != NULL || coeffs != NULL) {
RSA_PRIME_INFO *pinfo;
int i;
/* it's the user's job to guarantee the buffer length */
for (i = 0; i < pnum; i++) {
pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i);
if (exps != NULL)
exps[i] = pinfo->d;
if (coeffs != NULL)
coeffs[i] = pinfo->t;
}
}
return 1;
}
const BIGNUM *RSA_get0_n(const RSA *r)
{
return r->n;
}
const BIGNUM *RSA_get0_e(const RSA *r)
{
return r->e;
}
const BIGNUM *RSA_get0_d(const RSA *r)
{
return r->d;
}
const BIGNUM *RSA_get0_p(const RSA *r)
{
return r->p;
}
const BIGNUM *RSA_get0_q(const RSA *r)
{
return r->q;
}
const BIGNUM *RSA_get0_dmp1(const RSA *r)
{
return r->dmp1;
}
const BIGNUM *RSA_get0_dmq1(const RSA *r)
{
return r->dmq1;
}
const BIGNUM *RSA_get0_iqmp(const RSA *r)
{
return r->iqmp;
}
void RSA_clear_flags(RSA *r, int flags)
{
r->flags &= ~flags;
}
int RSA_test_flags(const RSA *r, int flags)
{
return r->flags & flags;
}
void RSA_set_flags(RSA *r, int flags)
{
r->flags |= flags;
}
int RSA_get_version(RSA *r)
{
/* { two-prime(0), multi(1) } */
return r->version;
}
ENGINE *RSA_get0_engine(const RSA *r)
{
return r->engine;
}
int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2)
{
/* If key type not RSA or RSA-PSS return error */
if (ctx != NULL && ctx->pmeth != NULL
&& ctx->pmeth->pkey_id != EVP_PKEY_RSA
&& ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
return -1;
return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, p1, p2);
}
diff --git a/crypto/rsa/rsa_meth.c b/crypto/rsa/rsa_meth.c
index f5880a73d0f7..def19f375f92 100644
--- a/crypto/rsa/rsa_meth.c
+++ b/crypto/rsa/rsa_meth.c
@@ -1,287 +1,287 @@
/*
* Copyright 2016-2018 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 "rsa_locl.h"
#include <openssl/err.h>
RSA_METHOD *RSA_meth_new(const char *name, int flags)
{
RSA_METHOD *meth = OPENSSL_zalloc(sizeof(*meth));
if (meth != NULL) {
meth->flags = flags;
meth->name = OPENSSL_strdup(name);
if (meth->name != NULL)
return meth;
OPENSSL_free(meth);
}
RSAerr(RSA_F_RSA_METH_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
void RSA_meth_free(RSA_METHOD *meth)
{
if (meth != NULL) {
OPENSSL_free(meth->name);
OPENSSL_free(meth);
}
}
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)
{
RSA_METHOD *ret = OPENSSL_malloc(sizeof(*ret));
if (ret != NULL) {
memcpy(ret, meth, sizeof(*meth));
ret->name = OPENSSL_strdup(meth->name);
if (ret->name != NULL)
return ret;
OPENSSL_free(ret);
}
RSAerr(RSA_F_RSA_METH_DUP, ERR_R_MALLOC_FAILURE);
return NULL;
}
const char *RSA_meth_get0_name(const RSA_METHOD *meth)
{
return meth->name;
}
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
{
char *tmpname = OPENSSL_strdup(name);
if (tmpname == NULL) {
RSAerr(RSA_F_RSA_METH_SET1_NAME, ERR_R_MALLOC_FAILURE);
return 0;
}
OPENSSL_free(meth->name);
meth->name = tmpname;
return 1;
}
int RSA_meth_get_flags(const RSA_METHOD *meth)
{
return meth->flags;
}
int RSA_meth_set_flags(RSA_METHOD *meth, int flags)
{
meth->flags = flags;
return 1;
}
void *RSA_meth_get0_app_data(const RSA_METHOD *meth)
{
return meth->app_data;
}
int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data)
{
meth->app_data = app_data;
return 1;
}
int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
return meth->rsa_pub_enc;
}
int RSA_meth_set_pub_enc(RSA_METHOD *meth,
int (*pub_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding))
{
meth->rsa_pub_enc = pub_enc;
return 1;
}
int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
return meth->rsa_pub_dec;
}
int RSA_meth_set_pub_dec(RSA_METHOD *meth,
int (*pub_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding))
{
meth->rsa_pub_dec = pub_dec;
return 1;
}
int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
return meth->rsa_priv_enc;
}
int RSA_meth_set_priv_enc(RSA_METHOD *meth,
int (*priv_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding))
{
meth->rsa_priv_enc = priv_enc;
return 1;
}
int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
return meth->rsa_priv_dec;
}
int RSA_meth_set_priv_dec(RSA_METHOD *meth,
int (*priv_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding))
{
meth->rsa_priv_dec = priv_dec;
return 1;
}
/* Can be null */
int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth))
- (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+ (BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx)
{
return meth->rsa_mod_exp;
}
int RSA_meth_set_mod_exp(RSA_METHOD *meth,
- int (*mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+ int (*mod_exp) (BIGNUM *r0, const BIGNUM *i, RSA *rsa,
BN_CTX *ctx))
{
meth->rsa_mod_exp = mod_exp;
return 1;
}
/* Can be null */
int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth))
(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
{
return meth->bn_mod_exp;
}
int RSA_meth_set_bn_mod_exp(RSA_METHOD *meth,
int (*bn_mod_exp) (BIGNUM *r,
const BIGNUM *a,
const BIGNUM *p,
const BIGNUM *m,
BN_CTX *ctx,
BN_MONT_CTX *m_ctx))
{
meth->bn_mod_exp = bn_mod_exp;
return 1;
}
/* called at new */
int (*RSA_meth_get_init(const RSA_METHOD *meth)) (RSA *rsa)
{
return meth->init;
}
int RSA_meth_set_init(RSA_METHOD *meth, int (*init) (RSA *rsa))
{
meth->init = init;
return 1;
}
/* called at free */
int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa)
{
return meth->finish;
}
int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa))
{
meth->finish = finish;
return 1;
}
int (*RSA_meth_get_sign(const RSA_METHOD *meth))
(int type,
const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,
const RSA *rsa)
{
return meth->rsa_sign;
}
int RSA_meth_set_sign(RSA_METHOD *meth,
int (*sign) (int type, const unsigned char *m,
unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,
const RSA *rsa))
{
meth->rsa_sign = sign;
return 1;
}
int (*RSA_meth_get_verify(const RSA_METHOD *meth))
(int dtype, const unsigned char *m,
unsigned int m_length, const unsigned char *sigbuf,
unsigned int siglen, const RSA *rsa)
{
return meth->rsa_verify;
}
int RSA_meth_set_verify(RSA_METHOD *meth,
int (*verify) (int dtype, const unsigned char *m,
unsigned int m_length,
const unsigned char *sigbuf,
unsigned int siglen, const RSA *rsa))
{
meth->rsa_verify = verify;
return 1;
}
int (*RSA_meth_get_keygen(const RSA_METHOD *meth))
(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
{
return meth->rsa_keygen;
}
int RSA_meth_set_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits, BIGNUM *e,
BN_GENCB *cb))
{
meth->rsa_keygen = keygen;
return 1;
}
int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth))
(RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb)
{
return meth->rsa_multi_prime_keygen;
}
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb))
{
meth->rsa_multi_prime_keygen = keygen;
return 1;
}
diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c
index d581777eec9b..2b1b006c2801 100644
--- a/crypto/rsa/rsa_ossl.c
+++ b/crypto/rsa/rsa_ossl.c
@@ -1,970 +1,971 @@
/*
* Copyright 1995-2018 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"
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_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_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->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;
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_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;
}
if (r < 0)
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
err:
if (ctx != NULL)
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_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)
- /* r0 = r0 * iqmp mod 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/sha/asm/keccak1600-s390x.pl b/crypto/sha/asm/keccak1600-s390x.pl
index 3bce19be9ea4..1184cf233eba 100755
--- a/crypto/sha/asm/keccak1600-s390x.pl
+++ b/crypto/sha/asm/keccak1600-s390x.pl
@@ -1,560 +1,560 @@
#!/usr/bin/env perl
# Copyright 2017-2018 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/.
# ====================================================================
#
# Keccak-1600 for s390x.
#
# June 2017.
#
# Below code is [lane complementing] KECCAK_2X implementation (see
# sha/keccak1600.c) with C[5] and D[5] held in register bank. Though
# instead of actually unrolling the loop pair-wise I simply flip
# pointers to T[][] and A[][] at the end of round. Since number of
# rounds is even, last round writes to A[][] and everything works out.
# In the nutshell it's transliteration of x86_64 module, because both
# architectures have similar capabilities/limitations. Performance
# measurement is problematic as I don't have access to an idle system.
# It looks like z13 processes one byte [out of long message] in ~14
# cycles. At least the result is consistent with estimate based on
# amount of instruction and assumed instruction issue rate. It's ~2.5x
# faster than compiler-generated code.
$flavour = shift;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
$g="";
} else {
$SIZE_T=8;
$g="g";
}
while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
open STDOUT,">$output";
my @A = map([ 8*$_, 8*($_+1), 8*($_+2), 8*($_+3), 8*($_+4) ], (0,5,10,15,20));
my @C = map("%r$_",(0,1,5..7));
my @D = map("%r$_",(8..12));
my @T = map("%r$_",(13..14));
my ($src,$dst,$iotas) = map("%r$_",(2..4));
my $sp = "%r15";
$stdframe=16*$SIZE_T+4*8;
$frame=$stdframe+25*8;
my @rhotates = ([ 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 ]);
{ my @C = @C; # copy, because we mess them up...
my @D = @D;
$code.=<<___;
.text
.type __KeccakF1600,\@function
.align 32
__KeccakF1600:
st${g} %r14,$SIZE_T*14($sp)
lg @C[0],$A[4][0]($src)
lg @C[1],$A[4][1]($src)
lg @C[2],$A[4][2]($src)
lg @C[3],$A[4][3]($src)
lg @C[4],$A[4][4]($src)
larl $iotas,iotas
j .Loop
.align 16
.Loop:
lg @D[0],$A[0][0]($src)
lg @D[1],$A[1][1]($src)
lg @D[2],$A[2][2]($src)
lg @D[3],$A[3][3]($src)
xgr @C[0],@D[0]
xg @C[1],$A[0][1]($src)
xg @C[2],$A[0][2]($src)
xg @C[3],$A[0][3]($src)
lgr @D[4],@C[4]
xg @C[4],$A[0][4]($src)
xg @C[0],$A[1][0]($src)
xgr @C[1],@D[1]
xg @C[2],$A[1][2]($src)
xg @C[3],$A[1][3]($src)
xg @C[4],$A[1][4]($src)
xg @C[0],$A[2][0]($src)
xg @C[1],$A[2][1]($src)
xgr @C[2],@D[2]
xg @C[3],$A[2][3]($src)
xg @C[4],$A[2][4]($src)
xg @C[0],$A[3][0]($src)
xg @C[1],$A[3][1]($src)
xg @C[2],$A[3][2]($src)
xgr @C[3],@D[3]
xg @C[4],$A[3][4]($src)
lgr @T[0],@C[2]
rllg @C[2],@C[2],1
xgr @C[2],@C[0] # D[1] = ROL64(C[2], 1) ^ C[0]
rllg @C[0],@C[0],1
xgr @C[0],@C[3] # D[4] = ROL64(C[0], 1) ^ C[3]
rllg @C[3],@C[3],1
xgr @C[3],@C[1] # D[2] = ROL64(C[3], 1) ^ C[1]
rllg @C[1],@C[1],1
xgr @C[1],@C[4] # D[0] = ROL64(C[1], 1) ^ C[4]
rllg @C[4],@C[4],1
xgr @C[4],@T[0] # D[3] = ROL64(C[4], 1) ^ C[2]
___
(@D[0..4], @C) = (@C[1..4,0], @D);
$code.=<<___;
xgr @C[1],@D[1]
xgr @C[2],@D[2]
xgr @C[3],@D[3]
rllg @C[1],@C[1],$rhotates[1][1]
xgr @C[4],@D[4]
rllg @C[2],@C[2],$rhotates[2][2]
xgr @C[0],@D[0]
lgr @T[0],@C[1]
ogr @C[1],@C[2]
rllg @C[3],@C[3],$rhotates[3][3]
xgr @C[1],@C[0] # C[0] ^ ( C[1] | C[2])
rllg @C[4],@C[4],$rhotates[4][4]
xg @C[1],0($iotas)
la $iotas,8($iotas)
stg @C[1],$A[0][0]($dst) # R[0][0] = C[0] ^ ( C[1] | C[2]) ^ iotas[i]
lgr @T[1],@C[4]
ngr @C[4],@C[3]
lghi @C[1],-1 # no 'not' instruction :-(
xgr @C[4],@C[2] # C[2] ^ ( C[4] & C[3])
xgr @C[2],@C[1] # not @C[2]
stg @C[4],$A[0][2]($dst) # R[0][2] = C[2] ^ ( C[4] & C[3])
ogr @C[2],@C[3]
xgr @C[2],@T[0] # C[1] ^ (~C[2] | C[3])
ngr @T[0],@C[0]
stg @C[2],$A[0][1]($dst) # R[0][1] = C[1] ^ (~C[2] | C[3])
xgr @T[0],@T[1] # C[4] ^ ( C[1] & C[0])
ogr @T[1],@C[0]
stg @T[0],$A[0][4]($dst) # R[0][4] = C[4] ^ ( C[1] & C[0])
xgr @T[1],@C[3] # C[3] ^ ( C[4] | C[0])
stg @T[1],$A[0][3]($dst) # R[0][3] = C[3] ^ ( C[4] | C[0])
lg @C[0],$A[0][3]($src)
lg @C[4],$A[4][2]($src)
lg @C[3],$A[3][1]($src)
lg @C[1],$A[1][4]($src)
lg @C[2],$A[2][0]($src)
xgr @C[0],@D[3]
xgr @C[4],@D[2]
rllg @C[0],@C[0],$rhotates[0][3]
xgr @C[3],@D[1]
rllg @C[4],@C[4],$rhotates[4][2]
xgr @C[1],@D[4]
rllg @C[3],@C[3],$rhotates[3][1]
xgr @C[2],@D[0]
lgr @T[0],@C[0]
ogr @C[0],@C[4]
rllg @C[1],@C[1],$rhotates[1][4]
xgr @C[0],@C[3] # C[3] ^ (C[0] | C[4])
rllg @C[2],@C[2],$rhotates[2][0]
stg @C[0],$A[1][3]($dst) # R[1][3] = C[3] ^ (C[0] | C[4])
lgr @T[1],@C[1]
ngr @C[1],@T[0]
lghi @C[0],-1 # no 'not' instruction :-(
xgr @C[1],@C[4] # C[4] ^ (C[1] & C[0])
xgr @C[4],@C[0] # not @C[4]
stg @C[1],$A[1][4]($dst) # R[1][4] = C[4] ^ (C[1] & C[0])
ogr @C[4],@C[3]
xgr @C[4],@C[2] # C[2] ^ (~C[4] | C[3])
ngr @C[3],@C[2]
stg @C[4],$A[1][2]($dst) # R[1][2] = C[2] ^ (~C[4] | C[3])
xgr @C[3],@T[1] # C[1] ^ (C[3] & C[2])
ogr @T[1],@C[2]
stg @C[3],$A[1][1]($dst) # R[1][1] = C[1] ^ (C[3] & C[2])
xgr @T[1],@T[0] # C[0] ^ (C[1] | C[2])
stg @T[1],$A[1][0]($dst) # R[1][0] = C[0] ^ (C[1] | C[2])
lg @C[2],$A[2][3]($src)
lg @C[3],$A[3][4]($src)
lg @C[1],$A[1][2]($src)
lg @C[4],$A[4][0]($src)
lg @C[0],$A[0][1]($src)
xgr @C[2],@D[3]
xgr @C[3],@D[4]
rllg @C[2],@C[2],$rhotates[2][3]
xgr @C[1],@D[2]
rllg @C[3],@C[3],$rhotates[3][4]
xgr @C[4],@D[0]
rllg @C[1],@C[1],$rhotates[1][2]
xgr @C[0],@D[1]
lgr @T[0],@C[2]
ngr @C[2],@C[3]
rllg @C[4],@C[4],$rhotates[4][0]
xgr @C[2],@C[1] # C[1] ^ ( C[2] & C[3])
lghi @T[1],-1 # no 'not' instruction :-(
stg @C[2],$A[2][1]($dst) # R[2][1] = C[1] ^ ( C[2] & C[3])
xgr @C[3],@T[1] # not @C[3]
lgr @T[1],@C[4]
ngr @C[4],@C[3]
rllg @C[0],@C[0],$rhotates[0][1]
xgr @C[4],@T[0] # C[2] ^ ( C[4] & ~C[3])
ogr @T[0],@C[1]
stg @C[4],$A[2][2]($dst) # R[2][2] = C[2] ^ ( C[4] & ~C[3])
xgr @T[0],@C[0] # C[0] ^ ( C[2] | C[1])
ngr @C[1],@C[0]
stg @T[0],$A[2][0]($dst) # R[2][0] = C[0] ^ ( C[2] | C[1])
xgr @C[1],@T[1] # C[4] ^ ( C[1] & C[0])
ogr @C[0],@T[1]
stg @C[1],$A[2][4]($dst) # R[2][4] = C[4] ^ ( C[1] & C[0])
xgr @C[0],@C[3] # ~C[3] ^ ( C[0] | C[4])
stg @C[0],$A[2][3]($dst) # R[2][3] = ~C[3] ^ ( C[0] | C[4])
lg @C[2],$A[2][1]($src)
lg @C[3],$A[3][2]($src)
lg @C[1],$A[1][0]($src)
lg @C[4],$A[4][3]($src)
lg @C[0],$A[0][4]($src)
xgr @C[2],@D[1]
xgr @C[3],@D[2]
rllg @C[2],@C[2],$rhotates[2][1]
xgr @C[1],@D[0]
rllg @C[3],@C[3],$rhotates[3][2]
xgr @C[4],@D[3]
rllg @C[1],@C[1],$rhotates[1][0]
xgr @C[0],@D[4]
rllg @C[4],@C[4],$rhotates[4][3]
lgr @T[0],@C[2]
ogr @C[2],@C[3]
lghi @T[1],-1 # no 'not' instruction :-(
xgr @C[2],@C[1] # C[1] ^ ( C[2] | C[3])
xgr @C[3],@T[1] # not @C[3]
stg @C[2],$A[3][1]($dst) # R[3][1] = C[1] ^ ( C[2] | C[3])
lgr @T[1],@C[4]
ogr @C[4],@C[3]
rllg @C[0],@C[0],$rhotates[0][4]
xgr @C[4],@T[0] # C[2] ^ ( C[4] | ~C[3])
ngr @T[0],@C[1]
stg @C[4],$A[3][2]($dst) # R[3][2] = C[2] ^ ( C[4] | ~C[3])
xgr @T[0],@C[0] # C[0] ^ ( C[2] & C[1])
ogr @C[1],@C[0]
stg @T[0],$A[3][0]($dst) # R[3][0] = C[0] ^ ( C[2] & C[1])
xgr @C[1],@T[1] # C[4] ^ ( C[1] | C[0])
ngr @C[0],@T[1]
stg @C[1],$A[3][4]($dst) # R[3][4] = C[4] ^ ( C[1] | C[0])
xgr @C[0],@C[3] # ~C[3] ^ ( C[0] & C[4])
stg @C[0],$A[3][3]($dst) # R[3][3] = ~C[3] ^ ( C[0] & C[4])
xg @D[2],$A[0][2]($src)
xg @D[3],$A[1][3]($src)
xg @D[1],$A[4][1]($src)
xg @D[4],$A[2][4]($src)
xgr $dst,$src # xchg $dst,$src
rllg @D[2],@D[2],$rhotates[0][2]
xg @D[0],$A[3][0]($src)
rllg @D[3],@D[3],$rhotates[1][3]
xgr $src,$dst
rllg @D[1],@D[1],$rhotates[4][1]
xgr $dst,$src
rllg @D[4],@D[4],$rhotates[2][4]
___
@C = @D[2..4,0,1];
$code.=<<___;
lgr @T[0],@C[0]
ngr @C[0],@C[1]
lghi @T[1],-1 # no 'not' instruction :-(
xgr @C[0],@C[4] # C[4] ^ ( C[0] & C[1])
xgr @C[1],@T[1] # not @C[1]
stg @C[0],$A[4][4]($src) # R[4][4] = C[4] ^ ( C[0] & C[1])
lgr @T[1],@C[2]
ngr @C[2],@C[1]
rllg @D[0],@D[0],$rhotates[3][0]
xgr @C[2],@T[0] # C[0] ^ ( C[2] & ~C[1])
ogr @T[0],@C[4]
stg @C[2],$A[4][0]($src) # R[4][0] = C[0] ^ ( C[2] & ~C[1])
xgr @T[0],@C[3] # C[3] ^ ( C[0] | C[4])
ngr @C[4],@C[3]
stg @T[0],$A[4][3]($src) # R[4][3] = C[3] ^ ( C[0] | C[4])
xgr @C[4],@T[1] # C[2] ^ ( C[4] & C[3])
ogr @C[3],@T[1]
stg @C[4],$A[4][2]($src) # R[4][2] = C[2] ^ ( C[4] & C[3])
xgr @C[3],@C[1] # ~C[1] ^ ( C[2] | C[3])
lgr @C[1],@C[0] # harmonize with the loop top
lgr @C[0],@T[0]
stg @C[3],$A[4][1]($src) # R[4][1] = ~C[1] ^ ( C[2] | C[3])
tmll $iotas,255
jnz .Loop
l${g} %r14,$SIZE_T*14($sp)
br %r14
.size __KeccakF1600,.-__KeccakF1600
___
}
{
$code.=<<___;
.type KeccakF1600,\@function
.align 32
KeccakF1600:
.LKeccakF1600:
lghi %r1,-$frame
stm${g} %r6,%r15,$SIZE_T*6($sp)
lgr %r0,$sp
la $sp,0(%r1,$sp)
st${g} %r0,0($sp)
lghi @D[0],-1 # no 'not' instruction :-(
lghi @D[1],-1
lghi @D[2],-1
lghi @D[3],-1
lghi @D[4],-1
lghi @T[0],-1
xg @D[0],$A[0][1]($src)
xg @D[1],$A[0][2]($src)
xg @D[2],$A[1][3]($src)
xg @D[3],$A[2][2]($src)
xg @D[4],$A[3][2]($src)
xg @T[0],$A[4][0]($src)
stmg @D[0],@D[1],$A[0][1]($src)
stg @D[2],$A[1][3]($src)
stg @D[3],$A[2][2]($src)
stg @D[4],$A[3][2]($src)
stg @T[0],$A[4][0]($src)
la $dst,$stdframe($sp)
bras %r14,__KeccakF1600
lghi @D[0],-1 # no 'not' instruction :-(
lghi @D[1],-1
lghi @D[2],-1
lghi @D[3],-1
lghi @D[4],-1
lghi @T[0],-1
xg @D[0],$A[0][1]($src)
xg @D[1],$A[0][2]($src)
xg @D[2],$A[1][3]($src)
xg @D[3],$A[2][2]($src)
xg @D[4],$A[3][2]($src)
xg @T[0],$A[4][0]($src)
stmg @D[0],@D[1],$A[0][1]($src)
stg @D[2],$A[1][3]($src)
stg @D[3],$A[2][2]($src)
stg @D[4],$A[3][2]($src)
stg @T[0],$A[4][0]($src)
lm${g} %r6,%r15,$frame+6*$SIZE_T($sp)
br %r14
.size KeccakF1600,.-KeccakF1600
___
}
{ my ($A_flat,$inp,$len,$bsz) = map("%r$_",(2..5));
$code.=<<___;
.globl SHA3_absorb
.type SHA3_absorb,\@function
.align 32
SHA3_absorb:
lghi %r1,-$frame
stm${g} %r5,%r15,$SIZE_T*5($sp)
lgr %r0,$sp
la $sp,0(%r1,$sp)
st${g} %r0,0($sp)
lghi @D[0],-1 # no 'not' instruction :-(
lghi @D[1],-1
lghi @D[2],-1
lghi @D[3],-1
lghi @D[4],-1
lghi @T[0],-1
xg @D[0],$A[0][1]($src)
xg @D[1],$A[0][2]($src)
xg @D[2],$A[1][3]($src)
xg @D[3],$A[2][2]($src)
xg @D[4],$A[3][2]($src)
xg @T[0],$A[4][0]($src)
stmg @D[0],@D[1],$A[0][1]($src)
stg @D[2],$A[1][3]($src)
stg @D[3],$A[2][2]($src)
stg @D[4],$A[3][2]($src)
stg @T[0],$A[4][0]($src)
.Loop_absorb:
cl${g}r $len,$bsz
jl .Ldone_absorb
srl${g} $bsz,3
la %r1,0($A_flat)
.Lblock_absorb:
lrvg %r0,0($inp)
la $inp,8($inp)
xg %r0,0(%r1)
- la %r1,8(%r1)
a${g}hi $len,-8
- stg %r0,-8(%r1)
+ stg %r0,0(%r1)
+ la %r1,8(%r1)
brct $bsz,.Lblock_absorb
stm${g} $inp,$len,$frame+3*$SIZE_T($sp)
la $dst,$stdframe($sp)
bras %r14,__KeccakF1600
lm${g} $inp,$bsz,$frame+3*$SIZE_T($sp)
j .Loop_absorb
.align 16
.Ldone_absorb:
lghi @D[0],-1 # no 'not' instruction :-(
lghi @D[1],-1
lghi @D[2],-1
lghi @D[3],-1
lghi @D[4],-1
lghi @T[0],-1
xg @D[0],$A[0][1]($src)
xg @D[1],$A[0][2]($src)
xg @D[2],$A[1][3]($src)
xg @D[3],$A[2][2]($src)
xg @D[4],$A[3][2]($src)
xg @T[0],$A[4][0]($src)
stmg @D[0],@D[1],$A[0][1]($src)
stg @D[2],$A[1][3]($src)
stg @D[3],$A[2][2]($src)
stg @D[4],$A[3][2]($src)
stg @T[0],$A[4][0]($src)
lgr %r2,$len # return value
lm${g} %r6,%r15,$frame+6*$SIZE_T($sp)
br %r14
.size SHA3_absorb,.-SHA3_absorb
___
}
{ my ($A_flat,$out,$len,$bsz) = map("%r$_",(2..5));
$code.=<<___;
.globl SHA3_squeeze
.type SHA3_squeeze,\@function
.align 32
SHA3_squeeze:
srl${g} $bsz,3
st${g} %r14,2*$SIZE_T($sp)
lghi %r14,8
st${g} $bsz,5*$SIZE_T($sp)
la %r1,0($A_flat)
j .Loop_squeeze
.align 16
.Loop_squeeze:
cl${g}r $len,%r14
jl .Ltail_squeeze
lrvg %r0,0(%r1)
la %r1,8(%r1)
stg %r0,0($out)
la $out,8($out)
a${g}hi $len,-8 # len -= 8
jz .Ldone_squeeze
brct $bsz,.Loop_squeeze # bsz--
stm${g} $out,$len,3*$SIZE_T($sp)
bras %r14,.LKeccakF1600
lm${g} $out,$bsz,3*$SIZE_T($sp)
lghi %r14,8
la %r1,0($A_flat)
j .Loop_squeeze
.Ltail_squeeze:
lg %r0,0(%r1)
.Loop_tail_squeeze:
stc %r0,0($out)
la $out,1($out)
srlg %r0,8
brct $len,.Loop_tail_squeeze
.Ldone_squeeze:
l${g} %r14,2*$SIZE_T($sp)
br %r14
.size SHA3_squeeze,.-SHA3_squeeze
___
}
$code.=<<___;
.align 256
.quad 0,0,0,0,0,0,0,0
.type iotas,\@object
iotas:
.quad 0x0000000000000001
.quad 0x0000000000008082
.quad 0x800000000000808a
.quad 0x8000000080008000
.quad 0x000000000000808b
.quad 0x0000000080000001
.quad 0x8000000080008081
.quad 0x8000000000008009
.quad 0x000000000000008a
.quad 0x0000000000000088
.quad 0x0000000080008009
.quad 0x000000008000000a
.quad 0x000000008000808b
.quad 0x800000000000008b
.quad 0x8000000000008089
.quad 0x8000000000008003
.quad 0x8000000000008002
.quad 0x8000000000000080
.quad 0x000000000000800a
.quad 0x800000008000000a
.quad 0x8000000080008081
.quad 0x8000000000008080
.quad 0x0000000080000001
.quad 0x8000000080008008
.size iotas,.-iotas
.asciz "Keccak-1600 absorb and squeeze for s390x, CRYPTOGAMS by <appro\@openssl.org>"
___
# unlike 32-bit shift 64-bit one takes three arguments
$code =~ s/(srlg\s+)(%r[0-9]+),/$1$2,$2,/gm;
print $code;
close STDOUT;
diff --git a/crypto/sha/asm/sha512p8-ppc.pl b/crypto/sha/asm/sha512p8-ppc.pl
index 2792800b475c..0d4fdd292c07 100755
--- a/crypto/sha/asm/sha512p8-ppc.pl
+++ b/crypto/sha/asm/sha512p8-ppc.pl
@@ -1,427 +1,420 @@
#! /usr/bin/env perl
# Copyright 2014-2018 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/.
# ====================================================================
# SHA256/512 for PowerISA v2.07.
#
# Accurate performance measurements are problematic, because it's
# always virtualized setup with possibly throttled processor.
# Relative comparison is therefore more informative. This module is
# ~60% faster than integer-only sha512-ppc.pl. To anchor to something
# else, SHA256 is 24% slower than sha1-ppc.pl and 2.5x slower than
# hardware-assisted aes-128-cbc encrypt. SHA512 is 20% faster than
# sha1-ppc.pl and 1.6x slower than aes-128-cbc. Another interesting
# result is degree of computational resources' utilization. POWER8 is
# "massively multi-threaded chip" and difference between single- and
# maximum multi-process benchmark results tells that utilization is
# whooping 94%. For sha512-ppc.pl we get [not unimpressive] 84% and
# for sha1-ppc.pl - 73%. 100% means that multi-process result equals
# to single-process one, given that all threads end up on the same
# physical core.
#
######################################################################
# Believed-to-be-accurate results in cycles per processed byte [on
# little-endian system]. Numbers in square brackets are for 64-bit
# build of sha512-ppc.pl, presented for reference.
#
# POWER8 POWER9
# SHA256 9.7 [15.8] 11.2 [12.5]
# SHA512 6.1 [10.3] 7.0 [7.9]
$flavour=shift;
$output =shift;
if ($flavour =~ /64/) {
$SIZE_T=8;
$LRSAVE=2*$SIZE_T;
$STU="stdu";
$POP="ld";
$PUSH="std";
} elsif ($flavour =~ /32/) {
$SIZE_T=4;
$LRSAVE=$SIZE_T;
$STU="stwu";
$POP="lwz";
$PUSH="stw";
} else { die "nonsense $flavour"; }
$LENDIAN=($flavour=~/le/);
$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 $output" || die "can't call $xlate: $!";
if ($output =~ /512/) {
$bits=512;
$SZ=8;
$sz="d";
$rounds=80;
} else {
$bits=256;
$SZ=4;
$sz="w";
$rounds=64;
}
$func="sha${bits}_block_p8";
$LOCALS=8*$SIZE_T+8*16;
$FRAME=$LOCALS+9*16+6*$SIZE_T;
$sp ="r1";
$toc="r2";
$ctx="r3";
$inp="r4";
$num="r5";
$Tbl="r6";
$idx="r7";
$lrsave="r8";
$offload="r11";
$vrsave="r12";
@I = ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70) = (0,map("r$_",(10,26..31)));
@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("v$_",(0..7));
@X=map("v$_",(8..19,24..27));
($Ki,$Func,$Sigma,$lemask)=map("v$_",(28..31));
sub ROUND {
my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
my $j=($i+1)%16;
my $k=($i+2)%8;
$code.=<<___ if ($i<15 && ($i%(16/$SZ))==(16/$SZ-1));
lvx_u @X[$i+1],0,$inp ; load X[i] in advance
addi $inp,$inp,16
___
$code.=<<___ if ($i<16 && ($i%(16/$SZ)));
vsldoi @X[$i],@X[$i-1],@X[$i-1],$SZ
___
$code.=<<___ if ($LENDIAN && $i<16 && ($i%(16/$SZ))==0);
vperm @X[$i],@X[$i],@X[$i],$lemask
___
$code.=<<___ if ($i>=15);
vshasigma${sz} $Sigma,@X[($j+1)%16],0,0
vaddu${sz}m @X[$j],@X[$j],$Sigma
vshasigma${sz} $Sigma,@X[($j+14)%16],0,15
vaddu${sz}m @X[$j],@X[$j],$Sigma
vaddu${sz}m @X[$j],@X[$j],@X[($j+9)%16]
___
$code.=<<___;
vaddu${sz}m $h,$h,@X[$i%16] ; h+=X[i]
vsel $Func,$g,$f,$e ; Ch(e,f,g)
vaddu${sz}m $g,$g,$Ki ; future h+=K[i]
vaddu${sz}m $h,$h,$Func ; h+=Ch(e,f,g)
vshasigma${sz} $Sigma,$e,1,15 ; Sigma1(e)
vaddu${sz}m $h,$h,$Sigma ; h+=Sigma1(e)
vxor $Func,$a,$b
vsel $Func,$b,$c,$Func ; Maj(a,b,c)
vaddu${sz}m $d,$d,$h ; d+=h
vshasigma${sz} $Sigma,$a,1,0 ; Sigma0(a)
vaddu${sz}m $Sigma,$Sigma,$Func ; Sigma0(a)+Maj(a,b,c)
vaddu${sz}m $h,$h,$Sigma ; h+=Sigma0(a)+Maj(a,b,c)
lvx $Ki,@I[$k],$idx ; load next K[i]
___
$code.=<<___ if ($k == 7);
addi $idx,$idx,0x80
___
}
$code=<<___;
.machine "any"
.text
.globl $func
.align 6
$func:
$STU $sp,-$FRAME($sp)
mflr $lrsave
li r10,`$LOCALS+15`
li r11,`$LOCALS+31`
stvx v24,r10,$sp # ABI says so
addi r10,r10,32
mfspr $vrsave,256
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 r11,-4096+255
- stw $vrsave,`$FRAME+6*$SIZE_T-4`($sp) # save vrsave
+ li r11,-4096+255 # 0xfffff0ff
+ stw $vrsave,`$FRAME-6*$SIZE_T-4`($sp) # save vrsave
li $x10,0x10
$PUSH r26,`$FRAME-6*$SIZE_T`($sp)
li $x20,0x20
$PUSH r27,`$FRAME-5*$SIZE_T`($sp)
li $x30,0x30
$PUSH r28,`$FRAME-4*$SIZE_T`($sp)
li $x40,0x40
$PUSH r29,`$FRAME-3*$SIZE_T`($sp)
li $x50,0x50
$PUSH r30,`$FRAME-2*$SIZE_T`($sp)
li $x60,0x60
$PUSH r31,`$FRAME-1*$SIZE_T`($sp)
li $x70,0x70
$PUSH $lrsave,`$FRAME+$LRSAVE`($sp)
mtspr 256,r11
bl LPICmeup
addi $offload,$sp,`8*$SIZE_T+15`
___
$code.=<<___ if ($LENDIAN);
li $idx,8
lvsl $lemask,0,$idx
vspltisb $Ki,0x0f
vxor $lemask,$lemask,$Ki
___
$code.=<<___ if ($SZ==4);
lvx_4w $A,$x00,$ctx
lvx_4w $E,$x10,$ctx
vsldoi $B,$A,$A,4 # unpack
vsldoi $C,$A,$A,8
vsldoi $D,$A,$A,12
vsldoi $F,$E,$E,4
vsldoi $G,$E,$E,8
vsldoi $H,$E,$E,12
___
$code.=<<___ if ($SZ==8);
lvx_u $A,$x00,$ctx
lvx_u $C,$x10,$ctx
lvx_u $E,$x20,$ctx
vsldoi $B,$A,$A,8 # unpack
lvx_u $G,$x30,$ctx
vsldoi $D,$C,$C,8
vsldoi $F,$E,$E,8
vsldoi $H,$G,$G,8
___
$code.=<<___;
li r0,`($rounds-16)/16` # inner loop counter
b Loop
.align 5
Loop:
lvx $Ki,$x00,$Tbl
lvx_u @X[0],0,$inp
addi $inp,$inp,16
mr $idx,$Tbl # copy $Tbl
stvx $A,$x00,$offload # offload $A-$H
stvx $B,$x10,$offload
stvx $C,$x20,$offload
stvx $D,$x30,$offload
stvx $E,$x40,$offload
stvx $F,$x50,$offload
stvx $G,$x60,$offload
stvx $H,$x70,$offload
vaddu${sz}m $H,$H,$Ki # h+K[i]
lvx $Ki,$x10,$Tbl
___
for ($i=0;$i<16;$i++) { &ROUND($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
mtctr r0
b L16_xx
.align 5
L16_xx:
___
for (;$i<32;$i++) { &ROUND($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
bdnz L16_xx
lvx @X[2],$x00,$offload
subic. $num,$num,1
lvx @X[3],$x10,$offload
vaddu${sz}m $A,$A,@X[2]
lvx @X[4],$x20,$offload
vaddu${sz}m $B,$B,@X[3]
lvx @X[5],$x30,$offload
vaddu${sz}m $C,$C,@X[4]
lvx @X[6],$x40,$offload
vaddu${sz}m $D,$D,@X[5]
lvx @X[7],$x50,$offload
vaddu${sz}m $E,$E,@X[6]
lvx @X[8],$x60,$offload
vaddu${sz}m $F,$F,@X[7]
lvx @X[9],$x70,$offload
vaddu${sz}m $G,$G,@X[8]
vaddu${sz}m $H,$H,@X[9]
bne Loop
___
$code.=<<___ if ($SZ==4);
lvx @X[0],$x20,$idx
vperm $A,$A,$B,$Ki # pack the answer
lvx @X[1],$x30,$idx
vperm $E,$E,$F,$Ki
vperm $A,$A,$C,@X[0]
vperm $E,$E,$G,@X[0]
vperm $A,$A,$D,@X[1]
vperm $E,$E,$H,@X[1]
stvx_4w $A,$x00,$ctx
stvx_4w $E,$x10,$ctx
___
$code.=<<___ if ($SZ==8);
vperm $A,$A,$B,$Ki # pack the answer
vperm $C,$C,$D,$Ki
vperm $E,$E,$F,$Ki
vperm $G,$G,$H,$Ki
stvx_u $A,$x00,$ctx
stvx_u $C,$x10,$ctx
stvx_u $E,$x20,$ctx
stvx_u $G,$x30,$ctx
___
$code.=<<___;
- li r10,`$LOCALS+15`
+ addi $offload,$sp,`$LOCALS+15`
mtlr $lrsave
- li r11,`$LOCALS+31`
mtspr 256,$vrsave
- lvx v24,r10,$sp # ABI says so
- 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
+ lvx v24,$x00,$offload # ABI says so
+ lvx v25,$x10,$offload
+ lvx v26,$x20,$offload
+ lvx v27,$x30,$offload
+ lvx v28,$x40,$offload
+ lvx v29,$x50,$offload
+ lvx v30,$x60,$offload
+ lvx v31,$x70,$offload
$POP r26,`$FRAME-6*$SIZE_T`($sp)
$POP r27,`$FRAME-5*$SIZE_T`($sp)
$POP r28,`$FRAME-4*$SIZE_T`($sp)
$POP r29,`$FRAME-3*$SIZE_T`($sp)
$POP r30,`$FRAME-2*$SIZE_T`($sp)
$POP r31,`$FRAME-1*$SIZE_T`($sp)
addi $sp,$sp,$FRAME
blr
.long 0
.byte 0,12,4,1,0x80,6,3,0
.long 0
.size $func,.-$func
___
# Ugly hack here, because PPC assembler syntax seem to vary too
# much from platforms to platform...
$code.=<<___;
.align 6
LPICmeup:
mflr r0
bcl 20,31,\$+4
mflr $Tbl ; vvvvvv "distance" between . and 1st data entry
addi $Tbl,$Tbl,`64-8`
mtlr r0
blr
.long 0
.byte 0,12,0x14,0,0,0,0,0
.space `64-9*4`
___
if ($SZ==8) {
local *table = sub {
foreach(@_) { $code.=".quad $_,$_\n"; }
};
table(
"0x428a2f98d728ae22","0x7137449123ef65cd",
"0xb5c0fbcfec4d3b2f","0xe9b5dba58189dbbc",
"0x3956c25bf348b538","0x59f111f1b605d019",
"0x923f82a4af194f9b","0xab1c5ed5da6d8118",
"0xd807aa98a3030242","0x12835b0145706fbe",
"0x243185be4ee4b28c","0x550c7dc3d5ffb4e2",
"0x72be5d74f27b896f","0x80deb1fe3b1696b1",
"0x9bdc06a725c71235","0xc19bf174cf692694",
"0xe49b69c19ef14ad2","0xefbe4786384f25e3",
"0x0fc19dc68b8cd5b5","0x240ca1cc77ac9c65",
"0x2de92c6f592b0275","0x4a7484aa6ea6e483",
"0x5cb0a9dcbd41fbd4","0x76f988da831153b5",
"0x983e5152ee66dfab","0xa831c66d2db43210",
"0xb00327c898fb213f","0xbf597fc7beef0ee4",
"0xc6e00bf33da88fc2","0xd5a79147930aa725",
"0x06ca6351e003826f","0x142929670a0e6e70",
"0x27b70a8546d22ffc","0x2e1b21385c26c926",
"0x4d2c6dfc5ac42aed","0x53380d139d95b3df",
"0x650a73548baf63de","0x766a0abb3c77b2a8",
"0x81c2c92e47edaee6","0x92722c851482353b",
"0xa2bfe8a14cf10364","0xa81a664bbc423001",
"0xc24b8b70d0f89791","0xc76c51a30654be30",
"0xd192e819d6ef5218","0xd69906245565a910",
"0xf40e35855771202a","0x106aa07032bbd1b8",
"0x19a4c116b8d2d0c8","0x1e376c085141ab53",
"0x2748774cdf8eeb99","0x34b0bcb5e19b48a8",
"0x391c0cb3c5c95a63","0x4ed8aa4ae3418acb",
"0x5b9cca4f7763e373","0x682e6ff3d6b2b8a3",
"0x748f82ee5defb2fc","0x78a5636f43172f60",
"0x84c87814a1f0ab72","0x8cc702081a6439ec",
"0x90befffa23631e28","0xa4506cebde82bde9",
"0xbef9a3f7b2c67915","0xc67178f2e372532b",
"0xca273eceea26619c","0xd186b8c721c0c207",
"0xeada7dd6cde0eb1e","0xf57d4f7fee6ed178",
"0x06f067aa72176fba","0x0a637dc5a2c898a6",
"0x113f9804bef90dae","0x1b710b35131c471b",
"0x28db77f523047d84","0x32caab7b40c72493",
"0x3c9ebe0a15c9bebc","0x431d67c49c100d4c",
"0x4cc5d4becb3e42b6","0x597f299cfc657e2a",
"0x5fcb6fab3ad6faec","0x6c44198c4a475817","0");
$code.=<<___ if (!$LENDIAN);
.quad 0x0001020304050607,0x1011121314151617
___
$code.=<<___ if ($LENDIAN); # quad-swapped
.quad 0x1011121314151617,0x0001020304050607
___
} else {
local *table = sub {
foreach(@_) { $code.=".long $_,$_,$_,$_\n"; }
};
table(
"0x428a2f98","0x71374491","0xb5c0fbcf","0xe9b5dba5",
"0x3956c25b","0x59f111f1","0x923f82a4","0xab1c5ed5",
"0xd807aa98","0x12835b01","0x243185be","0x550c7dc3",
"0x72be5d74","0x80deb1fe","0x9bdc06a7","0xc19bf174",
"0xe49b69c1","0xefbe4786","0x0fc19dc6","0x240ca1cc",
"0x2de92c6f","0x4a7484aa","0x5cb0a9dc","0x76f988da",
"0x983e5152","0xa831c66d","0xb00327c8","0xbf597fc7",
"0xc6e00bf3","0xd5a79147","0x06ca6351","0x14292967",
"0x27b70a85","0x2e1b2138","0x4d2c6dfc","0x53380d13",
"0x650a7354","0x766a0abb","0x81c2c92e","0x92722c85",
"0xa2bfe8a1","0xa81a664b","0xc24b8b70","0xc76c51a3",
"0xd192e819","0xd6990624","0xf40e3585","0x106aa070",
"0x19a4c116","0x1e376c08","0x2748774c","0x34b0bcb5",
"0x391c0cb3","0x4ed8aa4a","0x5b9cca4f","0x682e6ff3",
"0x748f82ee","0x78a5636f","0x84c87814","0x8cc70208",
"0x90befffa","0xa4506ceb","0xbef9a3f7","0xc67178f2","0");
$code.=<<___ if (!$LENDIAN);
.long 0x00010203,0x10111213,0x10111213,0x10111213
.long 0x00010203,0x04050607,0x10111213,0x10111213
.long 0x00010203,0x04050607,0x08090a0b,0x10111213
___
$code.=<<___ if ($LENDIAN); # word-swapped
.long 0x10111213,0x10111213,0x10111213,0x00010203
.long 0x10111213,0x10111213,0x04050607,0x00010203
.long 0x10111213,0x08090a0b,0x04050607,0x00010203
___
}
$code.=<<___;
.asciz "SHA${bits} for PowerISA 2.07, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
___
$code =~ s/\`([^\`]*)\`/eval $1/gem;
print $code;
close STDOUT;
diff --git a/crypto/siphash/siphash.c b/crypto/siphash/siphash.c
index ff84a29f8215..be74a38d934d 100644
--- a/crypto/siphash/siphash.c
+++ b/crypto/siphash/siphash.c
@@ -1,248 +1,260 @@
/*
* Copyright 2017-2018 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
*/
/* Based on https://131002.net/siphash C reference implementation */
/*
SipHash reference C implementation
Copyright (c) 2012-2016 Jean-Philippe Aumasson
Copyright (c) 2012-2014 Daniel J. Bernstein
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdlib.h>
#include <string.h>
#include <openssl/crypto.h>
#include "internal/siphash.h"
#include "siphash_local.h"
/* default: SipHash-2-4 */
#define SIPHASH_C_ROUNDS 2
#define SIPHASH_D_ROUNDS 4
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
#define U32TO8_LE(p, v) \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24);
#define U64TO8_LE(p, v) \
U32TO8_LE((p), (uint32_t)((v))); \
U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
#define U8TO64_LE(p) \
(((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
#define SIPROUND \
do { \
v0 += v1; \
v1 = ROTL(v1, 13); \
v1 ^= v0; \
v0 = ROTL(v0, 32); \
v2 += v3; \
v3 = ROTL(v3, 16); \
v3 ^= v2; \
v0 += v3; \
v3 = ROTL(v3, 21); \
v3 ^= v0; \
v2 += v1; \
v1 = ROTL(v1, 17); \
v1 ^= v2; \
v2 = ROTL(v2, 32); \
} while (0)
size_t SipHash_ctx_size(void)
{
return sizeof(SIPHASH);
}
size_t SipHash_hash_size(SIPHASH *ctx)
{
return ctx->hash_size;
}
static size_t siphash_adjust_hash_size(size_t hash_size)
{
if (hash_size == 0)
hash_size = SIPHASH_MAX_DIGEST_SIZE;
return hash_size;
}
int SipHash_set_hash_size(SIPHASH *ctx, size_t hash_size)
{
hash_size = siphash_adjust_hash_size(hash_size);
if (hash_size != SIPHASH_MIN_DIGEST_SIZE
&& hash_size != SIPHASH_MAX_DIGEST_SIZE)
return 0;
- ctx->hash_size = hash_size;
+ /*
+ * It's possible that the key was set first. If the hash size changes,
+ * we need to adjust v1 (see SipHash_Init().
+ */
+
+ /* Start by adjusting the stored size, to make things easier */
+ ctx->hash_size = siphash_adjust_hash_size(ctx->hash_size);
+
+ /* Now, adjust ctx->v1 if the old and the new size differ */
+ if ((size_t)ctx->hash_size != hash_size) {
+ ctx->v1 ^= 0xee;
+ ctx->hash_size = hash_size;
+ }
return 1;
}
/* hash_size = crounds = drounds = 0 means SipHash24 with 16-byte output */
int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int crounds, int drounds)
{
uint64_t k0 = U8TO64_LE(k);
uint64_t k1 = U8TO64_LE(k + 8);
/* If the hash size wasn't set, i.e. is zero */
ctx->hash_size = siphash_adjust_hash_size(ctx->hash_size);
if (drounds == 0)
drounds = SIPHASH_D_ROUNDS;
if (crounds == 0)
crounds = SIPHASH_C_ROUNDS;
ctx->crounds = crounds;
ctx->drounds = drounds;
ctx->len = 0;
ctx->total_inlen = 0;
ctx->v0 = 0x736f6d6570736575ULL ^ k0;
ctx->v1 = 0x646f72616e646f6dULL ^ k1;
ctx->v2 = 0x6c7967656e657261ULL ^ k0;
ctx->v3 = 0x7465646279746573ULL ^ k1;
if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE)
ctx->v1 ^= 0xee;
return 1;
}
void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen)
{
uint64_t m;
const uint8_t *end;
int left;
int i;
uint64_t v0 = ctx->v0;
uint64_t v1 = ctx->v1;
uint64_t v2 = ctx->v2;
uint64_t v3 = ctx->v3;
ctx->total_inlen += inlen;
if (ctx->len) {
/* deal with leavings */
size_t available = SIPHASH_BLOCK_SIZE - ctx->len;
/* not enough to fill leavings */
if (inlen < available) {
memcpy(&ctx->leavings[ctx->len], in, inlen);
ctx->len += inlen;
return;
}
/* copy data into leavings and reduce input */
memcpy(&ctx->leavings[ctx->len], in, available);
inlen -= available;
in += available;
/* process leavings */
m = U8TO64_LE(ctx->leavings);
v3 ^= m;
for (i = 0; i < ctx->crounds; ++i)
SIPROUND;
v0 ^= m;
}
left = inlen & (SIPHASH_BLOCK_SIZE-1); /* gets put into leavings */
end = in + inlen - left;
for (; in != end; in += 8) {
m = U8TO64_LE(in);
v3 ^= m;
for (i = 0; i < ctx->crounds; ++i)
SIPROUND;
v0 ^= m;
}
/* save leavings and other ctx */
if (left)
memcpy(ctx->leavings, end, left);
ctx->len = left;
ctx->v0 = v0;
ctx->v1 = v1;
ctx->v2 = v2;
ctx->v3 = v3;
}
int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen)
{
/* finalize hash */
int i;
uint64_t b = ctx->total_inlen << 56;
uint64_t v0 = ctx->v0;
uint64_t v1 = ctx->v1;
uint64_t v2 = ctx->v2;
uint64_t v3 = ctx->v3;
if (outlen != (size_t)ctx->hash_size)
return 0;
switch (ctx->len) {
case 7:
b |= ((uint64_t)ctx->leavings[6]) << 48;
/* fall thru */
case 6:
b |= ((uint64_t)ctx->leavings[5]) << 40;
/* fall thru */
case 5:
b |= ((uint64_t)ctx->leavings[4]) << 32;
/* fall thru */
case 4:
b |= ((uint64_t)ctx->leavings[3]) << 24;
/* fall thru */
case 3:
b |= ((uint64_t)ctx->leavings[2]) << 16;
/* fall thru */
case 2:
b |= ((uint64_t)ctx->leavings[1]) << 8;
/* fall thru */
case 1:
b |= ((uint64_t)ctx->leavings[0]);
case 0:
break;
}
v3 ^= b;
for (i = 0; i < ctx->crounds; ++i)
SIPROUND;
v0 ^= b;
if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE)
v2 ^= 0xee;
else
v2 ^= 0xff;
for (i = 0; i < ctx->drounds; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out, b);
if (ctx->hash_size == SIPHASH_MIN_DIGEST_SIZE)
return 1;
v1 ^= 0xdd;
for (i = 0; i < ctx->drounds; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out + 8, b);
return 1;
}
diff --git a/crypto/sm2/sm2_crypt.c b/crypto/sm2/sm2_crypt.c
index 9c69a4505487..4389fc731edd 100644
--- a/crypto/sm2/sm2_crypt.c
+++ b/crypto/sm2/sm2_crypt.c
@@ -1,392 +1,393 @@
/*
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
* 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/sm2.h"
#include "internal/sm2err.h"
+#include "internal/ec_int.h" /* ecdh_KDF_X9_63() */
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <string.h>
typedef struct SM2_Ciphertext_st SM2_Ciphertext;
DECLARE_ASN1_FUNCTIONS(SM2_Ciphertext)
struct SM2_Ciphertext_st {
BIGNUM *C1x;
BIGNUM *C1y;
ASN1_OCTET_STRING *C3;
ASN1_OCTET_STRING *C2;
};
ASN1_SEQUENCE(SM2_Ciphertext) = {
ASN1_SIMPLE(SM2_Ciphertext, C1x, BIGNUM),
ASN1_SIMPLE(SM2_Ciphertext, C1y, BIGNUM),
ASN1_SIMPLE(SM2_Ciphertext, C3, ASN1_OCTET_STRING),
ASN1_SIMPLE(SM2_Ciphertext, C2, ASN1_OCTET_STRING),
} ASN1_SEQUENCE_END(SM2_Ciphertext)
IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext)
static size_t ec_field_size(const EC_GROUP *group)
{
/* Is there some simpler way to do this? */
BIGNUM *p = BN_new();
BIGNUM *a = BN_new();
BIGNUM *b = BN_new();
size_t field_size = 0;
if (p == NULL || a == NULL || b == NULL)
goto done;
if (!EC_GROUP_get_curve(group, p, a, b, NULL))
goto done;
field_size = (BN_num_bits(p) + 7) / 8;
done:
BN_free(p);
BN_free(a);
BN_free(b);
return field_size;
}
int sm2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
size_t *pt_size)
{
const size_t field_size = ec_field_size(EC_KEY_get0_group(key));
const int md_size = EVP_MD_size(digest);
size_t overhead;
if (md_size < 0) {
SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_DIGEST);
return 0;
}
if (field_size == 0) {
SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_FIELD);
return 0;
}
overhead = 10 + 2 * field_size + (size_t)md_size;
if (msg_len <= overhead) {
SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_ENCODING);
return 0;
}
*pt_size = msg_len - overhead;
return 1;
}
int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
size_t *ct_size)
{
const size_t field_size = ec_field_size(EC_KEY_get0_group(key));
const int md_size = EVP_MD_size(digest);
size_t sz;
if (field_size == 0 || md_size < 0)
return 0;
/* Integer and string are simple type; set constructed = 0, means primitive and definite length encoding. */
sz = 2 * ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER)
+ ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING)
+ ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING);
/* Sequence is structured type; set constructed = 1, means constructed and definite length encoding. */
*ct_size = ASN1_object_size(1, sz, V_ASN1_SEQUENCE);
return 1;
}
int sm2_encrypt(const EC_KEY *key,
const EVP_MD *digest,
const uint8_t *msg,
size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len)
{
int rc = 0, ciphertext_leni;
size_t i;
BN_CTX *ctx = NULL;
BIGNUM *k = NULL;
BIGNUM *x1 = NULL;
BIGNUM *y1 = NULL;
BIGNUM *x2 = NULL;
BIGNUM *y2 = NULL;
EVP_MD_CTX *hash = EVP_MD_CTX_new();
struct SM2_Ciphertext_st ctext_struct;
const EC_GROUP *group = EC_KEY_get0_group(key);
const BIGNUM *order = EC_GROUP_get0_order(group);
const EC_POINT *P = EC_KEY_get0_public_key(key);
EC_POINT *kG = NULL;
EC_POINT *kP = NULL;
uint8_t *msg_mask = NULL;
uint8_t *x2y2 = NULL;
uint8_t *C3 = NULL;
size_t field_size;
const int C3_size = EVP_MD_size(digest);
/* NULL these before any "goto done" */
ctext_struct.C2 = NULL;
ctext_struct.C3 = NULL;
if (hash == NULL || C3_size <= 0) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto done;
}
field_size = ec_field_size(group);
if (field_size == 0) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto done;
}
kG = EC_POINT_new(group);
kP = EC_POINT_new(group);
ctx = BN_CTX_new();
if (kG == NULL || kP == NULL || ctx == NULL) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto done;
}
BN_CTX_start(ctx);
k = BN_CTX_get(ctx);
x1 = BN_CTX_get(ctx);
x2 = BN_CTX_get(ctx);
y1 = BN_CTX_get(ctx);
y2 = BN_CTX_get(ctx);
if (y2 == NULL) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_BN_LIB);
goto done;
}
x2y2 = OPENSSL_zalloc(2 * field_size);
C3 = OPENSSL_zalloc(C3_size);
if (x2y2 == NULL || C3 == NULL) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto done;
}
memset(ciphertext_buf, 0, *ciphertext_len);
if (!BN_priv_rand_range(k, order)) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto done;
}
if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)
|| !EC_POINT_get_affine_coordinates(group, kG, x1, y1, ctx)
|| !EC_POINT_mul(group, kP, NULL, P, k, ctx)
|| !EC_POINT_get_affine_coordinates(group, kP, x2, y2, ctx)) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EC_LIB);
goto done;
}
if (BN_bn2binpad(x2, x2y2, field_size) < 0
|| BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto done;
}
msg_mask = OPENSSL_zalloc(msg_len);
if (msg_mask == NULL) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto done;
}
/* X9.63 with no salt happens to match the KDF used in SM2 */
- if (!ECDH_KDF_X9_62(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
+ if (!ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
digest)) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EVP_LIB);
goto done;
}
for (i = 0; i != msg_len; ++i)
msg_mask[i] ^= msg[i];
if (EVP_DigestInit(hash, digest) == 0
|| EVP_DigestUpdate(hash, x2y2, field_size) == 0
|| EVP_DigestUpdate(hash, msg, msg_len) == 0
|| EVP_DigestUpdate(hash, x2y2 + field_size, field_size) == 0
|| EVP_DigestFinal(hash, C3, NULL) == 0) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EVP_LIB);
goto done;
}
ctext_struct.C1x = x1;
ctext_struct.C1y = y1;
ctext_struct.C3 = ASN1_OCTET_STRING_new();
ctext_struct.C2 = ASN1_OCTET_STRING_new();
if (ctext_struct.C3 == NULL || ctext_struct.C2 == NULL) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size)
|| !ASN1_OCTET_STRING_set(ctext_struct.C2, msg_mask, msg_len)) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto done;
}
ciphertext_leni = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf);
/* Ensure cast to size_t is safe */
if (ciphertext_leni < 0) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto done;
}
*ciphertext_len = (size_t)ciphertext_leni;
rc = 1;
done:
ASN1_OCTET_STRING_free(ctext_struct.C2);
ASN1_OCTET_STRING_free(ctext_struct.C3);
OPENSSL_free(msg_mask);
OPENSSL_free(x2y2);
OPENSSL_free(C3);
EVP_MD_CTX_free(hash);
BN_CTX_free(ctx);
EC_POINT_free(kG);
EC_POINT_free(kP);
return rc;
}
int sm2_decrypt(const EC_KEY *key,
const EVP_MD *digest,
const uint8_t *ciphertext,
size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len)
{
int rc = 0;
int i;
BN_CTX *ctx = NULL;
const EC_GROUP *group = EC_KEY_get0_group(key);
EC_POINT *C1 = NULL;
struct SM2_Ciphertext_st *sm2_ctext = NULL;
BIGNUM *x2 = NULL;
BIGNUM *y2 = NULL;
uint8_t *x2y2 = NULL;
uint8_t *computed_C3 = NULL;
const size_t field_size = ec_field_size(group);
const int hash_size = EVP_MD_size(digest);
uint8_t *msg_mask = NULL;
const uint8_t *C2 = NULL;
const uint8_t *C3 = NULL;
int msg_len = 0;
EVP_MD_CTX *hash = NULL;
if (field_size == 0 || hash_size <= 0)
goto done;
memset(ptext_buf, 0xFF, *ptext_len);
sm2_ctext = d2i_SM2_Ciphertext(NULL, &ciphertext, ciphertext_len);
if (sm2_ctext == NULL) {
SM2err(SM2_F_SM2_DECRYPT, SM2_R_ASN1_ERROR);
goto done;
}
if (sm2_ctext->C3->length != hash_size) {
SM2err(SM2_F_SM2_DECRYPT, SM2_R_INVALID_ENCODING);
goto done;
}
C2 = sm2_ctext->C2->data;
C3 = sm2_ctext->C3->data;
msg_len = sm2_ctext->C2->length;
ctx = BN_CTX_new();
if (ctx == NULL) {
SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE);
goto done;
}
BN_CTX_start(ctx);
x2 = BN_CTX_get(ctx);
y2 = BN_CTX_get(ctx);
if (y2 == NULL) {
SM2err(SM2_F_SM2_DECRYPT, ERR_R_BN_LIB);
goto done;
}
msg_mask = OPENSSL_zalloc(msg_len);
x2y2 = OPENSSL_zalloc(2 * field_size);
computed_C3 = OPENSSL_zalloc(hash_size);
if (msg_mask == NULL || x2y2 == NULL || computed_C3 == NULL) {
SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE);
goto done;
}
C1 = EC_POINT_new(group);
if (C1 == NULL) {
SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!EC_POINT_set_affine_coordinates(group, C1, sm2_ctext->C1x,
sm2_ctext->C1y, ctx)
|| !EC_POINT_mul(group, C1, NULL, C1, EC_KEY_get0_private_key(key),
ctx)
|| !EC_POINT_get_affine_coordinates(group, C1, x2, y2, ctx)) {
SM2err(SM2_F_SM2_DECRYPT, ERR_R_EC_LIB);
goto done;
}
if (BN_bn2binpad(x2, x2y2, field_size) < 0
|| BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0
- || !ECDH_KDF_X9_62(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
+ || !ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
digest)) {
SM2err(SM2_F_SM2_DECRYPT, ERR_R_INTERNAL_ERROR);
goto done;
}
for (i = 0; i != msg_len; ++i)
ptext_buf[i] = C2[i] ^ msg_mask[i];
hash = EVP_MD_CTX_new();
if (hash == NULL) {
SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!EVP_DigestInit(hash, digest)
|| !EVP_DigestUpdate(hash, x2y2, field_size)
|| !EVP_DigestUpdate(hash, ptext_buf, msg_len)
|| !EVP_DigestUpdate(hash, x2y2 + field_size, field_size)
|| !EVP_DigestFinal(hash, computed_C3, NULL)) {
SM2err(SM2_F_SM2_DECRYPT, ERR_R_EVP_LIB);
goto done;
}
if (CRYPTO_memcmp(computed_C3, C3, hash_size) != 0) {
SM2err(SM2_F_SM2_DECRYPT, SM2_R_INVALID_DIGEST);
goto done;
}
rc = 1;
*ptext_len = msg_len;
done:
if (rc == 0)
memset(ptext_buf, 0, *ptext_len);
OPENSSL_free(msg_mask);
OPENSSL_free(x2y2);
OPENSSL_free(computed_C3);
EC_POINT_free(C1);
BN_CTX_free(ctx);
SM2_Ciphertext_free(sm2_ctext);
EVP_MD_CTX_free(hash);
return rc;
}
diff --git a/crypto/sm2/sm2_sign.c b/crypto/sm2/sm2_sign.c
index e594ffd10a0b..0f9c14cb5f4c 100644
--- a/crypto/sm2/sm2_sign.c
+++ b/crypto/sm2/sm2_sign.c
@@ -1,478 +1,479 @@
/*
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
* 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/sm2.h"
#include "internal/sm2err.h"
#include "internal/ec_int.h" /* ec_group_do_inverse_ord() */
+#include "internal/numbers.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <string.h>
int sm2_compute_z_digest(uint8_t *out,
const EVP_MD *digest,
const uint8_t *id,
const size_t id_len,
const EC_KEY *key)
{
int rc = 0;
const EC_GROUP *group = EC_KEY_get0_group(key);
BN_CTX *ctx = NULL;
EVP_MD_CTX *hash = NULL;
BIGNUM *p = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
BIGNUM *xG = NULL;
BIGNUM *yG = NULL;
BIGNUM *xA = NULL;
BIGNUM *yA = NULL;
int p_bytes = 0;
uint8_t *buf = NULL;
uint16_t entl = 0;
uint8_t e_byte = 0;
hash = EVP_MD_CTX_new();
ctx = BN_CTX_new();
if (hash == NULL || ctx == NULL) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
goto done;
}
p = BN_CTX_get(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
xG = BN_CTX_get(ctx);
yG = BN_CTX_get(ctx);
xA = BN_CTX_get(ctx);
yA = BN_CTX_get(ctx);
if (yA == NULL) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!EVP_DigestInit(hash, digest)) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
goto done;
}
/* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */
if (id_len >= (UINT16_MAX / 8)) {
/* too large */
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, SM2_R_ID_TOO_LARGE);
goto done;
}
entl = (uint16_t)(8 * id_len);
e_byte = entl >> 8;
if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
goto done;
}
e_byte = entl & 0xFF;
if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
goto done;
}
if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
goto done;
}
if (!EC_GROUP_get_curve(group, p, a, b, ctx)) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EC_LIB);
goto done;
}
p_bytes = BN_num_bytes(p);
buf = OPENSSL_zalloc(p_bytes);
if (buf == NULL) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
goto done;
}
if (BN_bn2binpad(a, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| BN_bn2binpad(b, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| !EC_POINT_get_affine_coordinates(group,
EC_GROUP_get0_generator(group),
xG, yG, ctx)
|| BN_bn2binpad(xG, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| BN_bn2binpad(yG, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| !EC_POINT_get_affine_coordinates(group,
EC_KEY_get0_public_key(key),
xA, yA, ctx)
|| BN_bn2binpad(xA, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| BN_bn2binpad(yA, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| !EVP_DigestFinal(hash, out, NULL)) {
SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_INTERNAL_ERROR);
goto done;
}
rc = 1;
done:
OPENSSL_free(buf);
BN_CTX_free(ctx);
EVP_MD_CTX_free(hash);
return rc;
}
static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
const EC_KEY *key,
const uint8_t *id,
const size_t id_len,
const uint8_t *msg, size_t msg_len)
{
EVP_MD_CTX *hash = EVP_MD_CTX_new();
const int md_size = EVP_MD_size(digest);
uint8_t *z = NULL;
BIGNUM *e = NULL;
if (md_size < 0) {
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, SM2_R_INVALID_DIGEST);
goto done;
}
z = OPENSSL_zalloc(md_size);
if (hash == NULL || z == NULL) {
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!sm2_compute_z_digest(z, digest, id, id_len, key)) {
/* SM2err already called */
goto done;
}
if (!EVP_DigestInit(hash, digest)
|| !EVP_DigestUpdate(hash, z, md_size)
|| !EVP_DigestUpdate(hash, msg, msg_len)
/* reuse z buffer to hold H(Z || M) */
|| !EVP_DigestFinal(hash, z, NULL)) {
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_EVP_LIB);
goto done;
}
e = BN_bin2bn(z, md_size, NULL);
if (e == NULL)
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_INTERNAL_ERROR);
done:
OPENSSL_free(z);
EVP_MD_CTX_free(hash);
return e;
}
static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
{
const BIGNUM *dA = EC_KEY_get0_private_key(key);
const EC_GROUP *group = EC_KEY_get0_group(key);
const BIGNUM *order = EC_GROUP_get0_order(group);
ECDSA_SIG *sig = NULL;
EC_POINT *kG = NULL;
BN_CTX *ctx = NULL;
BIGNUM *k = NULL;
BIGNUM *rk = NULL;
BIGNUM *r = NULL;
BIGNUM *s = NULL;
BIGNUM *x1 = NULL;
BIGNUM *tmp = NULL;
kG = EC_POINT_new(group);
ctx = BN_CTX_new();
if (kG == NULL || ctx == NULL) {
SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);
goto done;
}
BN_CTX_start(ctx);
k = BN_CTX_get(ctx);
rk = BN_CTX_get(ctx);
x1 = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL) {
SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);
goto done;
}
/*
* These values are returned and so should not be allocated out of the
* context
*/
r = BN_new();
s = BN_new();
if (r == NULL || s == NULL) {
SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);
goto done;
}
for (;;) {
if (!BN_priv_rand_range(k, order)) {
SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);
goto done;
}
if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)
|| !EC_POINT_get_affine_coordinates(group, kG, x1, NULL,
ctx)
|| !BN_mod_add(r, e, x1, order, ctx)) {
SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);
goto done;
}
/* try again if r == 0 or r+k == n */
if (BN_is_zero(r))
continue;
if (!BN_add(rk, r, k)) {
SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);
goto done;
}
if (BN_cmp(rk, order) == 0)
continue;
if (!BN_add(s, dA, BN_value_one())
|| !ec_group_do_inverse_ord(group, s, s, ctx)
|| !BN_mod_mul(tmp, dA, r, order, ctx)
|| !BN_sub(tmp, k, tmp)
|| !BN_mod_mul(s, s, tmp, order, ctx)) {
SM2err(SM2_F_SM2_SIG_GEN, ERR_R_BN_LIB);
goto done;
}
sig = ECDSA_SIG_new();
if (sig == NULL) {
SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);
goto done;
}
/* takes ownership of r and s */
ECDSA_SIG_set0(sig, r, s);
break;
}
done:
if (sig == NULL) {
BN_free(r);
BN_free(s);
}
BN_CTX_free(ctx);
EC_POINT_free(kG);
return sig;
}
static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,
const BIGNUM *e)
{
int ret = 0;
const EC_GROUP *group = EC_KEY_get0_group(key);
const BIGNUM *order = EC_GROUP_get0_order(group);
BN_CTX *ctx = NULL;
EC_POINT *pt = NULL;
BIGNUM *t = NULL;
BIGNUM *x1 = NULL;
const BIGNUM *r = NULL;
const BIGNUM *s = NULL;
ctx = BN_CTX_new();
pt = EC_POINT_new(group);
if (ctx == NULL || pt == NULL) {
SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE);
goto done;
}
BN_CTX_start(ctx);
t = BN_CTX_get(ctx);
x1 = BN_CTX_get(ctx);
if (x1 == NULL) {
SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE);
goto done;
}
/*
* B1: verify whether r' in [1,n-1], verification failed if not
* B2: vefify whether s' in [1,n-1], verification failed if not
* B3: set M'~=ZA || M'
* B4: calculate e'=Hv(M'~)
* B5: calculate t = (r' + s') modn, verification failed if t=0
* B6: calculate the point (x1', y1')=[s']G + [t]PA
* B7: calculate R=(e'+x1') modn, verfication pass if yes, otherwise failed
*/
ECDSA_SIG_get0(sig, &r, &s);
if (BN_cmp(r, BN_value_one()) < 0
|| BN_cmp(s, BN_value_one()) < 0
|| BN_cmp(order, r) <= 0
|| BN_cmp(order, s) <= 0) {
SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE);
goto done;
}
if (!BN_mod_add(t, r, s, order, ctx)) {
SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB);
goto done;
}
if (BN_is_zero(t)) {
SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE);
goto done;
}
if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx)
|| !EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) {
SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_EC_LIB);
goto done;
}
if (!BN_mod_add(t, e, x1, order, ctx)) {
SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB);
goto done;
}
if (BN_cmp(r, t) == 0)
ret = 1;
done:
EC_POINT_free(pt);
BN_CTX_free(ctx);
return ret;
}
ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
const EVP_MD *digest,
const uint8_t *id,
const size_t id_len,
const uint8_t *msg, size_t msg_len)
{
BIGNUM *e = NULL;
ECDSA_SIG *sig = NULL;
e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);
if (e == NULL) {
/* SM2err already called */
goto done;
}
sig = sm2_sig_gen(key, e);
done:
BN_free(e);
return sig;
}
int sm2_do_verify(const EC_KEY *key,
const EVP_MD *digest,
const ECDSA_SIG *sig,
const uint8_t *id,
const size_t id_len,
const uint8_t *msg, size_t msg_len)
{
BIGNUM *e = NULL;
int ret = 0;
e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);
if (e == NULL) {
/* SM2err already called */
goto done;
}
ret = sm2_sig_verify(key, sig, e);
done:
BN_free(e);
return ret;
}
int sm2_sign(const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen, EC_KEY *eckey)
{
BIGNUM *e = NULL;
ECDSA_SIG *s = NULL;
int sigleni;
int ret = -1;
e = BN_bin2bn(dgst, dgstlen, NULL);
if (e == NULL) {
SM2err(SM2_F_SM2_SIGN, ERR_R_BN_LIB);
goto done;
}
s = sm2_sig_gen(eckey, e);
sigleni = i2d_ECDSA_SIG(s, &sig);
if (sigleni < 0) {
SM2err(SM2_F_SM2_SIGN, ERR_R_INTERNAL_ERROR);
goto done;
}
*siglen = (unsigned int)sigleni;
ret = 1;
done:
ECDSA_SIG_free(s);
BN_free(e);
return ret;
}
int sm2_verify(const unsigned char *dgst, int dgstlen,
const unsigned char *sig, int sig_len, EC_KEY *eckey)
{
ECDSA_SIG *s = NULL;
BIGNUM *e = NULL;
const unsigned char *p = sig;
unsigned char *der = NULL;
int derlen = -1;
int ret = -1;
s = ECDSA_SIG_new();
if (s == NULL) {
SM2err(SM2_F_SM2_VERIFY, ERR_R_MALLOC_FAILURE);
goto done;
}
if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) {
SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING);
goto done;
}
/* Ensure signature uses DER and doesn't have trailing garbage */
derlen = i2d_ECDSA_SIG(s, &der);
if (derlen != sig_len || memcmp(sig, der, derlen) != 0) {
SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING);
goto done;
}
e = BN_bin2bn(dgst, dgstlen, NULL);
if (e == NULL) {
SM2err(SM2_F_SM2_VERIFY, ERR_R_BN_LIB);
goto done;
}
ret = sm2_sig_verify(eckey, s, e);
done:
OPENSSL_free(der);
BN_free(e);
ECDSA_SIG_free(s);
return ret;
}
diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c
index 45d48202b561..6b996134df49 100644
--- a/crypto/ui/ui_openssl.c
+++ b/crypto/ui/ui_openssl.c
@@ -1,720 +1,738 @@
/*
* Copyright 2001-2018 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 <openssl/e_os2.h>
#include <openssl/err.h>
#include <openssl/ui.h>
#ifndef OPENSSL_NO_UI_CONSOLE
/*
* need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc
* [maybe others?], because it masks interfaces not discussed in standard,
* sigaction and fileno included. -pedantic would be more appropriate for the
* intended purposes, but we can't prevent users from adding -ansi.
*/
# if defined(OPENSSL_SYS_VXWORKS)
# include <sys/types.h>
# endif
# if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
# ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 2
# endif
# endif
# include <signal.h>
# include <stdio.h>
# include <string.h>
# include <errno.h>
# if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
# ifdef OPENSSL_UNISTD
# include OPENSSL_UNISTD
# else
# include <unistd.h>
# endif
/*
* If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX
* system and have sigaction and termios.
*/
# if defined(_POSIX_VERSION) && _POSIX_VERSION>=199309L
# define SIGACTION
# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
# define TERMIOS
# endif
# endif
# endif
# include "ui_locl.h"
# include "internal/cryptlib.h"
# ifdef OPENSSL_SYS_VMS /* prototypes for sys$whatever */
# include <starlet.h>
# ifdef __DECC
# pragma message disable DOLLARID
# endif
# endif
# ifdef WIN_CONSOLE_BUG
# include <windows.h>
# ifndef OPENSSL_SYS_WINCE
# include <wincon.h>
# endif
# endif
/*
* There are 6 types of terminal interface supported, TERMIO, TERMIOS, VMS,
* MSDOS, WIN32 Console and SGTTY.
*
* If someone defines one of the macros TERMIO, TERMIOS or SGTTY, it will
* remain respected. Otherwise, we default to TERMIOS except for a few
* systems that require something different.
*
* Note: we do not use SGTTY unless it's defined by the configuration. We
* may eventually opt to remove it's use entirely.
*/
# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
# if defined(_LIBC)
# undef TERMIOS
# define TERMIO
# undef SGTTY
/*
* We know that VMS, MSDOS, VXWORKS, use entirely other mechanisms.
*/
# elif !defined(OPENSSL_SYS_VMS) \
&& !defined(OPENSSL_SYS_MSDOS) \
&& !defined(OPENSSL_SYS_VXWORKS)
# define TERMIOS
# undef TERMIO
# undef SGTTY
# endif
# endif
# ifdef TERMIOS
# include <termios.h>
# define TTY_STRUCT struct termios
# define TTY_FLAGS c_lflag
# define TTY_get(tty,data) tcgetattr(tty,data)
# define TTY_set(tty,data) tcsetattr(tty,TCSANOW,data)
# endif
# ifdef TERMIO
# include <termio.h>
# define TTY_STRUCT struct termio
# define TTY_FLAGS c_lflag
# define TTY_get(tty,data) ioctl(tty,TCGETA,data)
# define TTY_set(tty,data) ioctl(tty,TCSETA,data)
# endif
# ifdef SGTTY
# include <sgtty.h>
# define TTY_STRUCT struct sgttyb
# define TTY_FLAGS sg_flags
# define TTY_get(tty,data) ioctl(tty,TIOCGETP,data)
# define TTY_set(tty,data) ioctl(tty,TIOCSETP,data)
# endif
# if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
# include <sys/ioctl.h>
# endif
# ifdef OPENSSL_SYS_MSDOS
# include <conio.h>
# endif
# ifdef OPENSSL_SYS_VMS
# include <ssdef.h>
# include <iodef.h>
# include <ttdef.h>
# include <descrip.h>
struct IOSB {
short iosb$w_value;
short iosb$w_count;
long iosb$l_info;
};
# endif
# ifndef NX509_SIG
# define NX509_SIG 32
# endif
/* Define globals. They are protected by a lock */
# ifdef SIGACTION
static struct sigaction savsig[NX509_SIG];
# else
static void (*savsig[NX509_SIG]) (int);
# endif
# ifdef OPENSSL_SYS_VMS
static struct IOSB iosb;
static $DESCRIPTOR(terminal, "TT");
static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this
* will always suffice for the actual
* structures? */
static long status;
static unsigned short channel = 0;
# elif defined(_WIN32) && !defined(_WIN32_WCE)
static DWORD tty_orig, tty_new;
# else
# if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
static TTY_STRUCT tty_orig, tty_new;
# endif
# endif
static FILE *tty_in, *tty_out;
static int is_a_tty;
/* Declare static functions */
# if !defined(OPENSSL_SYS_WINCE)
static int read_till_nl(FILE *);
static void recsig(int);
static void pushsig(void);
static void popsig(void);
# endif
# if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
static int noecho_fgets(char *buf, int size, FILE *tty);
# endif
static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
static int read_string(UI *ui, UI_STRING *uis);
static int write_string(UI *ui, UI_STRING *uis);
static int open_console(UI *ui);
static int echo_console(UI *ui);
static int noecho_console(UI *ui);
static int close_console(UI *ui);
/*
* The following function makes sure that info and error strings are printed
* before any prompt.
*/
static int write_string(UI *ui, UI_STRING *uis)
{
switch (UI_get_string_type(uis)) {
case UIT_ERROR:
case UIT_INFO:
fputs(UI_get0_output_string(uis), tty_out);
fflush(tty_out);
break;
case UIT_NONE:
case UIT_PROMPT:
case UIT_VERIFY:
case UIT_BOOLEAN:
break;
}
return 1;
}
static int read_string(UI *ui, UI_STRING *uis)
{
int ok = 0;
switch (UI_get_string_type(uis)) {
case UIT_BOOLEAN:
fputs(UI_get0_output_string(uis), tty_out);
fputs(UI_get0_action_string(uis), tty_out);
fflush(tty_out);
return read_string_inner(ui, uis,
UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
0);
case UIT_PROMPT:
fputs(UI_get0_output_string(uis), tty_out);
fflush(tty_out);
return read_string_inner(ui, uis,
UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
1);
case UIT_VERIFY:
fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis));
fflush(tty_out);
if ((ok = read_string_inner(ui, uis,
UI_get_input_flags(uis) &
UI_INPUT_FLAG_ECHO, 1)) <= 0)
return ok;
if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) {
fprintf(tty_out, "Verify failure\n");
fflush(tty_out);
return 0;
}
break;
case UIT_NONE:
case UIT_INFO:
case UIT_ERROR:
break;
}
return 1;
}
# if !defined(OPENSSL_SYS_WINCE)
/* Internal functions to read a string without echoing */
static int read_till_nl(FILE *in)
{
# define SIZE 4
char buf[SIZE + 1];
do {
if (!fgets(buf, SIZE, in))
return 0;
} while (strchr(buf, '\n') == NULL);
return 1;
}
static volatile sig_atomic_t intr_signal;
# endif
static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
{
static int ps;
int ok;
char result[BUFSIZ];
int maxsize = BUFSIZ - 1;
# if !defined(OPENSSL_SYS_WINCE)
char *p = NULL;
int echo_eol = !echo;
intr_signal = 0;
ok = 0;
ps = 0;
pushsig();
ps = 1;
if (!echo && !noecho_console(ui))
goto error;
ps = 2;
result[0] = '\0';
# if defined(_WIN32)
if (is_a_tty) {
DWORD numread;
# if defined(CP_UTF8)
if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) {
WCHAR wresult[BUFSIZ];
if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE),
wresult, maxsize, &numread, NULL)) {
if (numread >= 2 &&
wresult[numread-2] == L'\r' &&
wresult[numread-1] == L'\n') {
wresult[numread-2] = L'\n';
numread--;
}
wresult[numread] = '\0';
if (WideCharToMultiByte(CP_UTF8, 0, wresult, -1,
result, sizeof(result), NULL, 0) > 0)
p = result;
OPENSSL_cleanse(wresult, sizeof(wresult));
}
} else
# endif
if (ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE),
result, maxsize, &numread, NULL)) {
if (numread >= 2 &&
result[numread-2] == '\r' && result[numread-1] == '\n') {
result[numread-2] = '\n';
numread--;
}
result[numread] = '\0';
p = result;
}
} else
# elif defined(OPENSSL_SYS_MSDOS)
if (!echo) {
noecho_fgets(result, maxsize, tty_in);
p = result; /* FIXME: noecho_fgets doesn't return errors */
} else
# endif
p = fgets(result, maxsize, tty_in);
if (p == NULL)
goto error;
if (feof(tty_in))
goto error;
if (ferror(tty_in))
goto error;
if ((p = (char *)strchr(result, '\n')) != NULL) {
if (strip_nl)
*p = '\0';
} else if (!read_till_nl(tty_in))
goto error;
if (UI_set_result(ui, uis, result) >= 0)
ok = 1;
error:
if (intr_signal == SIGINT)
ok = -1;
if (echo_eol)
fprintf(tty_out, "\n");
if (ps >= 2 && !echo && !echo_console(ui))
ok = 0;
if (ps >= 1)
popsig();
# else
ok = 1;
# endif
OPENSSL_cleanse(result, BUFSIZ);
return ok;
}
/* Internal functions to open, handle and close a channel to the console. */
static int open_console(UI *ui)
{
CRYPTO_THREAD_write_lock(ui->lock);
is_a_tty = 1;
# if defined(OPENSSL_SYS_VXWORKS)
tty_in = stdin;
tty_out = stderr;
# elif defined(_WIN32) && !defined(_WIN32_WCE)
if ((tty_out = fopen("conout$", "w")) == NULL)
tty_out = stderr;
if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &tty_orig)) {
tty_in = stdin;
} else {
is_a_tty = 0;
if ((tty_in = fopen("conin$", "r")) == NULL)
tty_in = stdin;
}
# else
# ifdef OPENSSL_SYS_MSDOS
# define DEV_TTY "con"
# else
# define DEV_TTY "/dev/tty"
# endif
if ((tty_in = fopen(DEV_TTY, "r")) == NULL)
tty_in = stdin;
if ((tty_out = fopen(DEV_TTY, "w")) == NULL)
tty_out = stderr;
# endif
# if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
if (TTY_get(fileno(tty_in), &tty_orig) == -1) {
# ifdef ENOTTY
if (errno == ENOTTY)
is_a_tty = 0;
else
# endif
# ifdef EINVAL
/*
* Ariel Glenn reports that solaris can return EINVAL instead.
* This should be ok
*/
if (errno == EINVAL)
is_a_tty = 0;
else
# endif
+# ifdef ENXIO
+ /*
+ * Solaris can return ENXIO.
+ * This should be ok
+ */
+ if (errno == ENXIO)
+ is_a_tty = 0;
+ else
+# endif
+# ifdef EIO
+ /*
+ * Linux can return EIO.
+ * This should be ok
+ */
+ if (errno == EIO)
+ is_a_tty = 0;
+ else
+# endif
# ifdef ENODEV
/*
* MacOS X returns ENODEV (Operation not supported by device),
* which seems appropriate.
*/
if (errno == ENODEV)
is_a_tty = 0;
else
# endif
{
char tmp_num[10];
BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%d", errno);
UIerr(UI_F_OPEN_CONSOLE, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE);
ERR_add_error_data(2, "errno=", tmp_num);
return 0;
}
}
# endif
# ifdef OPENSSL_SYS_VMS
status = sys$assign(&terminal, &channel, 0, 0);
/* if there isn't a TT device, something is very wrong */
if (status != SS$_NORMAL) {
char tmp_num[12];
BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status);
UIerr(UI_F_OPEN_CONSOLE, UI_R_SYSASSIGN_ERROR);
ERR_add_error_data(2, "status=", tmp_num);
return 0;
}
status = sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12,
0, 0, 0, 0);
/* If IO$_SENSEMODE doesn't work, this is not a terminal device */
if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
is_a_tty = 0;
# endif
return 1;
}
static int noecho_console(UI *ui)
{
# ifdef TTY_FLAGS
memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
tty_new.TTY_FLAGS &= ~ECHO;
# endif
# if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
return 0;
# endif
# ifdef OPENSSL_SYS_VMS
if (is_a_tty) {
tty_new[0] = tty_orig[0];
tty_new[1] = tty_orig[1] | TT$M_NOECHO;
tty_new[2] = tty_orig[2];
status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
0, 0, 0, 0);
if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
char tmp_num[2][12];
BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X",
status);
BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X",
iosb.iosb$w_value);
UIerr(UI_F_NOECHO_CONSOLE, UI_R_SYSQIOW_ERROR);
ERR_add_error_data(5, "status=", tmp_num[0],
",", "iosb.iosb$w_value=", tmp_num[1]);
return 0;
}
}
# endif
# if defined(_WIN32) && !defined(_WIN32_WCE)
if (is_a_tty) {
tty_new = tty_orig;
tty_new &= ~ENABLE_ECHO_INPUT;
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new);
}
# endif
return 1;
}
static int echo_console(UI *ui)
{
# if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
return 0;
# endif
# ifdef OPENSSL_SYS_VMS
if (is_a_tty) {
tty_new[0] = tty_orig[0];
tty_new[1] = tty_orig[1];
tty_new[2] = tty_orig[2];
status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
0, 0, 0, 0);
if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
char tmp_num[2][12];
BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X",
status);
BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X",
iosb.iosb$w_value);
UIerr(UI_F_ECHO_CONSOLE, UI_R_SYSQIOW_ERROR);
ERR_add_error_data(5, "status=", tmp_num[0],
",", "iosb.iosb$w_value=", tmp_num[1]);
return 0;
}
}
# endif
# if defined(_WIN32) && !defined(_WIN32_WCE)
if (is_a_tty) {
tty_new = tty_orig;
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new);
}
# endif
return 1;
}
static int close_console(UI *ui)
{
if (tty_in != stdin)
fclose(tty_in);
if (tty_out != stderr)
fclose(tty_out);
# ifdef OPENSSL_SYS_VMS
status = sys$dassgn(channel);
if (status != SS$_NORMAL) {
char tmp_num[12];
BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status);
UIerr(UI_F_CLOSE_CONSOLE, UI_R_SYSDASSGN_ERROR);
ERR_add_error_data(2, "status=", tmp_num);
return 0;
}
# endif
CRYPTO_THREAD_unlock(ui->lock);
return 1;
}
# if !defined(OPENSSL_SYS_WINCE)
/* Internal functions to handle signals and act on them */
static void pushsig(void)
{
# ifndef OPENSSL_SYS_WIN32
int i;
# endif
# ifdef SIGACTION
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = recsig;
# endif
# ifdef OPENSSL_SYS_WIN32
savsig[SIGABRT] = signal(SIGABRT, recsig);
savsig[SIGFPE] = signal(SIGFPE, recsig);
savsig[SIGILL] = signal(SIGILL, recsig);
savsig[SIGINT] = signal(SIGINT, recsig);
savsig[SIGSEGV] = signal(SIGSEGV, recsig);
savsig[SIGTERM] = signal(SIGTERM, recsig);
# else
for (i = 1; i < NX509_SIG; i++) {
# ifdef SIGUSR1
if (i == SIGUSR1)
continue;
# endif
# ifdef SIGUSR2
if (i == SIGUSR2)
continue;
# endif
# ifdef SIGKILL
if (i == SIGKILL) /* We can't make any action on that. */
continue;
# endif
# ifdef SIGACTION
sigaction(i, &sa, &savsig[i]);
# else
savsig[i] = signal(i, recsig);
# endif
}
# endif
# ifdef SIGWINCH
signal(SIGWINCH, SIG_DFL);
# endif
}
static void popsig(void)
{
# ifdef OPENSSL_SYS_WIN32
signal(SIGABRT, savsig[SIGABRT]);
signal(SIGFPE, savsig[SIGFPE]);
signal(SIGILL, savsig[SIGILL]);
signal(SIGINT, savsig[SIGINT]);
signal(SIGSEGV, savsig[SIGSEGV]);
signal(SIGTERM, savsig[SIGTERM]);
# else
int i;
for (i = 1; i < NX509_SIG; i++) {
# ifdef SIGUSR1
if (i == SIGUSR1)
continue;
# endif
# ifdef SIGUSR2
if (i == SIGUSR2)
continue;
# endif
# ifdef SIGACTION
sigaction(i, &savsig[i], NULL);
# else
signal(i, savsig[i]);
# endif
}
# endif
}
static void recsig(int i)
{
intr_signal = i;
}
# endif
/* Internal functions specific for Windows */
# if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
static int noecho_fgets(char *buf, int size, FILE *tty)
{
int i;
char *p;
p = buf;
for (;;) {
if (size == 0) {
*p = '\0';
break;
}
size--;
# if defined(_WIN32)
i = _getch();
# else
i = getch();
# endif
if (i == '\r')
i = '\n';
*(p++) = i;
if (i == '\n') {
*p = '\0';
break;
}
}
# ifdef WIN_CONSOLE_BUG
/*
* Win95 has several evil console bugs: one of these is that the last
* character read using getch() is passed to the next read: this is
* usually a CR so this can be trouble. No STDIO fix seems to work but
* flushing the console appears to do the trick.
*/
{
HANDLE inh;
inh = GetStdHandle(STD_INPUT_HANDLE);
FlushConsoleInputBuffer(inh);
}
# endif
return strlen(buf);
}
# endif
static UI_METHOD ui_openssl = {
"OpenSSL default user interface",
open_console,
write_string,
NULL, /* No flusher is needed for command lines */
read_string,
close_console,
NULL
};
/* The method with all the built-in console thingies */
UI_METHOD *UI_OpenSSL(void)
{
return &ui_openssl;
}
static const UI_METHOD *default_UI_meth = &ui_openssl;
#else
static const UI_METHOD *default_UI_meth = NULL;
#endif
void UI_set_default_method(const UI_METHOD *meth)
{
default_UI_meth = meth;
}
const UI_METHOD *UI_get_default_method(void)
{
return default_UI_meth;
}
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 11ac52ce3c55..b3760dbadf3a 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -1,390 +1,390 @@
/*
* Copyright 1995-2018 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.h"
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#ifndef OPENSSL_NO_POSIX_IO
# include <sys/stat.h>
#endif
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include "x509_lcl.h"
struct lookup_dir_hashes_st {
unsigned long hash;
int suffix;
};
struct lookup_dir_entry_st {
char *dir;
int dir_type;
STACK_OF(BY_DIR_HASH) *hashes;
};
typedef struct lookup_dir_st {
BUF_MEM *buffer;
STACK_OF(BY_DIR_ENTRY) *dirs;
CRYPTO_RWLOCK *lock;
} BY_DIR;
static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
char **ret);
static int new_dir(X509_LOOKUP *lu);
static void free_dir(X509_LOOKUP *lu);
static int add_cert_dir(BY_DIR *ctx, const char *dir, int type);
static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret);
static X509_LOOKUP_METHOD x509_dir_lookup = {
"Load certs from files in a directory",
new_dir, /* new_item */
free_dir, /* free */
NULL, /* init */
NULL, /* shutdown */
dir_ctrl, /* ctrl */
get_cert_by_subject, /* get_by_subject */
NULL, /* get_by_issuer_serial */
NULL, /* get_by_fingerprint */
NULL, /* get_by_alias */
};
X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
{
return &x509_dir_lookup;
}
static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
char **retp)
{
int ret = 0;
BY_DIR *ld = (BY_DIR *)ctx->method_data;
switch (cmd) {
case X509_L_ADD_DIR:
if (argl == X509_FILETYPE_DEFAULT) {
- const char *dir = getenv(X509_get_default_cert_dir_env());
+ const char *dir = ossl_safe_getenv(X509_get_default_cert_dir_env());
if (dir)
ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM);
else
ret = add_cert_dir(ld, X509_get_default_cert_dir(),
X509_FILETYPE_PEM);
if (!ret) {
X509err(X509_F_DIR_CTRL, X509_R_LOADING_CERT_DIR);
}
} else
ret = add_cert_dir(ld, argp, (int)argl);
break;
}
return ret;
}
static int new_dir(X509_LOOKUP *lu)
{
BY_DIR *a = OPENSSL_malloc(sizeof(*a));
if (a == NULL) {
X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
return 0;
}
if ((a->buffer = BUF_MEM_new()) == NULL) {
X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
goto err;
}
a->dirs = NULL;
a->lock = CRYPTO_THREAD_lock_new();
if (a->lock == NULL) {
BUF_MEM_free(a->buffer);
X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
goto err;
}
lu->method_data = a;
return 1;
err:
OPENSSL_free(a);
return 0;
}
static void by_dir_hash_free(BY_DIR_HASH *hash)
{
OPENSSL_free(hash);
}
static int by_dir_hash_cmp(const BY_DIR_HASH *const *a,
const BY_DIR_HASH *const *b)
{
if ((*a)->hash > (*b)->hash)
return 1;
if ((*a)->hash < (*b)->hash)
return -1;
return 0;
}
static void by_dir_entry_free(BY_DIR_ENTRY *ent)
{
OPENSSL_free(ent->dir);
sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
OPENSSL_free(ent);
}
static void free_dir(X509_LOOKUP *lu)
{
BY_DIR *a = (BY_DIR *)lu->method_data;
sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
BUF_MEM_free(a->buffer);
CRYPTO_THREAD_lock_free(a->lock);
OPENSSL_free(a);
}
static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
{
int j;
size_t len;
const char *s, *ss, *p;
if (dir == NULL || !*dir) {
X509err(X509_F_ADD_CERT_DIR, X509_R_INVALID_DIRECTORY);
return 0;
}
s = dir;
p = s;
do {
if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0')) {
BY_DIR_ENTRY *ent;
ss = s;
s = p + 1;
len = p - ss;
if (len == 0)
continue;
for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) {
ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
if (strlen(ent->dir) == len && strncmp(ent->dir, ss, len) == 0)
break;
}
if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
continue;
if (ctx->dirs == NULL) {
ctx->dirs = sk_BY_DIR_ENTRY_new_null();
if (!ctx->dirs) {
X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
return 0;
}
}
ent = OPENSSL_malloc(sizeof(*ent));
if (ent == NULL) {
X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
return 0;
}
ent->dir_type = type;
ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
ent->dir = OPENSSL_strndup(ss, len);
if (ent->dir == NULL || ent->hashes == NULL) {
by_dir_entry_free(ent);
return 0;
}
if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) {
by_dir_entry_free(ent);
X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
return 0;
}
}
} while (*p++ != '\0');
return 1;
}
static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret)
{
BY_DIR *ctx;
union {
X509 st_x509;
X509_CRL crl;
} data;
int ok = 0;
int i, j, k;
unsigned long h;
BUF_MEM *b = NULL;
X509_OBJECT stmp, *tmp;
const char *postfix = "";
if (name == NULL)
return 0;
stmp.type = type;
if (type == X509_LU_X509) {
data.st_x509.cert_info.subject = name;
stmp.data.x509 = &data.st_x509;
postfix = "";
} else if (type == X509_LU_CRL) {
data.crl.crl.issuer = name;
stmp.data.crl = &data.crl;
postfix = "r";
} else {
X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE);
goto finish;
}
if ((b = BUF_MEM_new()) == NULL) {
X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB);
goto finish;
}
ctx = (BY_DIR *)xl->method_data;
h = X509_NAME_hash(name);
for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {
BY_DIR_ENTRY *ent;
int idx;
BY_DIR_HASH htmp, *hent;
ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
if (!BUF_MEM_grow(b, j)) {
X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
goto finish;
}
if (type == X509_LU_CRL && ent->hashes) {
htmp.hash = h;
CRYPTO_THREAD_read_lock(ctx->lock);
idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
if (idx >= 0) {
hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
k = hent->suffix;
} else {
hent = NULL;
k = 0;
}
CRYPTO_THREAD_unlock(ctx->lock);
} else {
k = 0;
hent = NULL;
}
for (;;) {
char c = '/';
#ifdef OPENSSL_SYS_VMS
c = ent->dir[strlen(ent->dir) - 1];
if (c != ':' && c != '>' && c != ']') {
/*
* If no separator is present, we assume the directory
* specifier is a logical name, and add a colon. We really
* should use better VMS routines for merging things like
* this, but this will do for now... -- Richard Levitte
*/
c = ':';
} else {
c = '\0';
}
#endif
if (c == '\0') {
/*
* This is special. When c == '\0', no directory separator
* should be added.
*/
BIO_snprintf(b->data, b->max,
"%s%08lx.%s%d", ent->dir, h, postfix, k);
} else {
BIO_snprintf(b->data, b->max,
"%s%c%08lx.%s%d", ent->dir, c, h, postfix, k);
}
#ifndef OPENSSL_NO_POSIX_IO
# ifdef _WIN32
# define stat _stat
# endif
{
struct stat st;
if (stat(b->data, &st) < 0)
break;
}
#endif
/* found one. */
if (type == X509_LU_X509) {
if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0)
break;
} else if (type == X509_LU_CRL) {
if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
break;
}
/* else case will caught higher up */
k++;
}
/*
* we have added it to the cache so now pull it out again
*/
CRYPTO_THREAD_write_lock(ctx->lock);
j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);
tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);
CRYPTO_THREAD_unlock(ctx->lock);
/* If a CRL, update the last file suffix added for this */
if (type == X509_LU_CRL) {
CRYPTO_THREAD_write_lock(ctx->lock);
/*
* Look for entry again in case another thread added an entry
* first.
*/
if (hent == NULL) {
htmp.hash = h;
idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
}
if (hent == NULL) {
hent = OPENSSL_malloc(sizeof(*hent));
if (hent == NULL) {
CRYPTO_THREAD_unlock(ctx->lock);
X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
ok = 0;
goto finish;
}
hent->hash = h;
hent->suffix = k;
if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
CRYPTO_THREAD_unlock(ctx->lock);
OPENSSL_free(hent);
X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
ok = 0;
goto finish;
}
} else if (hent->suffix < k) {
hent->suffix = k;
}
CRYPTO_THREAD_unlock(ctx->lock);
}
if (tmp != NULL) {
ok = 1;
ret->type = tmp->type;
memcpy(&ret->data, &tmp->data, sizeof(ret->data));
/*
* Clear any errors that might have been raised processing empty
* or malformed files.
*/
ERR_clear_error();
goto finish;
}
}
finish:
BUF_MEM_free(b);
return ok;
}
diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c
index 78d7fbdf4488..244512c9352b 100644
--- a/crypto/x509/by_file.c
+++ b/crypto/x509/by_file.c
@@ -1,227 +1,227 @@
/*
* Copyright 1995-2018 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 <errno.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include "x509_lcl.h"
static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
long argl, char **ret);
static X509_LOOKUP_METHOD x509_file_lookup = {
"Load file into cache",
NULL, /* new_item */
NULL, /* free */
NULL, /* init */
NULL, /* shutdown */
by_file_ctrl, /* ctrl */
NULL, /* get_by_subject */
NULL, /* get_by_issuer_serial */
NULL, /* get_by_fingerprint */
NULL, /* get_by_alias */
};
X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
{
return &x509_file_lookup;
}
static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
long argl, char **ret)
{
int ok = 0;
const char *file;
switch (cmd) {
case X509_L_FILE_LOAD:
if (argl == X509_FILETYPE_DEFAULT) {
- file = getenv(X509_get_default_cert_file_env());
+ file = ossl_safe_getenv(X509_get_default_cert_file_env());
if (file)
ok = (X509_load_cert_crl_file(ctx, file,
X509_FILETYPE_PEM) != 0);
else
ok = (X509_load_cert_crl_file
(ctx, X509_get_default_cert_file(),
X509_FILETYPE_PEM) != 0);
if (!ok) {
X509err(X509_F_BY_FILE_CTRL, X509_R_LOADING_DEFAULTS);
}
} else {
if (argl == X509_FILETYPE_PEM)
ok = (X509_load_cert_crl_file(ctx, argp,
X509_FILETYPE_PEM) != 0);
else
ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0);
}
break;
}
return ok;
}
int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
{
int ret = 0;
BIO *in = NULL;
int i, count = 0;
X509 *x = NULL;
in = BIO_new(BIO_s_file());
if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB);
goto err;
}
if (type == X509_FILETYPE_PEM) {
for (;;) {
x = PEM_read_bio_X509_AUX(in, NULL, NULL, "");
if (x == NULL) {
if ((ERR_GET_REASON(ERR_peek_last_error()) ==
PEM_R_NO_START_LINE) && (count > 0)) {
ERR_clear_error();
break;
} else {
X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_PEM_LIB);
goto err;
}
}
i = X509_STORE_add_cert(ctx->store_ctx, x);
if (!i)
goto err;
count++;
X509_free(x);
x = NULL;
}
ret = count;
} else if (type == X509_FILETYPE_ASN1) {
x = d2i_X509_bio(in, NULL);
if (x == NULL) {
X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_ASN1_LIB);
goto err;
}
i = X509_STORE_add_cert(ctx->store_ctx, x);
if (!i)
goto err;
ret = i;
} else {
X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE);
goto err;
}
if (ret == 0)
X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_NO_CERTIFICATE_FOUND);
err:
X509_free(x);
BIO_free(in);
return ret;
}
int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
{
int ret = 0;
BIO *in = NULL;
int i, count = 0;
X509_CRL *x = NULL;
in = BIO_new(BIO_s_file());
if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB);
goto err;
}
if (type == X509_FILETYPE_PEM) {
for (;;) {
x = PEM_read_bio_X509_CRL(in, NULL, NULL, "");
if (x == NULL) {
if ((ERR_GET_REASON(ERR_peek_last_error()) ==
PEM_R_NO_START_LINE) && (count > 0)) {
ERR_clear_error();
break;
} else {
X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_PEM_LIB);
goto err;
}
}
i = X509_STORE_add_crl(ctx->store_ctx, x);
if (!i)
goto err;
count++;
X509_CRL_free(x);
x = NULL;
}
ret = count;
} else if (type == X509_FILETYPE_ASN1) {
x = d2i_X509_CRL_bio(in, NULL);
if (x == NULL) {
X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_ASN1_LIB);
goto err;
}
i = X509_STORE_add_crl(ctx->store_ctx, x);
if (!i)
goto err;
ret = i;
} else {
X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE);
goto err;
}
if (ret == 0)
X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_NO_CRL_FOUND);
err:
X509_CRL_free(x);
BIO_free(in);
return ret;
}
int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
{
STACK_OF(X509_INFO) *inf;
X509_INFO *itmp;
BIO *in;
int i, count = 0;
if (type != X509_FILETYPE_PEM)
return X509_load_cert_file(ctx, file, type);
in = BIO_new_file(file, "r");
if (!in) {
X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
return 0;
}
inf = PEM_X509_INFO_read_bio(in, NULL, NULL, "");
BIO_free(in);
if (!inf) {
X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
return 0;
}
for (i = 0; i < sk_X509_INFO_num(inf); i++) {
itmp = sk_X509_INFO_value(inf, i);
if (itmp->x509) {
if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509))
goto err;
count++;
}
if (itmp->crl) {
if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl))
goto err;
count++;
}
}
if (count == 0)
X509err(X509_F_X509_LOAD_CERT_CRL_FILE,
X509_R_NO_CERTIFICATE_OR_CRL_FOUND);
err:
sk_X509_INFO_pop_free(inf, X509_INFO_free);
return count;
}
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 3a60d412daf8..61e81922b4da 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -1,3269 +1,3268 @@
/*
* Copyright 1995-2018 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 <errno.h>
#include <limits.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include "internal/dane.h"
#include "internal/x509_int.h"
#include "x509_lcl.h"
/* CRL score values */
/* No unhandled critical extensions */
#define CRL_SCORE_NOCRITICAL 0x100
/* certificate is within CRL scope */
#define CRL_SCORE_SCOPE 0x080
/* CRL times valid */
#define CRL_SCORE_TIME 0x040
/* Issuer name matches certificate */
#define CRL_SCORE_ISSUER_NAME 0x020
/* If this score or above CRL is probably valid */
#define CRL_SCORE_VALID (CRL_SCORE_NOCRITICAL|CRL_SCORE_TIME|CRL_SCORE_SCOPE)
/* CRL issuer is certificate issuer */
#define CRL_SCORE_ISSUER_CERT 0x018
/* CRL issuer is on certificate path */
#define CRL_SCORE_SAME_PATH 0x008
/* CRL issuer matches CRL AKID */
#define CRL_SCORE_AKID 0x004
/* Have a delta CRL with valid times */
#define CRL_SCORE_TIME_DELTA 0x002
static int build_chain(X509_STORE_CTX *ctx);
static int verify_chain(X509_STORE_CTX *ctx);
static int dane_verify(X509_STORE_CTX *ctx);
static int null_callback(int ok, X509_STORE_CTX *e);
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
static int check_chain_extensions(X509_STORE_CTX *ctx);
static int check_name_constraints(X509_STORE_CTX *ctx);
static int check_id(X509_STORE_CTX *ctx);
static int check_trust(X509_STORE_CTX *ctx, int num_untrusted);
static int check_revocation(X509_STORE_CTX *ctx);
static int check_cert(X509_STORE_CTX *ctx);
static int check_policy(X509_STORE_CTX *ctx);
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth);
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert);
static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert);
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
unsigned int *preasons, X509_CRL *crl, X509 *x);
static int get_crl_delta(X509_STORE_CTX *ctx,
X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x);
static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl,
int *pcrl_score, X509_CRL *base,
STACK_OF(X509_CRL) *crls);
static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer,
int *pcrl_score);
static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
unsigned int *preasons);
static int check_crl_path(X509_STORE_CTX *ctx, X509 *x);
static int check_crl_chain(X509_STORE_CTX *ctx,
STACK_OF(X509) *cert_path,
STACK_OF(X509) *crl_path);
static int internal_verify(X509_STORE_CTX *ctx);
static int null_callback(int ok, X509_STORE_CTX *e)
{
return ok;
}
/* Return 1 is a certificate is self signed */
static int cert_self_signed(X509 *x)
{
/*
* FIXME: x509v3_cache_extensions() needs to detect more failures and not
* set EXFLAG_SET when that happens. Especially, if the failures are
* parse errors, rather than memory pressure!
*/
X509_check_purpose(x, -1, 0);
if (x->ex_flags & EXFLAG_SS)
return 1;
else
return 0;
}
/* Given a certificate try and find an exact match in the store */
static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
{
STACK_OF(X509) *certs;
X509 *xtmp = NULL;
int i;
/* Lookup all certs with matching subject name */
certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
if (certs == NULL)
return NULL;
/* Look for exact match */
for (i = 0; i < sk_X509_num(certs); i++) {
xtmp = sk_X509_value(certs, i);
if (!X509_cmp(xtmp, x))
break;
}
if (i < sk_X509_num(certs))
X509_up_ref(xtmp);
else
xtmp = NULL;
sk_X509_pop_free(certs, X509_free);
return xtmp;
}
/*-
* Inform the verify callback of an error.
* If B<x> is not NULL it is the error cert, otherwise use the chain cert at
* B<depth>.
* If B<err> is not X509_V_OK, that's the error value, otherwise leave
* unchanged (presumably set by the caller).
*
* Returns 0 to abort verification with an error, non-zero to continue.
*/
static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err)
{
ctx->error_depth = depth;
ctx->current_cert = (x != NULL) ? x : sk_X509_value(ctx->chain, depth);
if (err != X509_V_OK)
ctx->error = err;
return ctx->verify_cb(0, ctx);
}
/*-
* Inform the verify callback of an error, CRL-specific variant. Here, the
* error depth and certificate are already set, we just specify the error
* number.
*
* Returns 0 to abort verification with an error, non-zero to continue.
*/
static int verify_cb_crl(X509_STORE_CTX *ctx, int err)
{
ctx->error = err;
return ctx->verify_cb(0, ctx);
}
static int check_auth_level(X509_STORE_CTX *ctx)
{
int i;
int num = sk_X509_num(ctx->chain);
if (ctx->param->auth_level <= 0)
return 1;
for (i = 0; i < num; ++i) {
X509 *cert = sk_X509_value(ctx->chain, i);
/*
* We've already checked the security of the leaf key, so here we only
* check the security of issuer keys.
*/
if (i > 0 && !check_key_level(ctx, cert) &&
verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL) == 0)
return 0;
/*
* We also check the signature algorithm security of all certificates
* except those of the trust anchor at index num-1.
*/
if (i < num - 1 && !check_sig_level(ctx, cert) &&
verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK) == 0)
return 0;
}
return 1;
}
static int verify_chain(X509_STORE_CTX *ctx)
{
int err;
int ok;
/*
* Before either returning with an error, or continuing with CRL checks,
* instantiate chain public key parameters.
*/
if ((ok = build_chain(ctx)) == 0 ||
(ok = check_chain_extensions(ctx)) == 0 ||
(ok = check_auth_level(ctx)) == 0 ||
(ok = check_id(ctx)) == 0 || 1)
X509_get_pubkey_parameters(NULL, ctx->chain);
if (ok == 0 || (ok = ctx->check_revocation(ctx)) == 0)
return ok;
err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
ctx->param->flags);
if (err != X509_V_OK) {
if ((ok = verify_cb_cert(ctx, NULL, ctx->error_depth, err)) == 0)
return ok;
}
/* Verify chain signatures and expiration times */
ok = (ctx->verify != NULL) ? ctx->verify(ctx) : internal_verify(ctx);
if (!ok)
return ok;
if ((ok = check_name_constraints(ctx)) == 0)
return ok;
#ifndef OPENSSL_NO_RFC3779
/* RFC 3779 path validation, now that CRL check has been done */
if ((ok = X509v3_asid_validate_path(ctx)) == 0)
return ok;
if ((ok = X509v3_addr_validate_path(ctx)) == 0)
return ok;
#endif
/* If we get this far evaluate policies */
if (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)
ok = ctx->check_policy(ctx);
return ok;
}
int X509_verify_cert(X509_STORE_CTX *ctx)
{
SSL_DANE *dane = ctx->dane;
int ret;
if (ctx->cert == NULL) {
X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
if (ctx->chain != NULL) {
/*
* This X509_STORE_CTX has already been used to verify a cert. We
* cannot do another one.
*/
X509err(X509_F_X509_VERIFY_CERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
/*
* first we make sure the chain we are going to build is present and that
* the first entry is in place
*/
if (((ctx->chain = sk_X509_new_null()) == NULL) ||
(!sk_X509_push(ctx->chain, ctx->cert))) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
X509_up_ref(ctx->cert);
ctx->num_untrusted = 1;
/* If the peer's public key is too weak, we can stop early. */
if (!check_key_level(ctx, ctx->cert) &&
!verify_cb_cert(ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL))
return 0;
if (DANETLS_ENABLED(dane))
ret = dane_verify(ctx);
else
ret = verify_chain(ctx);
/*
* Safety-net. If we are returning an error, we must also set ctx->error,
* so that the chain is not considered verified should the error be ignored
* (e.g. TLS with SSL_VERIFY_NONE).
*/
if (ret <= 0 && ctx->error == X509_V_OK)
ctx->error = X509_V_ERR_UNSPECIFIED;
return ret;
}
/*
* Given a STACK_OF(X509) find the issuer of cert (if any)
*/
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
{
int i;
X509 *issuer, *rv = NULL;
for (i = 0; i < sk_X509_num(sk); i++) {
issuer = sk_X509_value(sk, i);
if (ctx->check_issued(ctx, x, issuer)) {
rv = issuer;
if (x509_check_cert_time(ctx, rv, -1))
break;
}
}
return rv;
}
/* Given a possible certificate and issuer check them */
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
{
int ret;
if (x == issuer)
return cert_self_signed(x);
ret = X509_check_issued(issuer, x);
if (ret == X509_V_OK) {
int i;
X509 *ch;
/* Special case: single self signed certificate */
if (cert_self_signed(x) && sk_X509_num(ctx->chain) == 1)
return 1;
for (i = 0; i < sk_X509_num(ctx->chain); i++) {
ch = sk_X509_value(ctx->chain, i);
if (ch == issuer || !X509_cmp(ch, issuer)) {
ret = X509_V_ERR_PATH_LOOP;
break;
}
}
}
return (ret == X509_V_OK);
}
/* Alternative lookup method: look from a STACK stored in other_ctx */
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
*issuer = find_issuer(ctx, ctx->other_ctx, x);
if (*issuer) {
X509_up_ref(*issuer);
return 1;
} else
return 0;
}
static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm)
{
STACK_OF(X509) *sk = NULL;
X509 *x;
int i;
for (i = 0; i < sk_X509_num(ctx->other_ctx); i++) {
x = sk_X509_value(ctx->other_ctx, i);
if (X509_NAME_cmp(nm, X509_get_subject_name(x)) == 0) {
if (sk == NULL)
sk = sk_X509_new_null();
if (sk == NULL || sk_X509_push(sk, x) == 0) {
sk_X509_pop_free(sk, X509_free);
X509err(X509_F_LOOKUP_CERTS_SK, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return NULL;
}
X509_up_ref(x);
}
}
return sk;
}
/*
* Check EE or CA certificate purpose. For trusted certificates explicit local
* auxiliary trust can be used to override EKU-restrictions.
*/
static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
int must_be_ca)
{
int tr_ok = X509_TRUST_UNTRUSTED;
/*
* For trusted certificates we want to see whether any auxiliary trust
* settings trump the purpose constraints.
*
* This is complicated by the fact that the trust ordinals in
* ctx->param->trust are entirely independent of the purpose ordinals in
* ctx->param->purpose!
*
* What connects them is their mutual initialization via calls from
* X509_STORE_CTX_set_default() into X509_VERIFY_PARAM_lookup() which sets
* related values of both param->trust and param->purpose. It is however
* typically possible to infer associated trust values from a purpose value
* via the X509_PURPOSE API.
*
* Therefore, we can only check for trust overrides when the purpose we're
* checking is the same as ctx->param->purpose and ctx->param->trust is
* also set.
*/
if (depth >= ctx->num_untrusted && purpose == ctx->param->purpose)
tr_ok = X509_check_trust(x, ctx->param->trust, X509_TRUST_NO_SS_COMPAT);
switch (tr_ok) {
case X509_TRUST_TRUSTED:
return 1;
case X509_TRUST_REJECTED:
break;
default:
switch (X509_check_purpose(x, purpose, must_be_ca > 0)) {
case 1:
return 1;
case 0:
break;
default:
if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) == 0)
return 1;
}
break;
}
return verify_cb_cert(ctx, x, depth, X509_V_ERR_INVALID_PURPOSE);
}
/*
* Check a certificate chains extensions for consistency with the supplied
* purpose
*/
static int check_chain_extensions(X509_STORE_CTX *ctx)
{
int i, must_be_ca, plen = 0;
X509 *x;
int proxy_path_length = 0;
int purpose;
int allow_proxy_certs;
int num = sk_X509_num(ctx->chain);
/*-
* must_be_ca can have 1 of 3 values:
* -1: we accept both CA and non-CA certificates, to allow direct
* use of self-signed certificates (which are marked as CA).
* 0: we only accept non-CA certificates. This is currently not
* used, but the possibility is present for future extensions.
* 1: we only accept CA certificates. This is currently used for
* all certificates in the chain except the leaf certificate.
*/
must_be_ca = -1;
/* CRL path validation */
if (ctx->parent) {
allow_proxy_certs = 0;
purpose = X509_PURPOSE_CRL_SIGN;
} else {
allow_proxy_certs =
! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
purpose = ctx->param->purpose;
}
for (i = 0; i < num; i++) {
int ret;
x = sk_X509_value(ctx->chain, i);
if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
&& (x->ex_flags & EXFLAG_CRITICAL)) {
if (!verify_cb_cert(ctx, x, i,
X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION))
return 0;
}
if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) {
if (!verify_cb_cert(ctx, x, i,
X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED))
return 0;
}
ret = X509_check_ca(x);
switch (must_be_ca) {
case -1:
if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
&& (ret != 1) && (ret != 0)) {
ret = 0;
ctx->error = X509_V_ERR_INVALID_CA;
} else
ret = 1;
break;
case 0:
if (ret != 0) {
ret = 0;
ctx->error = X509_V_ERR_INVALID_NON_CA;
} else
ret = 1;
break;
default:
/* X509_V_FLAG_X509_STRICT is implicit for intermediate CAs */
if ((ret == 0)
|| ((i + 1 < num || ctx->param->flags & X509_V_FLAG_X509_STRICT)
&& (ret != 1))) {
ret = 0;
ctx->error = X509_V_ERR_INVALID_CA;
} else
ret = 1;
break;
}
if (ret == 0 && !verify_cb_cert(ctx, x, i, X509_V_OK))
return 0;
/* check_purpose() makes the callback as needed */
if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca))
return 0;
- /* Check pathlen if not self issued */
- if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
- && (x->ex_pathlen != -1)
- && (plen > (x->ex_pathlen + proxy_path_length + 1))) {
+ /* Check pathlen */
+ if ((i > 1) && (x->ex_pathlen != -1)
+ && (plen > (x->ex_pathlen + proxy_path_length))) {
if (!verify_cb_cert(ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED))
return 0;
}
- /* Increment path length if not self issued */
- if (!(x->ex_flags & EXFLAG_SI))
+ /* Increment path length if not a self issued intermediate CA */
+ if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0)
plen++;
/*
* If this certificate is a proxy certificate, the next certificate
* must be another proxy certificate or a EE certificate. If not,
* the next certificate must be a CA certificate.
*/
if (x->ex_flags & EXFLAG_PROXY) {
/*
* RFC3820, 4.1.3 (b)(1) stipulates that if pCPathLengthConstraint
* is less than max_path_length, the former should be copied to
* the latter, and 4.1.4 (a) stipulates that max_path_length
* should be verified to be larger than zero and decrement it.
*
* Because we're checking the certs in the reverse order, we start
* with verifying that proxy_path_length isn't larger than pcPLC,
* and copy the latter to the former if it is, and finally,
* increment proxy_path_length.
*/
if (x->ex_pcpathlen != -1) {
if (proxy_path_length > x->ex_pcpathlen) {
if (!verify_cb_cert(ctx, x, i,
X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED))
return 0;
}
proxy_path_length = x->ex_pcpathlen;
}
proxy_path_length++;
must_be_ca = 0;
} else
must_be_ca = 1;
}
return 1;
}
static int has_san_id(X509 *x, int gtype)
{
int i;
int ret = 0;
GENERAL_NAMES *gs = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
if (gs == NULL)
return 0;
for (i = 0; i < sk_GENERAL_NAME_num(gs); i++) {
GENERAL_NAME *g = sk_GENERAL_NAME_value(gs, i);
if (g->type == gtype) {
ret = 1;
break;
}
}
GENERAL_NAMES_free(gs);
return ret;
}
static int check_name_constraints(X509_STORE_CTX *ctx)
{
int i;
/* Check name constraints for all certificates */
for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) {
X509 *x = sk_X509_value(ctx->chain, i);
int j;
/* Ignore self issued certs unless last in chain */
if (i && (x->ex_flags & EXFLAG_SI))
continue;
/*
* Proxy certificates policy has an extra constraint, where the
* certificate subject MUST be the issuer with a single CN entry
* added.
* (RFC 3820: 3.4, 4.1.3 (a)(4))
*/
if (x->ex_flags & EXFLAG_PROXY) {
X509_NAME *tmpsubject = X509_get_subject_name(x);
X509_NAME *tmpissuer = X509_get_issuer_name(x);
X509_NAME_ENTRY *tmpentry = NULL;
int last_object_nid = 0;
int err = X509_V_OK;
int last_object_loc = X509_NAME_entry_count(tmpsubject) - 1;
/* Check that there are at least two RDNs */
if (last_object_loc < 1) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
goto proxy_name_done;
}
/*
* Check that there is exactly one more RDN in subject as
* there is in issuer.
*/
if (X509_NAME_entry_count(tmpsubject)
!= X509_NAME_entry_count(tmpissuer) + 1) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
goto proxy_name_done;
}
/*
* Check that the last subject component isn't part of a
* multivalued RDN
*/
if (X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject,
last_object_loc))
== X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject,
last_object_loc - 1))) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
goto proxy_name_done;
}
/*
* Check that the last subject RDN is a commonName, and that
* all the previous RDNs match the issuer exactly
*/
tmpsubject = X509_NAME_dup(tmpsubject);
if (tmpsubject == NULL) {
X509err(X509_F_CHECK_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
tmpentry =
X509_NAME_delete_entry(tmpsubject, last_object_loc);
last_object_nid =
OBJ_obj2nid(X509_NAME_ENTRY_get_object(tmpentry));
if (last_object_nid != NID_commonName
|| X509_NAME_cmp(tmpsubject, tmpissuer) != 0) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
}
X509_NAME_ENTRY_free(tmpentry);
X509_NAME_free(tmpsubject);
proxy_name_done:
if (err != X509_V_OK
&& !verify_cb_cert(ctx, x, i, err))
return 0;
}
/*
* Check against constraints for all certificates higher in chain
* including trust anchor. Trust anchor not strictly speaking needed
* but if it includes constraints it is to be assumed it expects them
* to be obeyed.
*/
for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) {
NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
if (nc) {
int rv = NAME_CONSTRAINTS_check(x, nc);
/* If EE certificate check commonName too */
if (rv == X509_V_OK && i == 0
&& (ctx->param->hostflags
& X509_CHECK_FLAG_NEVER_CHECK_SUBJECT) == 0
&& ((ctx->param->hostflags
& X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) != 0
|| !has_san_id(x, GEN_DNS)))
rv = NAME_CONSTRAINTS_check_CN(x, nc);
switch (rv) {
case X509_V_OK:
break;
case X509_V_ERR_OUT_OF_MEM:
return 0;
default:
if (!verify_cb_cert(ctx, x, i, rv))
return 0;
break;
}
}
}
}
return 1;
}
static int check_id_error(X509_STORE_CTX *ctx, int errcode)
{
return verify_cb_cert(ctx, ctx->cert, 0, errcode);
}
static int check_hosts(X509 *x, X509_VERIFY_PARAM *vpm)
{
int i;
int n = sk_OPENSSL_STRING_num(vpm->hosts);
char *name;
if (vpm->peername != NULL) {
OPENSSL_free(vpm->peername);
vpm->peername = NULL;
}
for (i = 0; i < n; ++i) {
name = sk_OPENSSL_STRING_value(vpm->hosts, i);
if (X509_check_host(x, name, 0, vpm->hostflags, &vpm->peername) > 0)
return 1;
}
return n == 0;
}
static int check_id(X509_STORE_CTX *ctx)
{
X509_VERIFY_PARAM *vpm = ctx->param;
X509 *x = ctx->cert;
if (vpm->hosts && check_hosts(x, vpm) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
return 0;
}
if (vpm->email && X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
return 0;
}
if (vpm->ip && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
return 0;
}
return 1;
}
static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
{
int i;
X509 *x = NULL;
X509 *mx;
SSL_DANE *dane = ctx->dane;
int num = sk_X509_num(ctx->chain);
int trust;
/*
* Check for a DANE issuer at depth 1 or greater, if it is a DANE-TA(2)
* match, we're done, otherwise we'll merely record the match depth.
*/
if (DANETLS_HAS_TA(dane) && num_untrusted > 0 && num_untrusted < num) {
switch (trust = check_dane_issuer(ctx, num_untrusted)) {
case X509_TRUST_TRUSTED:
case X509_TRUST_REJECTED:
return trust;
}
}
/*
* Check trusted certificates in chain at depth num_untrusted and up.
* Note, that depths 0..num_untrusted-1 may also contain trusted
* certificates, but the caller is expected to have already checked those,
* and wants to incrementally check just any added since.
*/
for (i = num_untrusted; i < num; i++) {
x = sk_X509_value(ctx->chain, i);
trust = X509_check_trust(x, ctx->param->trust, 0);
/* If explicitly trusted return trusted */
if (trust == X509_TRUST_TRUSTED)
goto trusted;
if (trust == X509_TRUST_REJECTED)
goto rejected;
}
/*
* If we are looking at a trusted certificate, and accept partial chains,
* the chain is PKIX trusted.
*/
if (num_untrusted < num) {
if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
goto trusted;
return X509_TRUST_UNTRUSTED;
}
if (num_untrusted == num && ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
/*
* Last-resort call with no new trusted certificates, check the leaf
* for a direct trust store match.
*/
i = 0;
x = sk_X509_value(ctx->chain, i);
mx = lookup_cert_match(ctx, x);
if (!mx)
return X509_TRUST_UNTRUSTED;
/*
* Check explicit auxiliary trust/reject settings. If none are set,
* we'll accept X509_TRUST_UNTRUSTED when not self-signed.
*/
trust = X509_check_trust(mx, ctx->param->trust, 0);
if (trust == X509_TRUST_REJECTED) {
X509_free(mx);
goto rejected;
}
/* Replace leaf with trusted match */
(void) sk_X509_set(ctx->chain, 0, mx);
X509_free(x);
ctx->num_untrusted = 0;
goto trusted;
}
/*
* If no trusted certs in chain at all return untrusted and allow
* standard (no issuer cert) etc errors to be indicated.
*/
return X509_TRUST_UNTRUSTED;
rejected:
if (!verify_cb_cert(ctx, x, i, X509_V_ERR_CERT_REJECTED))
return X509_TRUST_REJECTED;
return X509_TRUST_UNTRUSTED;
trusted:
if (!DANETLS_ENABLED(dane))
return X509_TRUST_TRUSTED;
if (dane->pdpth < 0)
dane->pdpth = num_untrusted;
/* With DANE, PKIX alone is not trusted until we have both */
if (dane->mdpth >= 0)
return X509_TRUST_TRUSTED;
return X509_TRUST_UNTRUSTED;
}
static int check_revocation(X509_STORE_CTX *ctx)
{
int i = 0, last = 0, ok = 0;
if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
return 1;
if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
last = sk_X509_num(ctx->chain) - 1;
else {
/* If checking CRL paths this isn't the EE certificate */
if (ctx->parent)
return 1;
last = 0;
}
for (i = 0; i <= last; i++) {
ctx->error_depth = i;
ok = check_cert(ctx);
if (!ok)
return ok;
}
return 1;
}
static int check_cert(X509_STORE_CTX *ctx)
{
X509_CRL *crl = NULL, *dcrl = NULL;
int ok = 0;
int cnum = ctx->error_depth;
X509 *x = sk_X509_value(ctx->chain, cnum);
ctx->current_cert = x;
ctx->current_issuer = NULL;
ctx->current_crl_score = 0;
ctx->current_reasons = 0;
if (x->ex_flags & EXFLAG_PROXY)
return 1;
while (ctx->current_reasons != CRLDP_ALL_REASONS) {
unsigned int last_reasons = ctx->current_reasons;
/* Try to retrieve relevant CRL */
if (ctx->get_crl)
ok = ctx->get_crl(ctx, &crl, x);
else
ok = get_crl_delta(ctx, &crl, &dcrl, x);
/*
* If error looking up CRL, nothing we can do except notify callback
*/
if (!ok) {
ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL);
goto done;
}
ctx->current_crl = crl;
ok = ctx->check_crl(ctx, crl);
if (!ok)
goto done;
if (dcrl) {
ok = ctx->check_crl(ctx, dcrl);
if (!ok)
goto done;
ok = ctx->cert_crl(ctx, dcrl, x);
if (!ok)
goto done;
} else
ok = 1;
/* Don't look in full CRL if delta reason is removefromCRL */
if (ok != 2) {
ok = ctx->cert_crl(ctx, crl, x);
if (!ok)
goto done;
}
X509_CRL_free(crl);
X509_CRL_free(dcrl);
crl = NULL;
dcrl = NULL;
/*
* If reasons not updated we won't get anywhere by another iteration,
* so exit loop.
*/
if (last_reasons == ctx->current_reasons) {
ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL);
goto done;
}
}
done:
X509_CRL_free(crl);
X509_CRL_free(dcrl);
ctx->current_crl = NULL;
return ok;
}
/* Check CRL times against values in X509_STORE_CTX */
static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
{
time_t *ptime;
int i;
if (notify)
ctx->current_crl = crl;
if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
ptime = &ctx->param->check_time;
else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME)
return 1;
else
ptime = NULL;
i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime);
if (i == 0) {
if (!notify)
return 0;
if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD))
return 0;
}
if (i > 0) {
if (!notify)
return 0;
if (!verify_cb_crl(ctx, X509_V_ERR_CRL_NOT_YET_VALID))
return 0;
}
if (X509_CRL_get0_nextUpdate(crl)) {
i = X509_cmp_time(X509_CRL_get0_nextUpdate(crl), ptime);
if (i == 0) {
if (!notify)
return 0;
if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD))
return 0;
}
/* Ignore expiry of base CRL is delta is valid */
if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) {
if (!notify)
return 0;
if (!verify_cb_crl(ctx, X509_V_ERR_CRL_HAS_EXPIRED))
return 0;
}
}
if (notify)
ctx->current_crl = NULL;
return 1;
}
static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
X509 **pissuer, int *pscore, unsigned int *preasons,
STACK_OF(X509_CRL) *crls)
{
int i, crl_score, best_score = *pscore;
unsigned int reasons, best_reasons = 0;
X509 *x = ctx->current_cert;
X509_CRL *crl, *best_crl = NULL;
X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
for (i = 0; i < sk_X509_CRL_num(crls); i++) {
crl = sk_X509_CRL_value(crls, i);
reasons = *preasons;
crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
if (crl_score < best_score || crl_score == 0)
continue;
/* If current CRL is equivalent use it if it is newer */
if (crl_score == best_score && best_crl != NULL) {
int day, sec;
if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl),
X509_CRL_get0_lastUpdate(crl)) == 0)
continue;
/*
* ASN1_TIME_diff never returns inconsistent signs for |day|
* and |sec|.
*/
if (day <= 0 && sec <= 0)
continue;
}
best_crl = crl;
best_crl_issuer = crl_issuer;
best_score = crl_score;
best_reasons = reasons;
}
if (best_crl) {
X509_CRL_free(*pcrl);
*pcrl = best_crl;
*pissuer = best_crl_issuer;
*pscore = best_score;
*preasons = best_reasons;
X509_CRL_up_ref(best_crl);
X509_CRL_free(*pdcrl);
*pdcrl = NULL;
get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
}
if (best_score >= CRL_SCORE_VALID)
return 1;
return 0;
}
/*
* Compare two CRL extensions for delta checking purposes. They should be
* both present or both absent. If both present all fields must be identical.
*/
static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid)
{
ASN1_OCTET_STRING *exta, *extb;
int i;
i = X509_CRL_get_ext_by_NID(a, nid, -1);
if (i >= 0) {
/* Can't have multiple occurrences */
if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
return 0;
exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
} else
exta = NULL;
i = X509_CRL_get_ext_by_NID(b, nid, -1);
if (i >= 0) {
if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
return 0;
extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
} else
extb = NULL;
if (!exta && !extb)
return 1;
if (!exta || !extb)
return 0;
if (ASN1_OCTET_STRING_cmp(exta, extb))
return 0;
return 1;
}
/* See if a base and delta are compatible */
static int check_delta_base(X509_CRL *delta, X509_CRL *base)
{
/* Delta CRL must be a delta */
if (!delta->base_crl_number)
return 0;
/* Base must have a CRL number */
if (!base->crl_number)
return 0;
/* Issuer names must match */
if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(delta)))
return 0;
/* AKID and IDP must match */
if (!crl_extension_match(delta, base, NID_authority_key_identifier))
return 0;
if (!crl_extension_match(delta, base, NID_issuing_distribution_point))
return 0;
/* Delta CRL base number must not exceed Full CRL number. */
if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
return 0;
/* Delta CRL number must exceed full CRL number */
if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0)
return 1;
return 0;
}
/*
* For a given base CRL find a delta... maybe extend to delta scoring or
* retrieve a chain of deltas...
*/
static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore,
X509_CRL *base, STACK_OF(X509_CRL) *crls)
{
X509_CRL *delta;
int i;
if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS))
return;
if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST))
return;
for (i = 0; i < sk_X509_CRL_num(crls); i++) {
delta = sk_X509_CRL_value(crls, i);
if (check_delta_base(delta, base)) {
if (check_crl_time(ctx, delta, 0))
*pscore |= CRL_SCORE_TIME_DELTA;
X509_CRL_up_ref(delta);
*dcrl = delta;
return;
}
}
*dcrl = NULL;
}
/*
* For a given CRL return how suitable it is for the supplied certificate
* 'x'. The return value is a mask of several criteria. If the issuer is not
* the certificate issuer this is returned in *pissuer. The reasons mask is
* also used to determine if the CRL is suitable: if no new reasons the CRL
* is rejected, otherwise reasons is updated.
*/
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
unsigned int *preasons, X509_CRL *crl, X509 *x)
{
int crl_score = 0;
unsigned int tmp_reasons = *preasons, crl_reasons;
/* First see if we can reject CRL straight away */
/* Invalid IDP cannot be processed */
if (crl->idp_flags & IDP_INVALID)
return 0;
/* Reason codes or indirect CRLs need extended CRL support */
if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) {
if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
return 0;
} else if (crl->idp_flags & IDP_REASONS) {
/* If no new reasons reject */
if (!(crl->idp_reasons & ~tmp_reasons))
return 0;
}
/* Don't process deltas at this stage */
else if (crl->base_crl_number)
return 0;
/* If issuer name doesn't match certificate need indirect CRL */
if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) {
if (!(crl->idp_flags & IDP_INDIRECT))
return 0;
} else
crl_score |= CRL_SCORE_ISSUER_NAME;
if (!(crl->flags & EXFLAG_CRITICAL))
crl_score |= CRL_SCORE_NOCRITICAL;
/* Check expiry */
if (check_crl_time(ctx, crl, 0))
crl_score |= CRL_SCORE_TIME;
/* Check authority key ID and locate certificate issuer */
crl_akid_check(ctx, crl, pissuer, &crl_score);
/* If we can't locate certificate issuer at this point forget it */
if (!(crl_score & CRL_SCORE_AKID))
return 0;
/* Check cert for matching CRL distribution points */
if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) {
/* If no new reasons reject */
if (!(crl_reasons & ~tmp_reasons))
return 0;
tmp_reasons |= crl_reasons;
crl_score |= CRL_SCORE_SCOPE;
}
*preasons = tmp_reasons;
return crl_score;
}
static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
X509 **pissuer, int *pcrl_score)
{
X509 *crl_issuer = NULL;
X509_NAME *cnm = X509_CRL_get_issuer(crl);
int cidx = ctx->error_depth;
int i;
if (cidx != sk_X509_num(ctx->chain) - 1)
cidx++;
crl_issuer = sk_X509_value(ctx->chain, cidx);
if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
if (*pcrl_score & CRL_SCORE_ISSUER_NAME) {
*pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT;
*pissuer = crl_issuer;
return;
}
}
for (cidx++; cidx < sk_X509_num(ctx->chain); cidx++) {
crl_issuer = sk_X509_value(ctx->chain, cidx);
if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
continue;
if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
*pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH;
*pissuer = crl_issuer;
return;
}
}
/* Anything else needs extended CRL support */
if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
return;
/*
* Otherwise the CRL issuer is not on the path. Look for it in the set of
* untrusted certificates.
*/
for (i = 0; i < sk_X509_num(ctx->untrusted); i++) {
crl_issuer = sk_X509_value(ctx->untrusted, i);
if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
continue;
if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
*pissuer = crl_issuer;
*pcrl_score |= CRL_SCORE_AKID;
return;
}
}
}
/*
* Check the path of a CRL issuer certificate. This creates a new
* X509_STORE_CTX and populates it with most of the parameters from the
* parent. This could be optimised somewhat since a lot of path checking will
* be duplicated by the parent, but this will rarely be used in practice.
*/
static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
{
X509_STORE_CTX crl_ctx;
int ret;
/* Don't allow recursive CRL path validation */
if (ctx->parent)
return 0;
if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted))
return -1;
crl_ctx.crls = ctx->crls;
/* Copy verify params across */
X509_STORE_CTX_set0_param(&crl_ctx, ctx->param);
crl_ctx.parent = ctx;
crl_ctx.verify_cb = ctx->verify_cb;
/* Verify CRL issuer */
ret = X509_verify_cert(&crl_ctx);
if (ret <= 0)
goto err;
/* Check chain is acceptable */
ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain);
err:
X509_STORE_CTX_cleanup(&crl_ctx);
return ret;
}
/*
* RFC3280 says nothing about the relationship between CRL path and
* certificate path, which could lead to situations where a certificate could
* be revoked or validated by a CA not authorised to do so. RFC5280 is more
* strict and states that the two paths must end in the same trust anchor,
* though some discussions remain... until this is resolved we use the
* RFC5280 version
*/
static int check_crl_chain(X509_STORE_CTX *ctx,
STACK_OF(X509) *cert_path,
STACK_OF(X509) *crl_path)
{
X509 *cert_ta, *crl_ta;
cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
if (!X509_cmp(cert_ta, crl_ta))
return 1;
return 0;
}
/*-
* Check for match between two dist point names: three separate cases.
* 1. Both are relative names and compare X509_NAME types.
* 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES.
* 3. Both are full names and compare two GENERAL_NAMES.
* 4. One is NULL: automatic match.
*/
static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
{
X509_NAME *nm = NULL;
GENERAL_NAMES *gens = NULL;
GENERAL_NAME *gena, *genb;
int i, j;
if (!a || !b)
return 1;
if (a->type == 1) {
if (!a->dpname)
return 0;
/* Case 1: two X509_NAME */
if (b->type == 1) {
if (!b->dpname)
return 0;
if (!X509_NAME_cmp(a->dpname, b->dpname))
return 1;
else
return 0;
}
/* Case 2: set name and GENERAL_NAMES appropriately */
nm = a->dpname;
gens = b->name.fullname;
} else if (b->type == 1) {
if (!b->dpname)
return 0;
/* Case 2: set name and GENERAL_NAMES appropriately */
gens = a->name.fullname;
nm = b->dpname;
}
/* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
if (nm) {
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
gena = sk_GENERAL_NAME_value(gens, i);
if (gena->type != GEN_DIRNAME)
continue;
if (!X509_NAME_cmp(nm, gena->d.directoryName))
return 1;
}
return 0;
}
/* Else case 3: two GENERAL_NAMES */
for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) {
gena = sk_GENERAL_NAME_value(a->name.fullname, i);
for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) {
genb = sk_GENERAL_NAME_value(b->name.fullname, j);
if (!GENERAL_NAME_cmp(gena, genb))
return 1;
}
}
return 0;
}
static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score)
{
int i;
X509_NAME *nm = X509_CRL_get_issuer(crl);
/* If no CRLissuer return is successful iff don't need a match */
if (!dp->CRLissuer)
return ! !(crl_score & CRL_SCORE_ISSUER_NAME);
for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
if (gen->type != GEN_DIRNAME)
continue;
if (!X509_NAME_cmp(gen->d.directoryName, nm))
return 1;
}
return 0;
}
/* Check CRLDP and IDP */
static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
unsigned int *preasons)
{
int i;
if (crl->idp_flags & IDP_ONLYATTR)
return 0;
if (x->ex_flags & EXFLAG_CA) {
if (crl->idp_flags & IDP_ONLYUSER)
return 0;
} else {
if (crl->idp_flags & IDP_ONLYCA)
return 0;
}
*preasons = crl->idp_reasons;
for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
if (crldp_check_crlissuer(dp, crl, crl_score)) {
if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)) {
*preasons &= dp->dp_reasons;
return 1;
}
}
}
if ((!crl->idp || !crl->idp->distpoint)
&& (crl_score & CRL_SCORE_ISSUER_NAME))
return 1;
return 0;
}
/*
* Retrieve CRL corresponding to current certificate. If deltas enabled try
* to find a delta CRL too
*/
static int get_crl_delta(X509_STORE_CTX *ctx,
X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
{
int ok;
X509 *issuer = NULL;
int crl_score = 0;
unsigned int reasons;
X509_CRL *crl = NULL, *dcrl = NULL;
STACK_OF(X509_CRL) *skcrl;
X509_NAME *nm = X509_get_issuer_name(x);
reasons = ctx->current_reasons;
ok = get_crl_sk(ctx, &crl, &dcrl,
&issuer, &crl_score, &reasons, ctx->crls);
if (ok)
goto done;
/* Lookup CRLs from store */
skcrl = ctx->lookup_crls(ctx, nm);
/* If no CRLs found and a near match from get_crl_sk use that */
if (!skcrl && crl)
goto done;
get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
done:
/* If we got any kind of CRL use it and return success */
if (crl) {
ctx->current_issuer = issuer;
ctx->current_crl_score = crl_score;
ctx->current_reasons = reasons;
*pcrl = crl;
*pdcrl = dcrl;
return 1;
}
return 0;
}
/* Check CRL validity */
static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
{
X509 *issuer = NULL;
EVP_PKEY *ikey = NULL;
int cnum = ctx->error_depth;
int chnum = sk_X509_num(ctx->chain) - 1;
/* if we have an alternative CRL issuer cert use that */
if (ctx->current_issuer)
issuer = ctx->current_issuer;
/*
* Else find CRL issuer: if not last certificate then issuer is next
* certificate in chain.
*/
else if (cnum < chnum)
issuer = sk_X509_value(ctx->chain, cnum + 1);
else {
issuer = sk_X509_value(ctx->chain, chnum);
/* If not self signed, can't check signature */
if (!ctx->check_issued(ctx, issuer, issuer) &&
!verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER))
return 0;
}
if (issuer == NULL)
return 1;
/*
* Skip most tests for deltas because they have already been done
*/
if (!crl->base_crl_number) {
/* Check for cRLSign bit if keyUsage present */
if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
!(issuer->ex_kusage & KU_CRL_SIGN) &&
!verify_cb_crl(ctx, X509_V_ERR_KEYUSAGE_NO_CRL_SIGN))
return 0;
if (!(ctx->current_crl_score & CRL_SCORE_SCOPE) &&
!verify_cb_crl(ctx, X509_V_ERR_DIFFERENT_CRL_SCOPE))
return 0;
if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH) &&
check_crl_path(ctx, ctx->current_issuer) <= 0 &&
!verify_cb_crl(ctx, X509_V_ERR_CRL_PATH_VALIDATION_ERROR))
return 0;
if ((crl->idp_flags & IDP_INVALID) &&
!verify_cb_crl(ctx, X509_V_ERR_INVALID_EXTENSION))
return 0;
}
if (!(ctx->current_crl_score & CRL_SCORE_TIME) &&
!check_crl_time(ctx, crl, 1))
return 0;
/* Attempt to get issuer certificate public key */
ikey = X509_get0_pubkey(issuer);
if (!ikey &&
!verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY))
return 0;
if (ikey) {
int rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
if (rv != X509_V_OK && !verify_cb_crl(ctx, rv))
return 0;
/* Verify CRL signature */
if (X509_CRL_verify(crl, ikey) <= 0 &&
!verify_cb_crl(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE))
return 0;
}
return 1;
}
/* Check certificate against CRL */
static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
{
X509_REVOKED *rev;
/*
* The rules changed for this... previously if a CRL contained unhandled
* critical extensions it could still be used to indicate a certificate
* was revoked. This has since been changed since critical extensions can
* change the meaning of CRL entries.
*/
if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
&& (crl->flags & EXFLAG_CRITICAL) &&
!verify_cb_crl(ctx, X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION))
return 0;
/*
* Look for serial number of certificate in CRL. If found, make sure
* reason is not removeFromCRL.
*/
if (X509_CRL_get0_by_cert(crl, &rev, x)) {
if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
return 2;
if (!verify_cb_crl(ctx, X509_V_ERR_CERT_REVOKED))
return 0;
}
return 1;
}
static int check_policy(X509_STORE_CTX *ctx)
{
int ret;
if (ctx->parent)
return 1;
/*
* With DANE, the trust anchor might be a bare public key, not a
* certificate! In that case our chain does not have the trust anchor
* certificate as a top-most element. This comports well with RFC5280
* chain verification, since there too, the trust anchor is not part of the
* chain to be verified. In particular, X509_policy_check() does not look
* at the TA cert, but assumes that it is present as the top-most chain
* element. We therefore temporarily push a NULL cert onto the chain if it
* was verified via a bare public key, and pop it off right after the
* X509_policy_check() call.
*/
if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL)) {
X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
ctx->param->policies, ctx->param->flags);
if (ctx->bare_ta_signed)
sk_X509_pop(ctx->chain);
if (ret == X509_PCY_TREE_INTERNAL) {
X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
/* Invalid or inconsistent extensions */
if (ret == X509_PCY_TREE_INVALID) {
int i;
/* Locate certificates with bad extensions and notify callback. */
for (i = 1; i < sk_X509_num(ctx->chain); i++) {
X509 *x = sk_X509_value(ctx->chain, i);
if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
continue;
if (!verify_cb_cert(ctx, x, i,
X509_V_ERR_INVALID_POLICY_EXTENSION))
return 0;
}
return 1;
}
if (ret == X509_PCY_TREE_FAILURE) {
ctx->current_cert = NULL;
ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
return ctx->verify_cb(0, ctx);
}
if (ret != X509_PCY_TREE_VALID) {
X509err(X509_F_CHECK_POLICY, ERR_R_INTERNAL_ERROR);
return 0;
}
if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) {
ctx->current_cert = NULL;
/*
* Verification errors need to be "sticky", a callback may have allowed
* an SSL handshake to continue despite an error, and we must then
* remain in an error state. Therefore, we MUST NOT clear earlier
* verification errors by setting the error to X509_V_OK.
*/
if (!ctx->verify_cb(2, ctx))
return 0;
}
return 1;
}
/*-
* Check certificate validity times.
* If depth >= 0, invoke verification callbacks on error, otherwise just return
* the validation status.
*
* Return 1 on success, 0 otherwise.
*/
int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
{
time_t *ptime;
int i;
if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
ptime = &ctx->param->check_time;
else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME)
return 1;
else
ptime = NULL;
i = X509_cmp_time(X509_get0_notBefore(x), ptime);
if (i >= 0 && depth < 0)
return 0;
if (i == 0 && !verify_cb_cert(ctx, x, depth,
X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD))
return 0;
if (i > 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_NOT_YET_VALID))
return 0;
i = X509_cmp_time(X509_get0_notAfter(x), ptime);
if (i <= 0 && depth < 0)
return 0;
if (i == 0 && !verify_cb_cert(ctx, x, depth,
X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD))
return 0;
if (i < 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_HAS_EXPIRED))
return 0;
return 1;
}
static int internal_verify(X509_STORE_CTX *ctx)
{
int n = sk_X509_num(ctx->chain) - 1;
X509 *xi = sk_X509_value(ctx->chain, n);
X509 *xs;
/*
* With DANE-verified bare public key TA signatures, it remains only to
* check the timestamps of the top certificate. We report the issuer as
* NULL, since all we have is a bare key.
*/
if (ctx->bare_ta_signed) {
xs = xi;
xi = NULL;
goto check_cert;
}
if (ctx->check_issued(ctx, xi, xi))
xs = xi;
else {
if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
xs = xi;
goto check_cert;
}
if (n <= 0)
return verify_cb_cert(ctx, xi, 0,
X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE);
n--;
ctx->error_depth = n;
xs = sk_X509_value(ctx->chain, n);
}
/*
* Do not clear ctx->error=0, it must be "sticky", only the user's callback
* is allowed to reset errors (at its own peril).
*/
while (n >= 0) {
EVP_PKEY *pkey;
/*
* Skip signature check for self signed certificates unless explicitly
* asked for. It doesn't add any security and just wastes time. If
* the issuer's public key is unusable, report the issuer certificate
* and its depth (rather than the depth of the subject).
*/
if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) {
if ((pkey = X509_get0_pubkey(xi)) == NULL) {
if (!verify_cb_cert(ctx, xi, xi != xs ? n+1 : n,
X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY))
return 0;
} else if (X509_verify(xs, pkey) <= 0) {
if (!verify_cb_cert(ctx, xs, n,
X509_V_ERR_CERT_SIGNATURE_FAILURE))
return 0;
}
}
check_cert:
/* Calls verify callback as needed */
if (!x509_check_cert_time(ctx, xs, n))
return 0;
/*
* Signal success at this depth. However, the previous error (if any)
* is retained.
*/
ctx->current_issuer = xi;
ctx->current_cert = xs;
ctx->error_depth = n;
if (!ctx->verify_cb(1, ctx))
return 0;
if (--n >= 0) {
xi = xs;
xs = sk_X509_value(ctx->chain, n);
}
}
return 1;
}
int X509_cmp_current_time(const ASN1_TIME *ctm)
{
return X509_cmp_time(ctm, NULL);
}
int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
{
static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1;
static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1;
ASN1_TIME *asn1_cmp_time = NULL;
int i, day, sec, ret = 0;
/*
* Note that ASN.1 allows much more slack in the time format than RFC5280.
* In RFC5280, the representation is fixed:
* UTCTime: YYMMDDHHMMSSZ
* GeneralizedTime: YYYYMMDDHHMMSSZ
*
* We do NOT currently enforce the following RFC 5280 requirement:
* "CAs conforming to this profile MUST always encode certificate
* validity dates through the year 2049 as UTCTime; certificate validity
* dates in 2050 or later MUST be encoded as GeneralizedTime."
*/
switch (ctm->type) {
case V_ASN1_UTCTIME:
if (ctm->length != (int)(utctime_length))
return 0;
break;
case V_ASN1_GENERALIZEDTIME:
if (ctm->length != (int)(generalizedtime_length))
return 0;
break;
default:
return 0;
}
/**
* Verify the format: the ASN.1 functions we use below allow a more
* flexible format than what's mandated by RFC 5280.
* Digit and date ranges will be verified in the conversion methods.
*/
for (i = 0; i < ctm->length - 1; i++) {
if (!ossl_isdigit(ctm->data[i]))
return 0;
}
if (ctm->data[ctm->length - 1] != 'Z')
return 0;
/*
* There is ASN1_UTCTIME_cmp_time_t but no
* ASN1_GENERALIZEDTIME_cmp_time_t or ASN1_TIME_cmp_time_t,
* so we go through ASN.1
*/
asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time);
if (asn1_cmp_time == NULL)
goto err;
if (!ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time))
goto err;
/*
* X509_cmp_time comparison is <=.
* The return value 0 is reserved for errors.
*/
ret = (day >= 0 && sec >= 0) ? -1 : 1;
err:
ASN1_TIME_free(asn1_cmp_time);
return ret;
}
ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
{
return X509_time_adj(s, adj, NULL);
}
ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
{
return X509_time_adj_ex(s, 0, offset_sec, in_tm);
}
ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
int offset_day, long offset_sec, time_t *in_tm)
{
time_t t;
if (in_tm)
t = *in_tm;
else
time(&t);
if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING)) {
if (s->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
if (s->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
}
return ASN1_TIME_adj(s, t, offset_day, offset_sec);
}
int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
{
EVP_PKEY *ktmp = NULL, *ktmp2;
int i, j;
if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey))
return 1;
for (i = 0; i < sk_X509_num(chain); i++) {
ktmp = X509_get0_pubkey(sk_X509_value(chain, i));
if (ktmp == NULL) {
X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,
X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
return 0;
}
if (!EVP_PKEY_missing_parameters(ktmp))
break;
}
if (ktmp == NULL) {
X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,
X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
return 0;
}
/* first, populate the other certs */
for (j = i - 1; j >= 0; j--) {
ktmp2 = X509_get0_pubkey(sk_X509_value(chain, j));
EVP_PKEY_copy_parameters(ktmp2, ktmp);
}
if (pkey != NULL)
EVP_PKEY_copy_parameters(pkey, ktmp);
return 1;
}
/* Make a delta CRL as the diff between two full CRLs */
X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
{
X509_CRL *crl = NULL;
int i;
STACK_OF(X509_REVOKED) *revs = NULL;
/* CRLs can't be delta already */
if (base->base_crl_number || newer->base_crl_number) {
X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_ALREADY_DELTA);
return NULL;
}
/* Base and new CRL must have a CRL number */
if (!base->crl_number || !newer->crl_number) {
X509err(X509_F_X509_CRL_DIFF, X509_R_NO_CRL_NUMBER);
return NULL;
}
/* Issuer names must match */
if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(newer))) {
X509err(X509_F_X509_CRL_DIFF, X509_R_ISSUER_MISMATCH);
return NULL;
}
/* AKID and IDP must match */
if (!crl_extension_match(base, newer, NID_authority_key_identifier)) {
X509err(X509_F_X509_CRL_DIFF, X509_R_AKID_MISMATCH);
return NULL;
}
if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) {
X509err(X509_F_X509_CRL_DIFF, X509_R_IDP_MISMATCH);
return NULL;
}
/* Newer CRL number must exceed full CRL number */
if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) {
X509err(X509_F_X509_CRL_DIFF, X509_R_NEWER_CRL_NOT_NEWER);
return NULL;
}
/* CRLs must verify */
if (skey && (X509_CRL_verify(base, skey) <= 0 ||
X509_CRL_verify(newer, skey) <= 0)) {
X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_VERIFY_FAILURE);
return NULL;
}
/* Create new CRL */
crl = X509_CRL_new();
if (crl == NULL || !X509_CRL_set_version(crl, 1))
goto memerr;
/* Set issuer name */
if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
goto memerr;
if (!X509_CRL_set1_lastUpdate(crl, X509_CRL_get0_lastUpdate(newer)))
goto memerr;
if (!X509_CRL_set1_nextUpdate(crl, X509_CRL_get0_nextUpdate(newer)))
goto memerr;
/* Set base CRL number: must be critical */
if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
goto memerr;
/*
* Copy extensions across from newest CRL to delta: this will set CRL
* number to correct value too.
*/
for (i = 0; i < X509_CRL_get_ext_count(newer); i++) {
X509_EXTENSION *ext;
ext = X509_CRL_get_ext(newer, i);
if (!X509_CRL_add_ext(crl, ext, -1))
goto memerr;
}
/* Go through revoked entries, copying as needed */
revs = X509_CRL_get_REVOKED(newer);
for (i = 0; i < sk_X509_REVOKED_num(revs); i++) {
X509_REVOKED *rvn, *rvtmp;
rvn = sk_X509_REVOKED_value(revs, i);
/*
* Add only if not also in base. TODO: need something cleverer here
* for some more complex CRLs covering multiple CAs.
*/
if (!X509_CRL_get0_by_serial(base, &rvtmp, &rvn->serialNumber)) {
rvtmp = X509_REVOKED_dup(rvn);
if (!rvtmp)
goto memerr;
if (!X509_CRL_add0_revoked(crl, rvtmp)) {
X509_REVOKED_free(rvtmp);
goto memerr;
}
}
}
/* TODO: optionally prune deleted entries */
if (skey && md && !X509_CRL_sign(crl, skey, md))
goto memerr;
return crl;
memerr:
X509err(X509_F_X509_CRL_DIFF, ERR_R_MALLOC_FAILURE);
X509_CRL_free(crl);
return NULL;
}
int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
{
return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
}
void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
{
return CRYPTO_get_ex_data(&ctx->ex_data, idx);
}
int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
{
return ctx->error;
}
void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
{
ctx->error = err;
}
int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
{
return ctx->error_depth;
}
void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth)
{
ctx->error_depth = depth;
}
X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
{
return ctx->current_cert;
}
void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x)
{
ctx->current_cert = x;
}
STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx)
{
return ctx->chain;
}
STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
{
if (!ctx->chain)
return NULL;
return X509_chain_up_ref(ctx->chain);
}
X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx)
{
return ctx->current_issuer;
}
X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx)
{
return ctx->current_crl;
}
X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx)
{
return ctx->parent;
}
void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
{
ctx->cert = x;
}
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
{
ctx->crls = sk;
}
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
{
/*
* XXX: Why isn't this function always used to set the associated trust?
* Should there even be a VPM->trust field at all? Or should the trust
* always be inferred from the purpose by X509_STORE_CTX_init().
*/
return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
}
int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
{
/*
* XXX: See above, this function would only be needed when the default
* trust for the purpose needs an override in a corner case.
*/
return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
}
/*
* This function is used to set the X509_STORE_CTX purpose and trust values.
* This is intended to be used when another structure has its own trust and
* purpose values which (if set) will be inherited by the ctx. If they aren't
* set then we will usually have a default purpose in mind which should then
* be used to set the trust value. An example of this is SSL use: an SSL
* structure will have its own purpose and trust settings which the
* application can set: if they aren't set then we use the default of SSL
* client/server.
*/
int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
int purpose, int trust)
{
int idx;
/* If purpose not set use default */
if (!purpose)
purpose = def_purpose;
/* If we have a purpose then check it is valid */
if (purpose) {
X509_PURPOSE *ptmp;
idx = X509_PURPOSE_get_by_id(purpose);
if (idx == -1) {
X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
X509_R_UNKNOWN_PURPOSE_ID);
return 0;
}
ptmp = X509_PURPOSE_get0(idx);
if (ptmp->trust == X509_TRUST_DEFAULT) {
idx = X509_PURPOSE_get_by_id(def_purpose);
/*
* XXX: In the two callers above def_purpose is always 0, which is
* not a known value, so idx will always be -1. How is the
* X509_TRUST_DEFAULT case actually supposed to be handled?
*/
if (idx == -1) {
X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
X509_R_UNKNOWN_PURPOSE_ID);
return 0;
}
ptmp = X509_PURPOSE_get0(idx);
}
/* If trust not set then get from purpose default */
if (!trust)
trust = ptmp->trust;
}
if (trust) {
idx = X509_TRUST_get_by_id(trust);
if (idx == -1) {
X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
X509_R_UNKNOWN_TRUST_ID);
return 0;
}
}
if (purpose && !ctx->param->purpose)
ctx->param->purpose = purpose;
if (trust && !ctx->param->trust)
ctx->param->trust = trust;
return 1;
}
X509_STORE_CTX *X509_STORE_CTX_new(void)
{
X509_STORE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
X509err(X509_F_X509_STORE_CTX_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
return ctx;
}
void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
{
if (ctx == NULL)
return;
X509_STORE_CTX_cleanup(ctx);
OPENSSL_free(ctx);
}
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
STACK_OF(X509) *chain)
{
int ret = 1;
ctx->ctx = store;
ctx->cert = x509;
ctx->untrusted = chain;
ctx->crls = NULL;
ctx->num_untrusted = 0;
ctx->other_ctx = NULL;
ctx->valid = 0;
ctx->chain = NULL;
ctx->error = 0;
ctx->explicit_policy = 0;
ctx->error_depth = 0;
ctx->current_cert = NULL;
ctx->current_issuer = NULL;
ctx->current_crl = NULL;
ctx->current_crl_score = 0;
ctx->current_reasons = 0;
ctx->tree = NULL;
ctx->parent = NULL;
ctx->dane = NULL;
ctx->bare_ta_signed = 0;
/* Zero ex_data to make sure we're cleanup-safe */
memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
/* store->cleanup is always 0 in OpenSSL, if set must be idempotent */
if (store)
ctx->cleanup = store->cleanup;
else
ctx->cleanup = 0;
if (store && store->check_issued)
ctx->check_issued = store->check_issued;
else
ctx->check_issued = check_issued;
if (store && store->get_issuer)
ctx->get_issuer = store->get_issuer;
else
ctx->get_issuer = X509_STORE_CTX_get1_issuer;
if (store && store->verify_cb)
ctx->verify_cb = store->verify_cb;
else
ctx->verify_cb = null_callback;
if (store && store->verify)
ctx->verify = store->verify;
else
ctx->verify = internal_verify;
if (store && store->check_revocation)
ctx->check_revocation = store->check_revocation;
else
ctx->check_revocation = check_revocation;
if (store && store->get_crl)
ctx->get_crl = store->get_crl;
else
ctx->get_crl = NULL;
if (store && store->check_crl)
ctx->check_crl = store->check_crl;
else
ctx->check_crl = check_crl;
if (store && store->cert_crl)
ctx->cert_crl = store->cert_crl;
else
ctx->cert_crl = cert_crl;
if (store && store->check_policy)
ctx->check_policy = store->check_policy;
else
ctx->check_policy = check_policy;
if (store && store->lookup_certs)
ctx->lookup_certs = store->lookup_certs;
else
ctx->lookup_certs = X509_STORE_CTX_get1_certs;
if (store && store->lookup_crls)
ctx->lookup_crls = store->lookup_crls;
else
ctx->lookup_crls = X509_STORE_CTX_get1_crls;
ctx->param = X509_VERIFY_PARAM_new();
if (ctx->param == NULL) {
X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* Inherit callbacks and flags from X509_STORE if not set use defaults.
*/
if (store)
ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
else
ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE;
if (ret)
ret = X509_VERIFY_PARAM_inherit(ctx->param,
X509_VERIFY_PARAM_lookup("default"));
if (ret == 0) {
X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* XXX: For now, continue to inherit trust from VPM, but infer from the
* purpose if this still yields the default value.
*/
if (ctx->param->trust == X509_TRUST_DEFAULT) {
int idx = X509_PURPOSE_get_by_id(ctx->param->purpose);
X509_PURPOSE *xp = X509_PURPOSE_get0(idx);
if (xp != NULL)
ctx->param->trust = X509_PURPOSE_get_trust(xp);
}
if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
&ctx->ex_data))
return 1;
X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
err:
/*
* On error clean up allocated storage, if the store context was not
* allocated with X509_STORE_CTX_new() this is our last chance to do so.
*/
X509_STORE_CTX_cleanup(ctx);
return 0;
}
/*
* Set alternative lookup method: just a STACK of trusted certificates. This
* avoids X509_STORE nastiness where it isn't needed.
*/
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
ctx->other_ctx = sk;
ctx->get_issuer = get_issuer_sk;
ctx->lookup_certs = lookup_certs_sk;
}
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
{
/*
* We need to be idempotent because, unfortunately, free() also calls
* cleanup(), so the natural call sequence new(), init(), cleanup(), free()
* calls cleanup() for the same object twice! Thus we must zero the
* pointers below after they're freed!
*/
/* Seems to always be 0 in OpenSSL, do this at most once. */
if (ctx->cleanup != NULL) {
ctx->cleanup(ctx);
ctx->cleanup = NULL;
}
if (ctx->param != NULL) {
if (ctx->parent == NULL)
X509_VERIFY_PARAM_free(ctx->param);
ctx->param = NULL;
}
X509_policy_tree_free(ctx->tree);
ctx->tree = NULL;
sk_X509_pop_free(ctx->chain, X509_free);
ctx->chain = NULL;
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
}
void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
{
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
}
void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
{
X509_VERIFY_PARAM_set_flags(ctx->param, flags);
}
void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
time_t t)
{
X509_VERIFY_PARAM_set_time(ctx->param, t);
}
X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
{
return ctx->cert;
}
STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
{
return ctx->untrusted;
}
void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
ctx->untrusted = sk;
}
void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
sk_X509_pop_free(ctx->chain, X509_free);
ctx->chain = sk;
}
void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
X509_STORE_CTX_verify_cb verify_cb)
{
ctx->verify_cb = verify_cb;
}
X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx)
{
return ctx->verify_cb;
}
void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx,
X509_STORE_CTX_verify_fn verify)
{
ctx->verify = verify;
}
X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx)
{
return ctx->verify;
}
X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx)
{
return ctx->get_issuer;
}
X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx)
{
return ctx->check_issued;
}
X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx)
{
return ctx->check_revocation;
}
X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx)
{
return ctx->get_crl;
}
X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx)
{
return ctx->check_crl;
}
X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx)
{
return ctx->cert_crl;
}
X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx)
{
return ctx->check_policy;
}
X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx)
{
return ctx->lookup_certs;
}
X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx)
{
return ctx->lookup_crls;
}
X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx)
{
return ctx->cleanup;
}
X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
{
return ctx->tree;
}
int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
{
return ctx->explicit_policy;
}
int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx)
{
return ctx->num_untrusted;
}
int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
{
const X509_VERIFY_PARAM *param;
param = X509_VERIFY_PARAM_lookup(name);
if (!param)
return 0;
return X509_VERIFY_PARAM_inherit(ctx->param, param);
}
X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
{
return ctx->param;
}
void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
{
X509_VERIFY_PARAM_free(ctx->param);
ctx->param = param;
}
void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane)
{
ctx->dane = dane;
}
static unsigned char *dane_i2d(
X509 *cert,
uint8_t selector,
unsigned int *i2dlen)
{
unsigned char *buf = NULL;
int len;
/*
* Extract ASN.1 DER form of certificate or public key.
*/
switch (selector) {
case DANETLS_SELECTOR_CERT:
len = i2d_X509(cert, &buf);
break;
case DANETLS_SELECTOR_SPKI:
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &buf);
break;
default:
X509err(X509_F_DANE_I2D, X509_R_BAD_SELECTOR);
return NULL;
}
if (len < 0 || buf == NULL) {
X509err(X509_F_DANE_I2D, ERR_R_MALLOC_FAILURE);
return NULL;
}
*i2dlen = (unsigned int)len;
return buf;
}
#define DANETLS_NONE 256 /* impossible uint8_t */
static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
{
SSL_DANE *dane = ctx->dane;
unsigned usage = DANETLS_NONE;
unsigned selector = DANETLS_NONE;
unsigned ordinal = DANETLS_NONE;
unsigned mtype = DANETLS_NONE;
unsigned char *i2dbuf = NULL;
unsigned int i2dlen = 0;
unsigned char mdbuf[EVP_MAX_MD_SIZE];
unsigned char *cmpbuf = NULL;
unsigned int cmplen = 0;
int i;
int recnum;
int matched = 0;
danetls_record *t = NULL;
uint32_t mask;
mask = (depth == 0) ? DANETLS_EE_MASK : DANETLS_TA_MASK;
/*
* The trust store is not applicable with DANE-TA(2)
*/
if (depth >= ctx->num_untrusted)
mask &= DANETLS_PKIX_MASK;
/*
* If we've previously matched a PKIX-?? record, no need to test any
* further PKIX-?? records, it remains to just build the PKIX chain.
* Had the match been a DANE-?? record, we'd be done already.
*/
if (dane->mdpth >= 0)
mask &= ~DANETLS_PKIX_MASK;
/*-
* https://tools.ietf.org/html/rfc7671#section-5.1
* https://tools.ietf.org/html/rfc7671#section-5.2
* https://tools.ietf.org/html/rfc7671#section-5.3
* https://tools.ietf.org/html/rfc7671#section-5.4
*
* We handle DANE-EE(3) records first as they require no chain building
* and no expiration or hostname checks. We also process digests with
* higher ordinals first and ignore lower priorities except Full(0) which
* is always processed (last). If none match, we then process PKIX-EE(1).
*
* NOTE: This relies on DANE usages sorting before the corresponding PKIX
* usages in SSL_dane_tlsa_add(), and also on descending sorting of digest
* priorities. See twin comment in ssl/ssl_lib.c.
*
* We expect that most TLSA RRsets will have just a single usage, so we
* don't go out of our way to cache multiple selector-specific i2d buffers
* across usages, but if the selector happens to remain the same as switch
* usages, that's OK. Thus, a set of "3 1 1", "3 0 1", "1 1 1", "1 0 1",
* records would result in us generating each of the certificate and public
* key DER forms twice, but more typically we'd just see multiple "3 1 1"
* or multiple "3 0 1" records.
*
* As soon as we find a match at any given depth, we stop, because either
* we've matched a DANE-?? record and the peer is authenticated, or, after
* exhausting all DANE-?? records, we've matched a PKIX-?? record, which is
* sufficient for DANE, and what remains to do is ordinary PKIX validation.
*/
recnum = (dane->umask & mask) ? sk_danetls_record_num(dane->trecs) : 0;
for (i = 0; matched == 0 && i < recnum; ++i) {
t = sk_danetls_record_value(dane->trecs, i);
if ((DANETLS_USAGE_BIT(t->usage) & mask) == 0)
continue;
if (t->usage != usage) {
usage = t->usage;
/* Reset digest agility for each usage/selector pair */
mtype = DANETLS_NONE;
ordinal = dane->dctx->mdord[t->mtype];
}
if (t->selector != selector) {
selector = t->selector;
/* Update per-selector state */
OPENSSL_free(i2dbuf);
i2dbuf = dane_i2d(cert, selector, &i2dlen);
if (i2dbuf == NULL)
return -1;
/* Reset digest agility for each usage/selector pair */
mtype = DANETLS_NONE;
ordinal = dane->dctx->mdord[t->mtype];
} else if (t->mtype != DANETLS_MATCHING_FULL) {
/*-
* Digest agility:
*
* <https://tools.ietf.org/html/rfc7671#section-9>
*
* For a fixed selector, after processing all records with the
* highest mtype ordinal, ignore all mtypes with lower ordinals
* other than "Full".
*/
if (dane->dctx->mdord[t->mtype] < ordinal)
continue;
}
/*
* Each time we hit a (new selector or) mtype, re-compute the relevant
* digest, more complex caching is not worth the code space.
*/
if (t->mtype != mtype) {
const EVP_MD *md = dane->dctx->mdevp[mtype = t->mtype];
cmpbuf = i2dbuf;
cmplen = i2dlen;
if (md != NULL) {
cmpbuf = mdbuf;
if (!EVP_Digest(i2dbuf, i2dlen, cmpbuf, &cmplen, md, 0)) {
matched = -1;
break;
}
}
}
/*
* Squirrel away the certificate and depth if we have a match. Any
* DANE match is dispositive, but with PKIX we still need to build a
* full chain.
*/
if (cmplen == t->dlen &&
memcmp(cmpbuf, t->data, cmplen) == 0) {
if (DANETLS_USAGE_BIT(usage) & DANETLS_DANE_MASK)
matched = 1;
if (matched || dane->mdpth < 0) {
dane->mdpth = depth;
dane->mtlsa = t;
OPENSSL_free(dane->mcert);
dane->mcert = cert;
X509_up_ref(cert);
}
break;
}
}
/* Clear the one-element DER cache */
OPENSSL_free(i2dbuf);
return matched;
}
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth)
{
SSL_DANE *dane = ctx->dane;
int matched = 0;
X509 *cert;
if (!DANETLS_HAS_TA(dane) || depth == 0)
return X509_TRUST_UNTRUSTED;
/*
* Record any DANE trust-anchor matches, for the first depth to test, if
* there's one at that depth. (This'll be false for length 1 chains looking
* for an exact match for the leaf certificate).
*/
cert = sk_X509_value(ctx->chain, depth);
if (cert != NULL && (matched = dane_match(ctx, cert, depth)) < 0)
return X509_TRUST_REJECTED;
if (matched > 0) {
ctx->num_untrusted = depth - 1;
return X509_TRUST_TRUSTED;
}
return X509_TRUST_UNTRUSTED;
}
static int check_dane_pkeys(X509_STORE_CTX *ctx)
{
SSL_DANE *dane = ctx->dane;
danetls_record *t;
int num = ctx->num_untrusted;
X509 *cert = sk_X509_value(ctx->chain, num - 1);
int recnum = sk_danetls_record_num(dane->trecs);
int i;
for (i = 0; i < recnum; ++i) {
t = sk_danetls_record_value(dane->trecs, i);
if (t->usage != DANETLS_USAGE_DANE_TA ||
t->selector != DANETLS_SELECTOR_SPKI ||
t->mtype != DANETLS_MATCHING_FULL ||
X509_verify(cert, t->spki) <= 0)
continue;
/* Clear any PKIX-?? matches that failed to extend to a full chain */
X509_free(dane->mcert);
dane->mcert = NULL;
/* Record match via a bare TA public key */
ctx->bare_ta_signed = 1;
dane->mdpth = num - 1;
dane->mtlsa = t;
/* Prune any excess chain certificates */
num = sk_X509_num(ctx->chain);
for (; num > ctx->num_untrusted; --num)
X509_free(sk_X509_pop(ctx->chain));
return X509_TRUST_TRUSTED;
}
return X509_TRUST_UNTRUSTED;
}
static void dane_reset(SSL_DANE *dane)
{
/*
* Reset state to verify another chain, or clear after failure.
*/
X509_free(dane->mcert);
dane->mcert = NULL;
dane->mtlsa = NULL;
dane->mdpth = -1;
dane->pdpth = -1;
}
static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert)
{
int err = X509_chain_check_suiteb(NULL, cert, NULL, ctx->param->flags);
if (err == X509_V_OK)
return 1;
return verify_cb_cert(ctx, cert, 0, err);
}
static int dane_verify(X509_STORE_CTX *ctx)
{
X509 *cert = ctx->cert;
SSL_DANE *dane = ctx->dane;
int matched;
int done;
dane_reset(dane);
/*-
* When testing the leaf certificate, if we match a DANE-EE(3) record,
* dane_match() returns 1 and we're done. If however we match a PKIX-EE(1)
* record, the match depth and matching TLSA record are recorded, but the
* return value is 0, because we still need to find a PKIX trust-anchor.
* Therefore, when DANE authentication is enabled (required), we're done
* if:
* + matched < 0, internal error.
* + matched == 1, we matched a DANE-EE(3) record
* + matched == 0, mdepth < 0 (no PKIX-EE match) and there are no
* DANE-TA(2) or PKIX-TA(0) to test.
*/
matched = dane_match(ctx, ctx->cert, 0);
done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0);
if (done)
X509_get_pubkey_parameters(NULL, ctx->chain);
if (matched > 0) {
/* Callback invoked as needed */
if (!check_leaf_suiteb(ctx, cert))
return 0;
/* Callback invoked as needed */
if ((dane->flags & DANE_FLAG_NO_DANE_EE_NAMECHECKS) == 0 &&
!check_id(ctx))
return 0;
/* Bypass internal_verify(), issue depth 0 success callback */
ctx->error_depth = 0;
ctx->current_cert = cert;
return ctx->verify_cb(1, ctx);
}
if (matched < 0) {
ctx->error_depth = 0;
ctx->current_cert = cert;
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
if (done) {
/* Fail early, TA-based success is not possible */
if (!check_leaf_suiteb(ctx, cert))
return 0;
return verify_cb_cert(ctx, cert, 0, X509_V_ERR_DANE_NO_MATCH);
}
/*
* Chain verification for usages 0/1/2. TLSA record matching of depth > 0
* certificates happens in-line with building the rest of the chain.
*/
return verify_chain(ctx);
}
/* Get issuer, without duplicate suppression */
static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert)
{
STACK_OF(X509) *saved_chain = ctx->chain;
int ok;
ctx->chain = NULL;
ok = ctx->get_issuer(issuer, ctx, cert);
ctx->chain = saved_chain;
return ok;
}
static int build_chain(X509_STORE_CTX *ctx)
{
SSL_DANE *dane = ctx->dane;
int num = sk_X509_num(ctx->chain);
X509 *cert = sk_X509_value(ctx->chain, num - 1);
int ss = cert_self_signed(cert);
STACK_OF(X509) *sktmp = NULL;
unsigned int search;
int may_trusted = 0;
int may_alternate = 0;
int trust = X509_TRUST_UNTRUSTED;
int alt_untrusted = 0;
int depth;
int ok = 0;
int i;
/* Our chain starts with a single untrusted element. */
if (!ossl_assert(num == 1 && ctx->num_untrusted == num)) {
X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
ctx->error = X509_V_ERR_UNSPECIFIED;
return 0;
}
#define S_DOUNTRUSTED (1 << 0) /* Search untrusted chain */
#define S_DOTRUSTED (1 << 1) /* Search trusted store */
#define S_DOALTERNATE (1 << 2) /* Retry with pruned alternate chain */
/*
* Set up search policy, untrusted if possible, trusted-first if enabled.
* If we're doing DANE and not doing PKIX-TA/PKIX-EE, we never look in the
* trust_store, otherwise we might look there first. If not trusted-first,
* and alternate chains are not disabled, try building an alternate chain
* if no luck with untrusted first.
*/
search = (ctx->untrusted != NULL) ? S_DOUNTRUSTED : 0;
if (DANETLS_HAS_PKIX(dane) || !DANETLS_HAS_DANE(dane)) {
if (search == 0 || ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
search |= S_DOTRUSTED;
else if (!(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS))
may_alternate = 1;
may_trusted = 1;
}
/*
* Shallow-copy the stack of untrusted certificates (with TLS, this is
* typically the content of the peer's certificate message) so can make
* multiple passes over it, while free to remove elements as we go.
*/
if (ctx->untrusted && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
/*
* If we got any "DANE-TA(2) Cert(0) Full(0)" trust-anchors from DNS, add
* them to our working copy of the untrusted certificate stack. Since the
* caller of X509_STORE_CTX_init() may have provided only a leaf cert with
* no corresponding stack of untrusted certificates, we may need to create
* an empty stack first. [ At present only the ssl library provides DANE
* support, and ssl_verify_cert_chain() always provides a non-null stack
* containing at least the leaf certificate, but we must be prepared for
* this to change. ]
*/
if (DANETLS_ENABLED(dane) && dane->certs != NULL) {
if (sktmp == NULL && (sktmp = sk_X509_new_null()) == NULL) {
X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
for (i = 0; i < sk_X509_num(dane->certs); ++i) {
if (!sk_X509_push(sktmp, sk_X509_value(dane->certs, i))) {
sk_X509_free(sktmp);
X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
}
}
/*
* Still absurdly large, but arithmetically safe, a lower hard upper bound
* might be reasonable.
*/
if (ctx->param->depth > INT_MAX/2)
ctx->param->depth = INT_MAX/2;
/*
* Try to Extend the chain until we reach an ultimately trusted issuer.
* Build chains up to one longer the limit, later fail if we hit the limit,
* with an X509_V_ERR_CERT_CHAIN_TOO_LONG error code.
*/
depth = ctx->param->depth + 1;
while (search != 0) {
X509 *x;
X509 *xtmp = NULL;
/*
* Look in the trust store if enabled for first lookup, or we've run
* out of untrusted issuers and search here is not disabled. When we
* reach the depth limit, we stop extending the chain, if by that point
* we've not found a trust-anchor, any trusted chain would be too long.
*
* The error reported to the application verify callback is at the
* maximal valid depth with the current certificate equal to the last
* not ultimately-trusted issuer. For example, with verify_depth = 0,
* the callback will report errors at depth=1 when the immediate issuer
* of the leaf certificate is not a trust anchor. No attempt will be
* made to locate an issuer for that certificate, since such a chain
* would be a-priori too long.
*/
if ((search & S_DOTRUSTED) != 0) {
i = num = sk_X509_num(ctx->chain);
if ((search & S_DOALTERNATE) != 0) {
/*
* As high up the chain as we can, look for an alternative
* trusted issuer of an untrusted certificate that currently
* has an untrusted issuer. We use the alt_untrusted variable
* to track how far up the chain we find the first match. It
* is only if and when we find a match, that we prune the chain
* and reset ctx->num_untrusted to the reduced count of
* untrusted certificates. While we're searching for such a
* match (which may never be found), it is neither safe nor
* wise to preemptively modify either the chain or
* ctx->num_untrusted.
*
* Note, like ctx->num_untrusted, alt_untrusted is a count of
* untrusted certificates, not a "depth".
*/
i = alt_untrusted;
}
x = sk_X509_value(ctx->chain, i-1);
ok = (depth < num) ? 0 : get_issuer(&xtmp, ctx, x);
if (ok < 0) {
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_STORE_LOOKUP;
search = 0;
continue;
}
if (ok > 0) {
/*
* Alternative trusted issuer for a mid-chain untrusted cert?
* Pop the untrusted cert's successors and retry. We might now
* be able to complete a valid chain via the trust store. Note
* that despite the current trust-store match we might still
* fail complete the chain to a suitable trust-anchor, in which
* case we may prune some more untrusted certificates and try
* again. Thus the S_DOALTERNATE bit may yet be turned on
* again with an even shorter untrusted chain!
*
* If in the process we threw away our matching PKIX-TA trust
* anchor, reset DANE trust. We might find a suitable trusted
* certificate among the ones from the trust store.
*/
if ((search & S_DOALTERNATE) != 0) {
if (!ossl_assert(num > i && i > 0 && ss == 0)) {
X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
X509_free(xtmp);
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_UNSPECIFIED;
search = 0;
continue;
}
search &= ~S_DOALTERNATE;
for (; num > i; --num)
X509_free(sk_X509_pop(ctx->chain));
ctx->num_untrusted = num;
if (DANETLS_ENABLED(dane) &&
dane->mdpth >= ctx->num_untrusted) {
dane->mdpth = -1;
X509_free(dane->mcert);
dane->mcert = NULL;
}
if (DANETLS_ENABLED(dane) &&
dane->pdpth >= ctx->num_untrusted)
dane->pdpth = -1;
}
/*
* Self-signed untrusted certificates get replaced by their
* trusted matching issuer. Otherwise, grow the chain.
*/
if (ss == 0) {
if (!sk_X509_push(ctx->chain, x = xtmp)) {
X509_free(xtmp);
X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_OUT_OF_MEM;
search = 0;
continue;
}
ss = cert_self_signed(x);
} else if (num == ctx->num_untrusted) {
/*
* We have a self-signed certificate that has the same
* subject name (and perhaps keyid and/or serial number) as
* a trust-anchor. We must have an exact match to avoid
* possible impersonation via key substitution etc.
*/
if (X509_cmp(x, xtmp) != 0) {
/* Self-signed untrusted mimic. */
X509_free(xtmp);
ok = 0;
} else {
X509_free(x);
ctx->num_untrusted = --num;
(void) sk_X509_set(ctx->chain, num, x = xtmp);
}
}
/*
* We've added a new trusted certificate to the chain, recheck
* trust. If not done, and not self-signed look deeper.
* Whether or not we're doing "trusted first", we no longer
* look for untrusted certificates from the peer's chain.
*
* At this point ctx->num_trusted and num must reflect the
* correct number of untrusted certificates, since the DANE
* logic in check_trust() depends on distinguishing CAs from
* "the wire" from CAs from the trust store. In particular, the
* certificate at depth "num" should be the new trusted
* certificate with ctx->num_untrusted <= num.
*/
if (ok) {
if (!ossl_assert(ctx->num_untrusted <= num)) {
X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_UNSPECIFIED;
search = 0;
continue;
}
search &= ~S_DOUNTRUSTED;
switch (trust = check_trust(ctx, num)) {
case X509_TRUST_TRUSTED:
case X509_TRUST_REJECTED:
search = 0;
continue;
}
if (ss == 0)
continue;
}
}
/*
* No dispositive decision, and either self-signed or no match, if
* we were doing untrusted-first, and alt-chains are not disabled,
* do that, by repeatedly losing one untrusted element at a time,
* and trying to extend the shorted chain.
*/
if ((search & S_DOUNTRUSTED) == 0) {
/* Continue search for a trusted issuer of a shorter chain? */
if ((search & S_DOALTERNATE) != 0 && --alt_untrusted > 0)
continue;
/* Still no luck and no fallbacks left? */
if (!may_alternate || (search & S_DOALTERNATE) != 0 ||
ctx->num_untrusted < 2)
break;
/* Search for a trusted issuer of a shorter chain */
search |= S_DOALTERNATE;
alt_untrusted = ctx->num_untrusted - 1;
ss = 0;
}
}
/*
* Extend chain with peer-provided certificates
*/
if ((search & S_DOUNTRUSTED) != 0) {
num = sk_X509_num(ctx->chain);
if (!ossl_assert(num == ctx->num_untrusted)) {
X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_UNSPECIFIED;
search = 0;
continue;
}
x = sk_X509_value(ctx->chain, num-1);
/*
* Once we run out of untrusted issuers, we stop looking for more
* and start looking only in the trust store if enabled.
*/
xtmp = (ss || depth < num) ? NULL : find_issuer(ctx, sktmp, x);
if (xtmp == NULL) {
search &= ~S_DOUNTRUSTED;
if (may_trusted)
search |= S_DOTRUSTED;
continue;
}
/* Drop this issuer from future consideration */
(void) sk_X509_delete_ptr(sktmp, xtmp);
if (!sk_X509_push(ctx->chain, xtmp)) {
X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_OUT_OF_MEM;
search = 0;
continue;
}
X509_up_ref(x = xtmp);
++ctx->num_untrusted;
ss = cert_self_signed(xtmp);
/*
* Check for DANE-TA trust of the topmost untrusted certificate.
*/
switch (trust = check_dane_issuer(ctx, ctx->num_untrusted - 1)) {
case X509_TRUST_TRUSTED:
case X509_TRUST_REJECTED:
search = 0;
continue;
}
}
}
sk_X509_free(sktmp);
/*
* Last chance to make a trusted chain, either bare DANE-TA public-key
* signers, or else direct leaf PKIX trust.
*/
num = sk_X509_num(ctx->chain);
if (num <= depth) {
if (trust == X509_TRUST_UNTRUSTED && DANETLS_HAS_DANE_TA(dane))
trust = check_dane_pkeys(ctx);
if (trust == X509_TRUST_UNTRUSTED && num == ctx->num_untrusted)
trust = check_trust(ctx, num);
}
switch (trust) {
case X509_TRUST_TRUSTED:
return 1;
case X509_TRUST_REJECTED:
/* Callback already issued */
return 0;
case X509_TRUST_UNTRUSTED:
default:
num = sk_X509_num(ctx->chain);
if (num > depth)
return verify_cb_cert(ctx, NULL, num-1,
X509_V_ERR_CERT_CHAIN_TOO_LONG);
if (DANETLS_ENABLED(dane) &&
(!DANETLS_HAS_PKIX(dane) || dane->pdpth >= 0))
return verify_cb_cert(ctx, NULL, num-1, X509_V_ERR_DANE_NO_MATCH);
if (ss && sk_X509_num(ctx->chain) == 1)
return verify_cb_cert(ctx, NULL, num-1,
X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
if (ss)
return verify_cb_cert(ctx, NULL, num-1,
X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
if (ctx->num_untrusted < num)
return verify_cb_cert(ctx, NULL, num-1,
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
return verify_cb_cert(ctx, NULL, num-1,
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
}
}
static const int minbits_table[] = { 80, 112, 128, 192, 256 };
static const int NUM_AUTH_LEVELS = OSSL_NELEM(minbits_table);
/*
* Check whether the public key of ``cert`` meets the security level of
* ``ctx``.
*
* Returns 1 on success, 0 otherwise.
*/
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert)
{
EVP_PKEY *pkey = X509_get0_pubkey(cert);
int level = ctx->param->auth_level;
/* Unsupported or malformed keys are not secure */
if (pkey == NULL)
return 0;
if (level <= 0)
return 1;
if (level > NUM_AUTH_LEVELS)
level = NUM_AUTH_LEVELS;
return EVP_PKEY_security_bits(pkey) >= minbits_table[level - 1];
}
/*
* Check whether the signature digest algorithm of ``cert`` meets the security
* level of ``ctx``. Should not be checked for trust anchors (whether
* self-signed or otherwise).
*
* Returns 1 on success, 0 otherwise.
*/
static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert)
{
int secbits = -1;
int level = ctx->param->auth_level;
if (level <= 0)
return 1;
if (level > NUM_AUTH_LEVELS)
level = NUM_AUTH_LEVELS;
if (!X509_get_signature_info(cert, NULL, NULL, &secbits, NULL))
return 0;
return secbits >= minbits_table[level - 1];
}
diff --git a/doc/man1/ca.pod b/doc/man1/ca.pod
index 9b282e6479a8..e998eabf8358 100644
--- a/doc/man1/ca.pod
+++ b/doc/man1/ca.pod
@@ -1,761 +1,763 @@
=pod
=head1 NAME
openssl-ca,
ca - sample minimal CA application
=head1 SYNOPSIS
B<openssl> B<ca>
[B<-help>]
[B<-verbose>]
[B<-config filename>]
[B<-name section>]
[B<-gencrl>]
[B<-revoke file>]
[B<-valid file>]
[B<-status serial>]
[B<-updatedb>]
[B<-crl_reason reason>]
[B<-crl_hold instruction>]
[B<-crl_compromise time>]
[B<-crl_CA_compromise time>]
[B<-crldays days>]
[B<-crlhours hours>]
[B<-crlexts section>]
[B<-startdate date>]
[B<-enddate date>]
[B<-days arg>]
[B<-md arg>]
[B<-policy arg>]
[B<-keyfile arg>]
[B<-keyform PEM|DER>]
[B<-key arg>]
[B<-passin arg>]
[B<-cert file>]
[B<-selfsign>]
[B<-in file>]
[B<-out file>]
[B<-notext>]
[B<-outdir dir>]
[B<-infiles>]
[B<-spkac file>]
[B<-ss_cert file>]
[B<-preserveDN>]
[B<-noemailDN>]
[B<-batch>]
[B<-msie_hack>]
[B<-extensions section>]
[B<-extfile section>]
[B<-engine id>]
[B<-subj arg>]
[B<-utf8>]
[B<-create_serial>]
[B<-rand_serial>]
[B<-multivalue-rdn>]
[B<-rand file...>]
[B<-writerand file>]
=head1 DESCRIPTION
The B<ca> command is a minimal CA application. It can be used
to sign certificate requests in a variety of forms and generate
CRLs it also maintains a text database of issued certificates
and their status.
The options descriptions will be divided into each purpose.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-verbose>
This prints extra details about the operations being performed.
=item B<-config filename>
Specifies the configuration file to use.
Optional; for a description of the default value,
see L<openssl(1)/COMMAND SUMMARY>.
=item B<-name section>
Specifies the configuration file section to use (overrides
B<default_ca> in the B<ca> section).
=item B<-in filename>
An input filename containing a single certificate request to be
signed by the CA.
=item B<-ss_cert filename>
A single self-signed certificate to be signed by the CA.
=item B<-spkac filename>
A file containing a single Netscape signed public key and challenge
and additional field values to be signed by the CA. See the B<SPKAC FORMAT>
section for information on the required input and output format.
=item B<-infiles>
If present this should be the last option, all subsequent arguments
are taken as the names of files containing certificate requests.
=item B<-out filename>
The output file to output certificates to. The default is standard
output. The certificate details will also be printed out to this
file in PEM format (except that B<-spkac> outputs DER format).
=item B<-outdir directory>
The directory to output certificates to. The certificate will be
written to a filename consisting of the serial number in hex with
".pem" appended.
=item B<-cert>
The CA certificate file.
=item B<-keyfile filename>
The private key to sign requests with.
=item B<-keyform PEM|DER>
The format of the data in the private key file.
The default is PEM.
=item B<-key password>
The password used to encrypt the private key. Since on some
systems the command line arguments are visible (e.g. Unix with
the 'ps' utility) this option should be used with caution.
=item B<-selfsign>
Indicates the issued certificates are to be signed with the key
the certificate requests were signed with (given with B<-keyfile>).
Certificate requests signed with a different key are ignored. If
B<-spkac>, B<-ss_cert> or B<-gencrl> are given, B<-selfsign> is
ignored.
A consequence of using B<-selfsign> is that the self-signed
certificate appears among the entries in the certificate database
(see the configuration option B<database>), and uses the same
serial number counter as all other certificates sign with the
self-signed certificate.
=item B<-passin arg>
The 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<-notext>
Don't output the text form of a certificate to the output file.
=item B<-startdate date>
This allows the start date to be explicitly set. The format of the
date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure), or
YYYYMMDDHHMMSSZ (the same as an ASN1 GeneralizedTime structure). In
both formats, seconds SS and timezone Z must be present.
=item B<-enddate date>
This allows the expiry date to be explicitly set. The format of the
date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure), or
YYYYMMDDHHMMSSZ (the same as an ASN1 GeneralizedTime structure). In
both formats, seconds SS and timezone Z must be present.
=item B<-days arg>
The number of days to certify the certificate for.
=item B<-md alg>
The message digest to use.
Any digest supported by the OpenSSL B<dgst> command can be used. For signing
algorithms that do not support a digest (i.e. Ed25519 and Ed448) any message
digest that is set is ignored. This option also applies to CRLs.
=item B<-policy arg>
This option defines the CA "policy" to use. This is a section in
the configuration file which decides which fields should be mandatory
or match the CA certificate. Check out the B<POLICY FORMAT> section
for more information.
=item B<-msie_hack>
This is a deprecated option to make B<ca> work with very old versions of
the IE certificate enrollment control "certenr3". It used UniversalStrings
for almost everything. Since the old control has various security bugs
its use is strongly discouraged.
=item B<-preserveDN>
Normally the DN order of a certificate is the same as the order of the
fields in the relevant policy section. When this option is set the order
is the same as the request. This is largely for compatibility with the
older IE enrollment control which would only accept certificates if their
DNs match the order of the request. This is not needed for Xenroll.
=item B<-noemailDN>
The DN of a certificate can contain the EMAIL field if present in the
request DN, however it is good policy just having the e-mail set into
the altName extension of the certificate. When this option is set the
EMAIL field is removed from the certificate' subject and set only in
the, eventually present, extensions. The B<email_in_dn> keyword can be
used in the configuration file to enable this behaviour.
=item B<-batch>
This sets the batch mode. In this mode no questions will be asked
and all certificates will be certified automatically.
=item B<-extensions section>
The section of the configuration file containing certificate extensions
to be added when a certificate is issued (defaults to B<x509_extensions>
unless the B<-extfile> option is used). If no extension section is
present then, a V1 certificate is created. If the extension section
is present (even if it is empty), then a V3 certificate is created. See the:w
L<x509v3_config(5)> manual page for details of the
extension section format.
=item B<-extfile file>
An additional configuration file to read certificate extensions from
(using the default section unless the B<-extensions> option is also
used).
=item B<-engine id>
Specifying an engine (by its unique B<id> string) will cause B<ca>
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<-subj arg>
Supersedes subject name given in the request.
-The arg must be formatted as I</type0=value0/type1=value1/type2=...>,
-characters may be escaped by \ (backslash), no spaces are skipped.
+The arg must be formatted as I</type0=value0/type1=value1/type2=...>.
+Keyword characters may be escaped by \ (backslash), and whitespace is retained.
+Empty values are permitted, but the corresponding type will not be included
+in the resulting certificate.
=item B<-utf8>
This option causes field values to be interpreted as UTF8 strings, by
default they are interpreted as ASCII. This means that the field
values, whether prompted from a terminal or obtained from a
configuration file, must be valid UTF8 strings.
=item B<-create_serial>
If reading serial from the text file as specified in the configuration
fails, specifying this option creates a new random serial to be used as next
serial number.
To get random serial numbers, use the B<-rand_serial> flag instead; this
should only be used for simple error-recovery.
=item B<-rand_serial>
Generate a large random number to use as the serial number.
This overrides any option or configuration to use a serial number file.
=item B<-multivalue-rdn>
This option causes the -subj argument to be interpreted with full
support for multivalued RDNs. Example:
I</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
If -multi-rdn is not used then the UID value is I<123456+CN=John Doe>.
=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.
=back
=head1 CRL OPTIONS
=over 4
=item B<-gencrl>
This option generates a CRL based on information in the index file.
=item B<-crldays num>
The number of days before the next CRL is due. That is the days from
now to place in the CRL nextUpdate field.
=item B<-crlhours num>
The number of hours before the next CRL is due.
=item B<-revoke filename>
A filename containing a certificate to revoke.
=item B<-valid filename>
A filename containing a certificate to add a Valid certificate entry.
=item B<-status serial>
Displays the revocation status of the certificate with the specified
serial number and exits.
=item B<-updatedb>
Updates the database index to purge expired certificates.
=item B<-crl_reason reason>
Revocation reason, where B<reason> is one of: B<unspecified>, B<keyCompromise>,
B<CACompromise>, B<affiliationChanged>, B<superseded>, B<cessationOfOperation>,
B<certificateHold> or B<removeFromCRL>. The matching of B<reason> is case
insensitive. Setting any revocation reason will make the CRL v2.
In practice B<removeFromCRL> is not particularly useful because it is only used
in delta CRLs which are not currently implemented.
=item B<-crl_hold instruction>
This sets the CRL revocation reason code to B<certificateHold> and the hold
instruction to B<instruction> which must be an OID. Although any OID can be
used only B<holdInstructionNone> (the use of which is discouraged by RFC2459)
B<holdInstructionCallIssuer> or B<holdInstructionReject> will normally be used.
=item B<-crl_compromise time>
This sets the revocation reason to B<keyCompromise> and the compromise time to
B<time>. B<time> should be in GeneralizedTime format that is B<YYYYMMDDHHMMSSZ>.
=item B<-crl_CA_compromise time>
This is the same as B<crl_compromise> except the revocation reason is set to
B<CACompromise>.
=item B<-crlexts section>
The section of the configuration file containing CRL extensions to
include. If no CRL extension section is present then a V1 CRL is
created, if the CRL extension section is present (even if it is
empty) then a V2 CRL is created. The CRL extensions specified are
CRL extensions and B<not> CRL entry extensions. It should be noted
that some software (for example Netscape) can't handle V2 CRLs. See
L<x509v3_config(5)> manual page for details of the
extension section format.
=back
=head1 CONFIGURATION FILE OPTIONS
The section of the configuration file containing options for B<ca>
is found as follows: If the B<-name> command line option is used,
then it names the section to be used. Otherwise the section to
be used must be named in the B<default_ca> option of the B<ca> section
of the configuration file (or in the default section of the
configuration file). Besides B<default_ca>, the following options are
read directly from the B<ca> section:
RANDFILE
preserve
msie_hack
With the exception of B<RANDFILE>, this is probably a bug and may
change in future releases.
Many of the configuration file options are identical to command line
options. Where the option is present in the configuration file
and the command line the command line value is used. Where an
option is described as mandatory then it must be present in
the configuration file or the command line equivalent (if
any) used.
=over 4
=item B<oid_file>
This specifies a file containing additional B<OBJECT IDENTIFIERS>.
Each line of the file should consist of the numerical form of the
object identifier followed by white space then the short name followed
by white space and finally the long name.
=item B<oid_section>
This specifies a section in the configuration file containing extra
object identifiers. Each line should consist of the short name of the
object identifier followed by B<=> and the numerical form. The short
and long names are the same when this option is used.
=item B<new_certs_dir>
The same as the B<-outdir> command line option. It specifies
the directory where new certificates will be placed. Mandatory.
=item B<certificate>
The same as B<-cert>. It gives the file containing the CA
certificate. Mandatory.
=item B<private_key>
Same as the B<-keyfile> option. The file containing the
CA private key. Mandatory.
=item B<RANDFILE>
At startup the specified file is loaded into the random number generator,
and at exit 256 bytes will be written to it.
=item B<default_days>
The same as the B<-days> option. The number of days to certify
a certificate for.
=item B<default_startdate>
The same as the B<-startdate> option. The start date to certify
a certificate for. If not set the current time is used.
=item B<default_enddate>
The same as the B<-enddate> option. Either this option or
B<default_days> (or the command line equivalents) must be
present.
=item B<default_crl_hours default_crl_days>
The same as the B<-crlhours> and the B<-crldays> options. These
will only be used if neither command line option is present. At
least one of these must be present to generate a CRL.
=item B<default_md>
The same as the B<-md> option. Mandatory except where the signing algorithm does
not require a digest (i.e. Ed25519 and Ed448).
=item B<database>
The text database file to use. Mandatory. This file must be present
though initially it will be empty.
=item B<unique_subject>
If the value B<yes> is given, the valid certificate entries in the
database must have unique subjects. if the value B<no> is given,
several valid certificate entries may have the exact same subject.
The default value is B<yes>, to be compatible with older (pre 0.9.8)
versions of OpenSSL. However, to make CA certificate roll-over easier,
it's recommended to use the value B<no>, especially if combined with
the B<-selfsign> command line option.
Note that it is valid in some circumstances for certificates to be created
without any subject. In the case where there are multiple certificates without
subjects this does not count as a duplicate.
=item B<serial>
A text file containing the next serial number to use in hex. Mandatory.
This file must be present and contain a valid serial number.
=item B<crlnumber>
A text file containing the next CRL number to use in hex. The crl number
will be inserted in the CRLs only if this file exists. If this file is
present, it must contain a valid CRL number.
=item B<x509_extensions>
The same as B<-extensions>.
=item B<crl_extensions>
The same as B<-crlexts>.
=item B<preserve>
The same as B<-preserveDN>
=item B<email_in_dn>
The same as B<-noemailDN>. If you want the EMAIL field to be removed
from the DN of the certificate simply set this to 'no'. If not present
the default is to allow for the EMAIL filed in the certificate's DN.
=item B<msie_hack>
The same as B<-msie_hack>
=item B<policy>
The same as B<-policy>. Mandatory. See the B<POLICY FORMAT> section
for more information.
=item B<name_opt>, B<cert_opt>
These options allow the format used to display the certificate details
when asking the user to confirm signing. All the options supported by
the B<x509> utilities B<-nameopt> and B<-certopt> switches can be used
here, except the B<no_signame> and B<no_sigdump> are permanently set
and cannot be disabled (this is because the certificate signature cannot
be displayed because the certificate has not been signed at this point).
For convenience the values B<ca_default> are accepted by both to produce
a reasonable output.
If neither option is present the format used in earlier versions of
OpenSSL is used. Use of the old format is B<strongly> discouraged because
it only displays fields mentioned in the B<policy> section, mishandles
multicharacter string types and does not display extensions.
=item B<copy_extensions>
Determines how extensions in certificate requests should be handled.
If set to B<none> or this option is not present then extensions are
ignored and not copied to the certificate. If set to B<copy> then any
extensions present in the request that are not already present are copied
to the certificate. If set to B<copyall> then all extensions in the
request are copied to the certificate: if the extension is already present
in the certificate it is deleted first. See the B<WARNINGS> section before
using this option.
The main use of this option is to allow a certificate request to supply
values for certain extensions such as subjectAltName.
=back
=head1 POLICY FORMAT
The policy section consists of a set of variables corresponding to
certificate DN fields. If the value is "match" then the field value
must match the same field in the CA certificate. If the value is
"supplied" then it must be present. If the value is "optional" then
it may be present. Any fields not mentioned in the policy section
are silently deleted, unless the B<-preserveDN> option is set but
this can be regarded more of a quirk than intended behaviour.
=head1 SPKAC FORMAT
The input to the B<-spkac> command line option is a Netscape
signed public key and challenge. This will usually come from
the B<KEYGEN> tag in an HTML form to create a new private key.
It is however possible to create SPKACs using the B<spkac> utility.
The file should contain the variable SPKAC set to the value of
the SPKAC and also the required DN components as name value pairs.
If you need to include the same component twice then it can be
preceded by a number and a '.'.
When processing SPKAC format, the output is DER if the B<-out>
flag is used, but PEM format if sending to stdout or the B<-outdir>
flag is used.
=head1 EXAMPLES
Note: these examples assume that the B<ca> directory structure is
already set up and the relevant files already exist. This usually
involves creating a CA certificate and private key with B<req>, a
serial number file and an empty index file and placing them in
the relevant directories.
To use the sample configuration file below the directories demoCA,
demoCA/private and demoCA/newcerts would be created. The CA
certificate would be copied to demoCA/cacert.pem and its private
key to demoCA/private/cakey.pem. A file demoCA/serial would be
created containing for example "01" and the empty index file
demoCA/index.txt.
Sign a certificate request:
openssl ca -in req.pem -out newcert.pem
Sign a certificate request, using CA extensions:
openssl ca -in req.pem -extensions v3_ca -out newcert.pem
Generate a CRL
openssl ca -gencrl -out crl.pem
Sign several requests:
openssl ca -infiles req1.pem req2.pem req3.pem
Certify a Netscape SPKAC:
openssl ca -spkac spkac.txt
A sample SPKAC file (the SPKAC line has been truncated for clarity):
SPKAC=MIG0MGAwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PDhCeV/xIxUg8V70YRxK2A5
CN=Steve Test
emailAddress=steve@openssl.org
0.OU=OpenSSL Group
1.OU=Another Group
A sample configuration file with the relevant sections for B<ca>:
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
dir = ./demoCA # top dir
database = $dir/index.txt # index file.
new_certs_dir = $dir/newcerts # new certs dir
certificate = $dir/cacert.pem # The CA cert
serial = $dir/serial # serial no file
#rand_serial = yes # for random serial#'s
private_key = $dir/private/cakey.pem# CA private key
RANDFILE = $dir/private/.rand # random number file
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = md5 # md to use
policy = policy_any # default policy
email_in_dn = no # Don't add the email into cert DN
name_opt = ca_default # Subject name display option
cert_opt = ca_default # Certificate display option
copy_extensions = none # Don't copy extensions from request
[ policy_any ]
countryName = supplied
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
=head1 FILES
Note: the location of all files can change either by compile time options,
configuration file entries, environment variables or command line options.
The values below reflect the default values.
/usr/local/ssl/lib/openssl.cnf - master configuration file
./demoCA - main CA directory
./demoCA/cacert.pem - CA certificate
./demoCA/private/cakey.pem - CA private key
./demoCA/serial - CA serial number file
./demoCA/serial.old - CA serial number backup file
./demoCA/index.txt - CA text database file
./demoCA/index.txt.old - CA text database backup file
./demoCA/certs - certificate output file
./demoCA/.rnd - CA random seed information
=head1 RESTRICTIONS
The text database index file is a critical part of the process and
if corrupted it can be difficult to fix. It is theoretically possible
to rebuild the index file from all the issued certificates and a current
CRL: however there is no option to do this.
V2 CRL features like delta CRLs are not currently supported.
Although several requests can be input and handled at once it is only
possible to include one SPKAC or self-signed certificate.
=head1 BUGS
The use of an in-memory text database can cause problems when large
numbers of certificates are present because, as the name implies
the database has to be kept in memory.
The B<ca> command really needs rewriting or the required functionality
exposed at either a command or interface level so a more friendly utility
(perl script or GUI) can handle things properly. The script
B<CA.pl> helps a little but not very much.
Any fields in a request that are not present in a policy are silently
deleted. This does not happen if the B<-preserveDN> option is used. To
enforce the absence of the EMAIL field within the DN, as suggested by
RFCs, regardless the contents of the request' subject the B<-noemailDN>
option can be used. The behaviour should be more friendly and
configurable.
Canceling some commands by refusing to certify a certificate can
create an empty file.
=head1 WARNINGS
The B<ca> command is quirky and at times downright unfriendly.
The B<ca> utility was originally meant as an example of how to do things
in a CA. It was not supposed to be used as a full blown CA itself:
nevertheless some people are using it for this purpose.
The B<ca> command is effectively a single user command: no locking is
done on the various files and attempts to run more than one B<ca> command
on the same database can have unpredictable results.
The B<copy_extensions> option should be used with caution. If care is
not taken then it can be a security risk. For example if a certificate
request contains a basicConstraints extension with CA:TRUE and the
B<copy_extensions> value is set to B<copyall> and the user does not spot
this when the certificate is displayed then this will hand the requester
a valid CA certificate.
This situation can be avoided by setting B<copy_extensions> to B<copy>
and including basicConstraints with CA:FALSE in the configuration file.
Then if the request contains a basicConstraints extension it will be
ignored.
It is advisable to also include values for other extensions such
as B<keyUsage> to prevent a request supplying its own values.
Additional restrictions can be placed on the CA certificate itself.
For example if the CA certificate has:
basicConstraints = CA:TRUE, pathlen:0
then even if a certificate is issued with CA:TRUE it will not be valid.
=head1 HISTORY
Since OpenSSL 1.1.1, the program follows RFC5280. Specifically,
certificate validity period (specified by any of B<-startdate>,
B<-enddate> and B<-days>) will be encoded as UTCTime if the dates are
earlier than year 2049 (included), and as GeneralizedTime if the dates
are in year 2050 or later.
=head1 SEE ALSO
L<req(1)>, L<spkac(1)>, L<x509(1)>, L<CA.pl(1)>,
L<config(5)>, L<x509v3_config(5)>
=head1 COPYRIGHT
Copyright 2000-2018 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/enc.pod b/doc/man1/enc.pod
index 01cca4ea93f1..2136a9497849 100644
--- a/doc/man1/enc.pod
+++ b/doc/man1/enc.pod
@@ -1,407 +1,431 @@
=pod
=head1 NAME
openssl-enc,
enc - symmetric cipher routines
=head1 SYNOPSIS
B<openssl enc -I<cipher>>
[B<-help>]
[B<-ciphers>]
[B<-in filename>]
[B<-out filename>]
[B<-pass arg>]
[B<-e>]
[B<-d>]
[B<-a>]
[B<-base64>]
[B<-A>]
[B<-k password>]
[B<-kfile filename>]
[B<-K key>]
[B<-iv IV>]
[B<-S salt>]
[B<-salt>]
[B<-nosalt>]
[B<-z>]
[B<-md digest>]
[B<-iter count>]
[B<-pbkdf2>]
[B<-p>]
[B<-P>]
[B<-bufsize number>]
[B<-nopad>]
[B<-debug>]
[B<-none>]
[B<-rand file...>]
[B<-writerand file>]
[B<-engine id>]
B<openssl> I<[cipher]> [B<...>]
=head1 DESCRIPTION
The symmetric cipher commands allow data to be encrypted or decrypted
using various block and stream ciphers using keys based on passwords
or explicitly provided. Base64 encoding or decoding can also be performed
either by itself or in addition to the encryption or decryption.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-ciphers>
List all supported ciphers.
=item B<-in filename>
The input filename, standard input by default.
=item B<-out filename>
The output filename, standard output by default.
=item B<-pass arg>
The password source. For more information about the format of B<arg>
see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)>.
=item B<-e>
Encrypt the input data: this is the default.
=item B<-d>
Decrypt the input data.
=item B<-a>
Base64 process the data. This means that if encryption is taking place
the data is base64 encoded after encryption. If decryption is set then
the input data is base64 decoded before being decrypted.
=item B<-base64>
Same as B<-a>
=item B<-A>
If the B<-a> option is set then base64 process the data on one line.
=item B<-k password>
The password to derive the key from. This is for compatibility with previous
versions of OpenSSL. Superseded by the B<-pass> argument.
=item B<-kfile filename>
Read the password to derive the key from the first line of B<filename>.
This is for compatibility with previous versions of OpenSSL. Superseded by
the B<-pass> argument.
=item B<-md digest>
Use the specified digest to create the key from the passphrase.
The default algorithm is sha-256.
=item B<-iter count>
Use a given number of iterations on the password in deriving the encryption key.
High values increase the time required to brute-force the resulting file.
This option enables the use of PBKDF2 algorithm to derive the key.
=item B<-pbkdf2>
Use PBKDF2 algorithm with default iteration count unless otherwise specified.
=item B<-nosalt>
Don't use a salt in the key derivation routines. This option B<SHOULD NOT> be
used except for test purposes or compatibility with ancient versions of
OpenSSL.
=item B<-salt>
Use salt (randomly generated or provide with B<-S> option) when
encrypting, this is the default.
=item B<-S salt>
The actual salt to use: this must be represented as a string of hex digits.
=item B<-K key>
The actual key to use: this must be represented as a string comprised only
of hex digits. If only the key is specified, the IV must additionally specified
using the B<-iv> option. When both a key and a password are specified, the
key given with the B<-K> option will be used and the IV generated from the
password will be taken. It does not make much sense to specify both key
and password.
=item B<-iv IV>
The actual IV to use: this must be represented as a string comprised only
of hex digits. When only the key is specified using the B<-K> option, the
IV must explicitly be defined. When a password is being specified using
one of the other options, the IV is generated from this password.
=item B<-p>
Print out the key and IV used.
=item B<-P>
Print out the key and IV used then immediately exit: don't do any encryption
or decryption.
=item B<-bufsize number>
Set the buffer size for I/O.
=item B<-nopad>
Disable standard block padding.
=item B<-debug>
Debug the BIOs used for I/O.
=item B<-z>
Compress or decompress clear text using zlib before encryption or after
decryption. This option exists only if OpenSSL with compiled with zlib
or zlib-dynamic option.
=item B<-none>
Use NULL cipher (no encryption or decryption of input).
=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.
=back
=head1 NOTES
The program can be called either as B<openssl cipher> or
B<openssl enc -cipher>. The first form doesn't work with
engine-provided ciphers, because this form is processed before the
configuration file is read and any ENGINEs loaded.
Use the B<list> command to get a list of supported ciphers.
Engines which provide entirely new encryption algorithms (such as the ccgost
engine which provides gost89 algorithm) should be configured in the
configuration file. Engines specified on the command line using -engine
options can only be used for hardware-assisted implementations of
ciphers which are supported by the OpenSSL core or another engine specified
in the configuration file.
When the enc command lists supported ciphers, ciphers provided by engines,
specified in the configuration files are listed too.
A password will be prompted for to derive the key and IV if necessary.
The B<-salt> option should B<ALWAYS> be used if the key is being derived
from a password unless you want compatibility with previous versions of
OpenSSL.
Without the B<-salt> option it is possible to perform efficient dictionary
attacks on the password and to attack stream cipher encrypted data. The reason
for this is that without the salt the same password always generates the same
encryption key. When the salt is being used the first eight bytes of the
encrypted data are reserved for the salt: it is generated at random when
encrypting a file and read from the encrypted file when it is decrypted.
Some of the ciphers do not have large keys and others have security
implications if not used correctly. A beginner is advised to just use
a strong block cipher, such as AES, in CBC mode.
All the block ciphers normally use PKCS#5 padding, also known as standard
block padding. This allows a rudimentary integrity or password check to
be performed. However since the chance of random data passing the test
is better than 1 in 256 it isn't a very good test.
If padding is disabled then the input data must be a multiple of the cipher
block length.
All RC2 ciphers have the same key and effective key length.
Blowfish and RC5 algorithms use a 128 bit key.
=head1 SUPPORTED CIPHERS
Note that some of these ciphers can be disabled at compile time
and some are available only if an appropriate engine is configured
in the configuration file. The output of the B<enc> command run with
the B<-ciphers> option (that is B<openssl enc -ciphers>) produces a
list of ciphers, supported by your version of OpenSSL, including
ones provided by configured engines.
The B<enc> program does not support authenticated encryption modes
like CCM and GCM, and will not support such modes in the future.
The B<enc> interface by necessity must begin streaming output (e.g.,
-to standard output when B<-out> is not used before the authentication
+to standard output when B<-out> is not used) before the authentication
tag could be validated, leading to the usage of B<enc> in pipelines
that begin processing untrusted data and are not capable of rolling
back upon authentication failure. The AEAD modes currently in common
use also suffer from catastrophic failure of confidentiality and/or
integrity upon reuse of key/iv/nonce, and since B<enc> places the
entire burden of key/iv/nonce management upon the user, the risk of
exposing AEAD modes is too great to allow. These key/iv/nonce
management issues also affect other modes currently exposed in B<enc>,
but the failure modes are less extreme in these cases, and the
functionality cannot be removed with a stable release branch.
For bulk encryption of data, whether using authenticated encryption
modes or other modes, L<cms(1)> is recommended, as it provides a
standard data format and performs the needed key/iv/nonce management.
base64 Base 64
bf-cbc Blowfish in CBC mode
bf Alias for bf-cbc
+ blowfish Alias for bf-cbc
bf-cfb Blowfish in CFB mode
bf-ecb Blowfish in ECB mode
bf-ofb Blowfish in OFB mode
cast-cbc CAST in CBC mode
cast Alias for cast-cbc
cast5-cbc CAST5 in CBC mode
cast5-cfb CAST5 in CFB mode
cast5-ecb CAST5 in ECB mode
cast5-ofb CAST5 in OFB mode
+ chacha20 ChaCha20 algorithm
+
des-cbc DES in CBC mode
des Alias for des-cbc
des-cfb DES in CFB mode
des-ofb DES in OFB mode
des-ecb DES in ECB mode
des-ede-cbc Two key triple DES EDE in CBC mode
des-ede Two key triple DES EDE in ECB mode
des-ede-cfb Two key triple DES EDE in CFB mode
des-ede-ofb Two key triple DES EDE in OFB mode
des-ede3-cbc Three key triple DES EDE in CBC mode
des-ede3 Three key triple DES EDE in ECB mode
des3 Alias for des-ede3-cbc
des-ede3-cfb Three key triple DES EDE CFB mode
des-ede3-ofb Three key triple DES EDE in OFB mode
desx DESX algorithm.
gost89 GOST 28147-89 in CFB mode (provided by ccgost engine)
gost89-cnt `GOST 28147-89 in CNT mode (provided by ccgost engine)
idea-cbc IDEA algorithm in CBC mode
idea same as idea-cbc
idea-cfb IDEA in CFB mode
idea-ecb IDEA in ECB mode
idea-ofb IDEA in OFB mode
rc2-cbc 128 bit RC2 in CBC mode
rc2 Alias for rc2-cbc
rc2-cfb 128 bit RC2 in CFB mode
rc2-ecb 128 bit RC2 in ECB mode
rc2-ofb 128 bit RC2 in OFB mode
rc2-64-cbc 64 bit RC2 in CBC mode
rc2-40-cbc 40 bit RC2 in CBC mode
rc4 128 bit RC4
rc4-64 64 bit RC4
rc4-40 40 bit RC4
rc5-cbc RC5 cipher in CBC mode
rc5 Alias for rc5-cbc
rc5-cfb RC5 cipher in CFB mode
rc5-ecb RC5 cipher in ECB mode
rc5-ofb RC5 cipher in OFB mode
+ seed-cbc SEED cipher in CBC mode
+ seed Alias for seed-cbc
+ seed-cfb SEED cipher in CFB mode
+ seed-ecb SEED cipher in ECB mode
+ seed-ofb SEED cipher in OFB mode
+
+ sm4-cbc SM4 cipher in CBC mode
+ sm4 Alias for sm4-cbc
+ sm4-cfb SM4 cipher in CFB mode
+ sm4-ctr SM4 cipher in CTR mode
+ sm4-ecb SM4 cipher in ECB mode
+ sm4-ofb SM4 cipher in OFB mode
+
aes-[128|192|256]-cbc 128/192/256 bit AES in CBC mode
aes[128|192|256] Alias for aes-[128|192|256]-cbc
aes-[128|192|256]-cfb 128/192/256 bit AES in 128 bit CFB mode
aes-[128|192|256]-cfb1 128/192/256 bit AES in 1 bit CFB mode
aes-[128|192|256]-cfb8 128/192/256 bit AES in 8 bit CFB mode
aes-[128|192|256]-ctr 128/192/256 bit AES in CTR mode
aes-[128|192|256]-ecb 128/192/256 bit AES in ECB mode
aes-[128|192|256]-ofb 128/192/256 bit AES in OFB mode
+ aria-[128|192|256]-cbc 128/192/256 bit ARIA in CBC mode
+ aria[128|192|256] Alias for aria-[128|192|256]-cbc
+ aria-[128|192|256]-cfb 128/192/256 bit ARIA in 128 bit CFB mode
+ aria-[128|192|256]-cfb1 128/192/256 bit ARIA in 1 bit CFB mode
+ aria-[128|192|256]-cfb8 128/192/256 bit ARIA in 8 bit CFB mode
+ aria-[128|192|256]-ctr 128/192/256 bit ARIA in CTR mode
+ aria-[128|192|256]-ecb 128/192/256 bit ARIA in ECB mode
+ aria-[128|192|256]-ofb 128/192/256 bit ARIA in OFB mode
+
camellia-[128|192|256]-cbc 128/192/256 bit Camellia in CBC mode
camellia[128|192|256] Alias for camellia-[128|192|256]-cbc
camellia-[128|192|256]-cfb 128/192/256 bit Camellia in 128 bit CFB mode
camellia-[128|192|256]-cfb1 128/192/256 bit Camellia in 1 bit CFB mode
camellia-[128|192|256]-cfb8 128/192/256 bit Camellia in 8 bit CFB mode
camellia-[128|192|256]-ctr 128/192/256 bit Camellia in CTR mode
camellia-[128|192|256]-ecb 128/192/256 bit Camellia in ECB mode
camellia-[128|192|256]-ofb 128/192/256 bit Camellia in OFB mode
=head1 EXAMPLES
Just base64 encode a binary file:
openssl base64 -in file.bin -out file.b64
Decode the same file
openssl base64 -d -in file.b64 -out file.bin
-Encrypt a file using triple DES in CBC mode using a prompted password:
+Encrypt a file using AES-128 using a prompted password
+and PBKDF2 key derivation:
- openssl des3 -salt -in file.txt -out file.des3
+ openssl enc -aes128 -pbkdf2 -in file.txt -out file.aes128
Decrypt a file using a supplied password:
- openssl des3 -d -salt -in file.des3 -out file.txt -k mypassword
+ openssl enc -aes128 -pbkdf2 -d -in file.aes128 -out file.txt \
+ -pass pass:<password>
Encrypt a file then base64 encode it (so it can be sent via mail for example)
-using Blowfish in CBC mode:
-
- openssl bf -a -salt -in file.txt -out file.bf
-
-Base64 decode a file then decrypt it:
+using AES-256 in CTR mode and PBKDF2 key derivation:
- openssl bf -d -salt -a -in file.bf -out file.txt
+ openssl enc -aes-256-ctr -pbkdf2 -a -in file.txt -out file.aes256
-Decrypt some data using a supplied 40 bit RC4 key:
+Base64 decode a file then decrypt it using a password supplied in a file:
- openssl rc4-40 -in file.rc4 -out file.txt -K 0102030405
+ openssl enc -aes-256-ctr -pbkdf2 -d -a -in file.aes256 -out file.txt \
+ -pass file:<passfile>
=head1 BUGS
The B<-A> option when used with large files doesn't work properly.
The B<enc> program only supports a fixed number of algorithms with
certain parameters. So if, for example, you want to use RC2 with a
76 bit key or RC4 with an 84 bit key you can't use this program.
=head1 HISTORY
The default digest was changed from MD5 to SHA256 in Openssl 1.1.0.
=head1 COPYRIGHT
Copyright 2000-2018 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/openssl.pod b/doc/man1/openssl.pod
index c656a34ec032..a39cf963d988 100644
--- a/doc/man1/openssl.pod
+++ b/doc/man1/openssl.pod
@@ -1,511 +1,568 @@
=pod
=head1 NAME
openssl - OpenSSL command line tool
=head1 SYNOPSIS
B<openssl>
I<command>
[ I<command_opts> ]
[ I<command_args> ]
B<openssl> B<list> [ B<standard-commands> | B<digest-commands> | B<cipher-commands> | B<cipher-algorithms> | B<digest-algorithms> | B<public-key-algorithms>]
B<openssl> B<no->I<XXX> [ I<arbitrary options> ]
=head1 DESCRIPTION
OpenSSL is a cryptography toolkit implementing the Secure Sockets Layer (SSL
v2/v3) and Transport Layer Security (TLS v1) network protocols and related
cryptography standards required by them.
The B<openssl> program is a command line tool for using the various
cryptography functions of OpenSSL's B<crypto> library from the shell.
It can be used for
o Creation and management of private keys, public keys and parameters
o Public key cryptographic operations
o Creation of X.509 certificates, CSRs and CRLs
o Calculation of Message Digests
o Encryption and Decryption with Ciphers
o SSL/TLS Client and Server Tests
o Handling of S/MIME signed or encrypted mail
o Time Stamp requests, generation and verification
=head1 COMMAND SUMMARY
The B<openssl> program provides a rich variety of commands (I<command> in the
SYNOPSIS above), each of which often has a wealth of options and arguments
(I<command_opts> and I<command_args> in the SYNOPSIS).
+Detailed documentation and use cases for most standard subcommands are available
+(e.g., L<x509(1)> or L<openssl-x509(1)>).
+
Many commands use an external configuration file for some or all of their
arguments and have a B<-config> option to specify that file.
The environment variable B<OPENSSL_CONF> can be used to specify
the location of the file.
If the environment variable is not specified, then the file is named
B<openssl.cnf> in the default certificate storage area, whose value
depends on the configuration flags specified when the OpenSSL
was built.
The list parameters B<standard-commands>, B<digest-commands>,
and B<cipher-commands> output a list (one entry per line) of the names
of all standard commands, message digest commands, or cipher commands,
respectively, that are available in the present B<openssl> utility.
The list parameters B<cipher-algorithms> and
B<digest-algorithms> list all cipher and message digest names, one entry per line. Aliases are listed as:
from => to
The list parameter B<public-key-algorithms> lists all supported public
key algorithms.
The command B<no->I<XXX> tests whether a command of the
specified name is available. If no command named I<XXX> exists, it
returns 0 (success) and prints B<no->I<XXX>; otherwise it returns 1
and prints I<XXX>. In both cases, the output goes to B<stdout> and
nothing is printed to B<stderr>. Additional command line arguments
are always ignored. Since for each cipher there is a command of the
same name, this provides an easy way for shell scripts to test for the
availability of ciphers in the B<openssl> program. (B<no->I<XXX> is
not able to detect pseudo-commands such as B<quit>,
B<list>, or B<no->I<XXX> itself.)
=head2 Standard Commands
=over 4
=item B<asn1parse>
Parse an ASN.1 sequence.
=item B<ca>
Certificate Authority (CA) Management.
=item B<ciphers>
Cipher Suite Description Determination.
=item B<cms>
CMS (Cryptographic Message Syntax) utility.
=item B<crl>
Certificate Revocation List (CRL) Management.
=item B<crl2pkcs7>
CRL to PKCS#7 Conversion.
=item B<dgst>
Message Digest Calculation.
=item B<dh>
Diffie-Hellman Parameter Management.
Obsoleted by L<dhparam(1)>.
=item B<dhparam>
Generation and Management of Diffie-Hellman Parameters. Superseded by
L<genpkey(1)> and L<pkeyparam(1)>.
=item B<dsa>
DSA Data Management.
=item B<dsaparam>
DSA Parameter Generation and Management. Superseded by
L<genpkey(1)> and L<pkeyparam(1)>.
=item B<ec>
EC (Elliptic curve) key processing.
=item B<ecparam>
EC parameter manipulation and generation.
=item B<enc>
Encoding with Ciphers.
=item B<engine>
Engine (loadable module) information and manipulation.
=item B<errstr>
Error Number to Error String Conversion.
=item B<gendh>
Generation of Diffie-Hellman Parameters.
Obsoleted by L<dhparam(1)>.
=item B<gendsa>
Generation of DSA Private Key from Parameters. Superseded by
L<genpkey(1)> and L<pkey(1)>.
=item B<genpkey>
Generation of Private Key or Parameters.
=item B<genrsa>
Generation of RSA Private Key. Superseded by L<genpkey(1)>.
=item B<nseq>
Create or examine a Netscape certificate sequence.
=item B<ocsp>
Online Certificate Status Protocol utility.
=item B<passwd>
Generation of hashed passwords.
=item B<pkcs12>
PKCS#12 Data Management.
=item B<pkcs7>
PKCS#7 Data Management.
=item B<pkcs8>
PKCS#8 format private key conversion tool.
=item B<pkey>
Public and private key management.
=item B<pkeyparam>
Public key algorithm parameter management.
=item B<pkeyutl>
Public key algorithm cryptographic operation utility.
=item B<prime>
Compute prime numbers.
=item B<rand>
Generate pseudo-random bytes.
=item B<rehash>
Create symbolic links to certificate and CRL files named by the hash values.
=item B<req>
PKCS#10 X.509 Certificate Signing Request (CSR) Management.
=item B<rsa>
RSA key management.
=item B<rsautl>
RSA utility for signing, verification, encryption, and decryption. Superseded
by L<pkeyutl(1)>.
=item B<s_client>
This implements a generic SSL/TLS client which can establish a transparent
connection to a remote server speaking SSL/TLS. It's intended for testing
purposes only and provides only rudimentary interface functionality but
internally uses mostly all functionality of the OpenSSL B<ssl> library.
=item B<s_server>
This implements a generic SSL/TLS server which accepts connections from remote
clients speaking SSL/TLS. It's intended for testing purposes only and provides
only rudimentary interface functionality but internally uses mostly all
functionality of the OpenSSL B<ssl> library. It provides both an own command
line oriented protocol for testing SSL functions and a simple HTTP response
facility to emulate an SSL/TLS-aware webserver.
=item B<s_time>
SSL Connection Timer.
=item B<sess_id>
SSL Session Data Management.
=item B<smime>
S/MIME mail processing.
=item B<speed>
Algorithm Speed Measurement.
=item B<spkac>
SPKAC printing and generating utility.
=item B<srp>
Maintain SRP password file.
=item B<storeutl>
Utility to list and display certificates, keys, CRLs, etc.
=item B<ts>
Time Stamping Authority tool (client/server).
=item B<verify>
X.509 Certificate Verification.
=item B<version>
OpenSSL Version Information.
=item B<x509>
X.509 Certificate Data Management.
=back
=head2 Message Digest Commands
=over 4
=item B<blake2b512>
BLAKE2b-512 Digest
=item B<blake2s256>
BLAKE2s-256 Digest
=item B<md2>
MD2 Digest
=item B<md4>
MD4 Digest
=item B<md5>
MD5 Digest
=item B<mdc2>
MDC2 Digest
=item B<rmd160>
RMD-160 Digest
=item B<sha1>
SHA-1 Digest
=item B<sha224>
SHA-2 224 Digest
=item B<sha256>
SHA-2 256 Digest
=item B<sha384>
SHA-2 384 Digest
=item B<sha512>
SHA-2 512 Digest
=item B<sha3-224>
SHA-3 224 Digest
=item B<sha3-256>
SHA-3 256 Digest
=item B<sha3-384>
SHA-3 384 Digest
=item B<sha3-512>
SHA-3 512 Digest
=item B<shake128>
SHA-3 SHAKE128 Digest
=item B<shake256>
SHA-3 SHAKE256 Digest
=item B<sm3>
SM3 Digest
=back
=head2 Encoding and Cipher Commands
+The following aliases provide convenient access to the most used encodings
+and ciphers.
+
+Depending on how OpenSSL was configured and built, not all ciphers listed
+here may be present. See L<enc(1)> for more information and command usage.
+
=over 4
+=item B<aes128>, B<aes-128-cbc>, B<aes-128-cfb>, B<aes-128-ctr>, B<aes-128-ecb>, B<aes-128-ofb>
+
+AES-128 Cipher
+
+=item B<aes192>, B<aes-192-cbc>, B<aes-192-cfb>, B<aes-192-ctr>, B<aes-192-ecb>, B<aes-192-ofb>
+
+AES-192 Cipher
+
+=item B<aes256>, B<aes-256-cbc>, B<aes-256-cfb>, B<aes-256-ctr>, B<aes-256-ecb>, B<aes-256-ofb>
+
+AES-256 Cipher
+
+=item B<aria128>, B<aria-128-cbc>, B<aria-128-cfb>, B<aria-128-ctr>, B<aria-128-ecb>, B<aria-128-ofb>
+
+Aria-128 Cipher
+
+=item B<aria192>, B<aria-192-cbc>, B<aria-192-cfb>, B<aria-192-ctr>, B<aria-192-ecb>, B<aria-192-ofb>
+
+Aria-192 Cipher
+
+=item B<aria256>, B<aria-256-cbc>, B<aria-256-cfb>, B<aria-256-ctr>, B<aria-256-ecb>, B<aria-256-ofb>
+
+Aria-256 Cipher
+
=item B<base64>
Base64 Encoding
=item B<bf>, B<bf-cbc>, B<bf-cfb>, B<bf-ecb>, B<bf-ofb>
Blowfish Cipher
+=item B<camellia128>, B<camellia-128-cbc>, B<camellia-128-cfb>, B<camellia-128-ctr>, B<camellia-128-ecb>, B<camellia-128-ofb>
+
+Camellia-128 Cipher
+
+=item B<camellia192>, B<camellia-192-cbc>, B<camellia-192-cfb>, B<camellia-192-ctr>, B<camellia-192-ecb>, B<camellia-192-ofb>
+
+Camellia-192 Cipher
+
+=item B<camellia256>, B<camellia-256-cbc>, B<camellia-256-cfb>, B<camellia-256-ctr>, B<camellia-256-ecb>, B<camellia-256-ofb>
+
+Camellia-256 Cipher
+
=item B<cast>, B<cast-cbc>
CAST Cipher
=item B<cast5-cbc>, B<cast5-cfb>, B<cast5-ecb>, B<cast5-ofb>
CAST5 Cipher
+=item B<chacha20>
+
+Chacha20 Cipher
+
=item B<des>, B<des-cbc>, B<des-cfb>, B<des-ecb>, B<des-ede>, B<des-ede-cbc>, B<des-ede-cfb>, B<des-ede-ofb>, B<des-ofb>
DES Cipher
=item B<des3>, B<desx>, B<des-ede3>, B<des-ede3-cbc>, B<des-ede3-cfb>, B<des-ede3-ofb>
Triple-DES Cipher
=item B<idea>, B<idea-cbc>, B<idea-cfb>, B<idea-ecb>, B<idea-ofb>
IDEA Cipher
=item B<rc2>, B<rc2-cbc>, B<rc2-cfb>, B<rc2-ecb>, B<rc2-ofb>
RC2 Cipher
=item B<rc4>
RC4 Cipher
=item B<rc5>, B<rc5-cbc>, B<rc5-cfb>, B<rc5-ecb>, B<rc5-ofb>
RC5 Cipher
+=item B<seed>, B<seed-cbc>, B<seed-cfb>, B<seed-ecb>, B<seed-ofb>
+
+SEED Cipher
+
+=item B<sm4>, B<sm4-cbc>, B<sm4-cfb>, B<sm4-ctr>, B<sm4-ecb>, B<sm4-ofb>
+
+SM4 Cipher
+
=back
=head1 OPTIONS
Details of which options are available depend on the specific command.
This section describes some common options with common behavior.
=head2 Common Options
=over 4
=item B<-help>
Provides a terse summary of all options.
=back
=head2 Pass Phrase Options
Several commands accept password arguments, typically using B<-passin>
and B<-passout> for input and output passwords respectively. These allow
the password to be obtained from a variety of sources. Both of these
options take a single argument whose format is described below. If no
password argument is given and a password is required then the user is
prompted to enter one: this will typically be read from the current
terminal with echoing turned off.
Note that character encoding may be relevant, please see
L<passphrase-encoding(7)>.
=over 4
=item B<pass:password>
The actual password is B<password>. Since the password is visible
to utilities (like 'ps' under Unix) this form should only be used
where security is not important.
=item B<env:var>
Obtain the password from the environment variable B<var>. Since
the environment of other processes is visible on certain platforms
(e.g. ps under certain Unix OSes) this option should be used with caution.
=item B<file:pathname>
The first line of B<pathname> is the password. If the same B<pathname>
argument is supplied to B<-passin> and B<-passout> arguments then the first
line will be used for the input password and the next line for the output
password. B<pathname> need not refer to a regular file: it could for example
refer to a device or named pipe.
=item B<fd:number>
Read the password from the file descriptor B<number>. This can be used to
send the data via a pipe for example.
=item B<stdin>
Read the password from standard input.
=back
=head1 SEE ALSO
L<asn1parse(1)>, L<ca(1)>, L<ciphers(1)>, L<cms(1)>, L<config(5)>,
L<crl(1)>, L<crl2pkcs7(1)>, L<dgst(1)>,
L<dhparam(1)>, L<dsa(1)>, L<dsaparam(1)>,
L<ec(1)>, L<ecparam(1)>,
L<enc(1)>, L<engine(1)>, L<errstr(1)>, L<gendsa(1)>, L<genpkey(1)>,
L<genrsa(1)>, L<nseq(1)>, L<ocsp(1)>,
L<passwd(1)>,
L<pkcs12(1)>, L<pkcs7(1)>, L<pkcs8(1)>,
L<pkey(1)>, L<pkeyparam(1)>, L<pkeyutl(1)>, L<prime(1)>,
L<rand(1)>, L<rehash(1)>, L<req(1)>, L<rsa(1)>,
L<rsautl(1)>, L<s_client(1)>,
L<s_server(1)>, L<s_time(1)>, L<sess_id(1)>,
L<smime(1)>, L<speed(1)>, L<spkac(1)>, L<srp(1)>, L<storeutl(1)>,
L<ts(1)>,
L<verify(1)>, L<version(1)>, L<x509(1)>,
L<crypto(7)>, L<ssl(7)>, L<x509v3_config(5)>
=head1 HISTORY
The B<list->I<XXX>B<-algorithms> pseudo-commands were added in OpenSSL 1.0.0;
For notes on the availability of other commands, see their individual
manual pages.
=head1 COPYRIGHT
Copyright 2000-2018 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/req.pod b/doc/man1/req.pod
index 113cd9b6c985..c76d63d6fd81 100644
--- a/doc/man1/req.pod
+++ b/doc/man1/req.pod
@@ -1,697 +1,699 @@
=pod
=head1 NAME
openssl-req,
req - PKCS#10 certificate request and certificate generating utility
=head1 SYNOPSIS
B<openssl> B<req>
[B<-help>]
[B<-inform PEM|DER>]
[B<-outform PEM|DER>]
[B<-in filename>]
[B<-passin arg>]
[B<-out filename>]
[B<-passout arg>]
[B<-text>]
[B<-pubkey>]
[B<-noout>]
[B<-verify>]
[B<-modulus>]
[B<-new>]
[B<-rand file...>]
[B<-writerand file>]
[B<-newkey rsa:bits>]
[B<-newkey alg:file>]
[B<-nodes>]
[B<-key filename>]
[B<-keyform PEM|DER>]
[B<-keyout filename>]
[B<-keygen_engine id>]
[B<-I<digest>>]
[B<-config filename>]
[B<-multivalue-rdn>]
[B<-x509>]
[B<-days n>]
[B<-set_serial n>]
[B<-newhdr>]
[B<-addext ext>]
[B<-extensions section>]
[B<-reqexts section>]
[B<-precert>]
[B<-utf8>]
[B<-nameopt>]
[B<-reqopt>]
[B<-subject>]
[B<-subj arg>]
[B<-batch>]
[B<-verbose>]
[B<-engine id>]
=head1 DESCRIPTION
The B<req> command primarily creates and processes certificate requests
in PKCS#10 format. It can additionally create self signed certificates
for use as root CAs for example.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-inform DER|PEM>
This specifies the input format. The B<DER> option uses an ASN1 DER encoded
form compatible with the PKCS#10. The B<PEM> form is the default format: it
consists of the B<DER> format base64 encoded with additional header and
footer lines.
=item B<-outform DER|PEM>
This specifies the output format, the options have the same meaning and default
as the B<-inform> option.
=item B<-in filename>
This specifies the input filename to read a request from or standard input
if this option is not specified. A request is only read if the creation
options (B<-new> and B<-newkey>) are not specified.
=item B<-passin arg>
The input 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<-out filename>
This specifies the output filename to write to or standard output by
default.
=item B<-passout 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<-text>
Prints out the certificate request in text form.
=item B<-subject>
Prints out the request subject (or certificate subject if B<-x509> is
specified)
=item B<-pubkey>
Outputs the public key.
=item B<-noout>
This option prevents output of the encoded version of the request.
=item B<-modulus>
This option prints out the value of the modulus of the public key
contained in the request.
=item B<-verify>
Verifies the signature on the request.
=item B<-new>
This option generates a new certificate request. It will prompt
the user for the relevant field values. The actual fields
prompted for and their maximum and minimum sizes are specified
in the configuration file and any requested extensions.
If the B<-key> option is not used it will generate a new RSA private
key using information specified in the configuration file.
=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<-newkey arg>
This option creates a new certificate request and a new private
key. The argument takes one of several forms. B<rsa:nbits>, where
B<nbits> is the number of bits, generates an RSA key B<nbits>
in size. If B<nbits> is omitted, i.e. B<-newkey rsa> specified,
the default key size, specified in the configuration file is used.
All other algorithms support the B<-newkey alg:file> form, where file may be
an algorithm parameter file, created by the B<genpkey -genparam> command
or and X.509 certificate for a key with appropriate algorithm.
B<param:file> generates a key using the parameter file or certificate B<file>,
the algorithm is determined by the parameters. B<algname:file> use algorithm
B<algname> and parameter file B<file>: the two algorithms must match or an
error occurs. B<algname> just uses algorithm B<algname>, and parameters,
if necessary should be specified via B<-pkeyopt> parameter.
B<dsa:filename> generates a DSA key using the parameters
in the file B<filename>. B<ec:filename> generates EC key (usable both with
ECDSA or ECDH algorithms), B<gost2001:filename> generates GOST R
34.10-2001 key (requires B<ccgost> engine configured in the configuration
file). If just B<gost2001> is specified a parameter set should be
specified by B<-pkeyopt paramset:X>
=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 B<KEY GENERATION OPTIONS> in the B<genpkey> manual page
for more details.
=item B<-key filename>
This specifies the file to read the private key from. It also
accepts PKCS#8 format private keys for PEM format files.
=item B<-keyform PEM|DER>
The format of the private key file specified in the B<-key>
argument. PEM is the default.
=item B<-keyout filename>
This gives the filename to write the newly created private key to.
If this option is not specified then the filename present in the
configuration file is used.
=item B<-nodes>
If this option is specified then if a private key is created it
will not be encrypted.
=item B<-I<digest>>
This specifies the message digest to sign the request.
Any digest supported by the OpenSSL B<dgst> command can be used.
This overrides the digest algorithm specified in
the configuration file.
Some public key algorithms may override this choice. For instance, DSA
signatures always use SHA1, GOST R 34.10 signatures always use
GOST R 34.11-94 (B<-md_gost94>), Ed25519 and Ed448 never use any digest.
=item B<-config filename>
This allows an alternative configuration file to be specified.
Optional; for a description of the default value,
see L<openssl(1)/COMMAND SUMMARY>.
=item B<-subj arg>
Sets subject name for new request or supersedes the subject name
when processing a request.
-The arg must be formatted as I</type0=value0/type1=value1/type2=...>,
-characters may be escaped by \ (backslash), no spaces are skipped.
+The arg must be formatted as I</type0=value0/type1=value1/type2=...>.
+Keyword characters may be escaped by \ (backslash), and whitespace is retained.
+Empty values are permitted, but the corresponding type will not be included
+in the request.
=item B<-multivalue-rdn>
This option causes the -subj argument to be interpreted with full
support for multivalued RDNs. Example:
I</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
If -multi-rdn is not used then the UID value is I<123456+CN=John Doe>.
=item B<-x509>
This option outputs a self signed certificate instead of a certificate
request. This is typically used to generate a test certificate or
a self signed root CA. The extensions added to the certificate
(if any) are specified in the configuration file. Unless specified
using the B<set_serial> option, a large random number will be used for
the serial number.
If existing request is specified with the B<-in> option, it is converted
to the self signed certificate otherwise new request is created.
=item B<-days n>
When the B<-x509> option is being used this specifies the number of
days to certify the certificate for, otherwise it is ignored. B<n> should
be a positive integer. The default is 30 days.
=item B<-set_serial n>
Serial number to use when outputting a self signed certificate. This
may be specified as a decimal value or a hex value if preceded by B<0x>.
=item B<-addext ext>
Add a specific extension to the certificate (if the B<-x509> option is
present) or certificate request. The argument must have the form of
a key=value pair as it would appear in a config file.
This option can be given multiple times.
=item B<-extensions section>
=item B<-reqexts section>
These options specify alternative sections to include certificate
extensions (if the B<-x509> option is present) or certificate
request extensions. This allows several different sections to
be used in the same configuration file to specify requests for
a variety of purposes.
=item B<-precert>
A poison extension will be added to the certificate, making it a
"pre-certificate" (see RFC6962). This can be submitted to Certificate
Transparency logs in order to obtain signed certificate timestamps (SCTs).
These SCTs can then be embedded into the pre-certificate as an extension, before
removing the poison and signing the certificate.
This implies the B<-new> flag.
=item B<-utf8>
This option causes field values to be interpreted as UTF8 strings, by
default they are interpreted as ASCII. This means that the field
values, whether prompted from a terminal or obtained from a
configuration file, must be valid UTF8 strings.
=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<-reqopt>
Customise the output format used with B<-text>. The B<option> argument can be
a single option or multiple options separated by commas.
See discussion of the B<-certopt> parameter in the L<x509(1)>
command.
=item B<-newhdr>
Adds the word B<NEW> to the PEM file header and footer lines on the outputted
request. Some software (Netscape certificate server) and some CAs need this.
=item B<-batch>
Non-interactive mode.
=item B<-verbose>
Print extra details about the operations being performed.
=item B<-engine id>
Specifying an engine (by its unique B<id> string) will cause B<req>
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<-keygen_engine id>
Specifies an engine (by its unique B<id> string) which would be used
for key generation operations.
=back
=head1 CONFIGURATION FILE FORMAT
The configuration options are specified in the B<req> section of
the configuration file. As with all configuration files if no
value is specified in the specific section (i.e. B<req>) then
the initial unnamed or B<default> section is searched too.
The options available are described in detail below.
=over 4
=item B<input_password output_password>
The passwords for the input private key file (if present) and
the output private key file (if one will be created). The
command line options B<passin> and B<passout> override the
configuration file values.
=item B<default_bits>
Specifies the default key size in bits.
This option is used in conjunction with the B<-new> option to generate
a new key. It can be overridden by specifying an explicit key size in
the B<-newkey> option. The smallest accepted key size is 512 bits. If
no key size is specified then 2048 bits is used.
=item B<default_keyfile>
This is the default filename to write a private key to. If not
specified the key is written to standard output. This can be
overridden by the B<-keyout> option.
=item B<oid_file>
This specifies a file containing additional B<OBJECT IDENTIFIERS>.
Each line of the file should consist of the numerical form of the
object identifier followed by white space then the short name followed
by white space and finally the long name.
=item B<oid_section>
This specifies a section in the configuration file containing extra
object identifiers. Each line should consist of the short name of the
object identifier followed by B<=> and the numerical form. The short
and long names are the same when this option is used.
=item B<RANDFILE>
At startup the specified file is loaded into the random number generator,
and at exit 256 bytes will be written to it.
It is used for private key generation.
=item B<encrypt_key>
If this is set to B<no> then if a private key is generated it is
B<not> encrypted. This is equivalent to the B<-nodes> command line
option. For compatibility B<encrypt_rsa_key> is an equivalent option.
=item B<default_md>
This option specifies the digest algorithm to use. Any digest supported by the
OpenSSL B<dgst> command can be used. This option can be overridden on the
command line. Certain signing algorithms (i.e. Ed25519 and Ed448) will ignore
any digest that has been set.
=item B<string_mask>
This option masks out the use of certain string types in certain
fields. Most users will not need to change this option.
It can be set to several values B<default> which is also the default
option uses PrintableStrings, T61Strings and BMPStrings if the
B<pkix> value is used then only PrintableStrings and BMPStrings will
be used. This follows the PKIX recommendation in RFC2459. If the
B<utf8only> option is used then only UTF8Strings will be used: this
is the PKIX recommendation in RFC2459 after 2003. Finally the B<nombstr>
option just uses PrintableStrings and T61Strings: certain software has
problems with BMPStrings and UTF8Strings: in particular Netscape.
=item B<req_extensions>
This specifies the configuration file section containing a list of
extensions to add to the certificate request. It can be overridden
by the B<-reqexts> command line switch. See the
L<x509v3_config(5)> manual page for details of the
extension section format.
=item B<x509_extensions>
This specifies the configuration file section containing a list of
extensions to add to certificate generated when the B<-x509> switch
is used. It can be overridden by the B<-extensions> command line switch.
=item B<prompt>
If set to the value B<no> this disables prompting of certificate fields
and just takes values from the config file directly. It also changes the
expected format of the B<distinguished_name> and B<attributes> sections.
=item B<utf8>
If set to the value B<yes> then field values to be interpreted as UTF8
strings, by default they are interpreted as ASCII. This means that
the field values, whether prompted from a terminal or obtained from a
configuration file, must be valid UTF8 strings.
=item B<attributes>
This specifies the section containing any request attributes: its format
is the same as B<distinguished_name>. Typically these may contain the
challengePassword or unstructuredName types. They are currently ignored
by OpenSSL's request signing utilities but some CAs might want them.
=item B<distinguished_name>
This specifies the section containing the distinguished name fields to
prompt for when generating a certificate or certificate request. The format
is described in the next section.
=back
=head1 DISTINGUISHED NAME AND ATTRIBUTE SECTION FORMAT
There are two separate formats for the distinguished name and attribute
sections. If the B<prompt> option is set to B<no> then these sections
just consist of field names and values: for example,
CN=My Name
OU=My Organization
emailAddress=someone@somewhere.org
This allows external programs (e.g. GUI based) to generate a template file
with all the field names and values and just pass it to B<req>. An example
of this kind of configuration file is contained in the B<EXAMPLES> section.
Alternatively if the B<prompt> option is absent or not set to B<no> then the
file contains field prompting information. It consists of lines of the form:
fieldName="prompt"
fieldName_default="default field value"
fieldName_min= 2
fieldName_max= 4
"fieldName" is the field name being used, for example commonName (or CN).
The "prompt" string is used to ask the user to enter the relevant
details. If the user enters nothing then the default value is used if no
default value is present then the field is omitted. A field can
still be omitted if a default value is present if the user just
enters the '.' character.
The number of characters entered must be between the fieldName_min and
fieldName_max limits: there may be additional restrictions based
on the field being used (for example countryName can only ever be
two characters long and must fit in a PrintableString).
Some fields (such as organizationName) can be used more than once
in a DN. This presents a problem because configuration files will
not recognize the same name occurring twice. To avoid this problem
if the fieldName contains some characters followed by a full stop
they will be ignored. So for example a second organizationName can
be input by calling it "1.organizationName".
The actual permitted field names are any object identifier short or
long names. These are compiled into OpenSSL and include the usual
values such as commonName, countryName, localityName, organizationName,
organizationalUnitName, stateOrProvinceName. Additionally emailAddress
is include as well as name, surname, givenName initials and dnQualifier.
Additional object identifiers can be defined with the B<oid_file> or
B<oid_section> options in the configuration file. Any additional fields
will be treated as though they were a DirectoryString.
=head1 EXAMPLES
Examine and verify certificate request:
openssl req -in req.pem -text -verify -noout
Create a private key and then generate a certificate request from it:
openssl genrsa -out key.pem 2048
openssl req -new -key key.pem -out req.pem
The same but just using req:
openssl req -newkey rsa:2048 -keyout key.pem -out req.pem
Generate a self signed root certificate:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out req.pem
Example of a file pointed to by the B<oid_file> option:
1.2.3.4 shortName A longer Name
1.2.3.6 otherName Other longer Name
Example of a section pointed to by B<oid_section> making use of variable
expansion:
testoid1=1.2.3.5
testoid2=${testoid1}.6
Sample configuration file prompting for field values:
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
req_extensions = v3_ca
dirstring_type = nobmp
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
localityName = Locality Name (eg, city)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 40
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical, CA:true
Sample configuration containing all field values:
RANDFILE = $ENV::HOME/.rnd
[ req ]
default_bits = 2048
default_keyfile = keyfile.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
prompt = no
output_password = mypass
[ req_distinguished_name ]
C = GB
ST = Test State or Province
L = Test Locality
O = Organization Name
OU = Organizational Unit Name
CN = Common Name
emailAddress = test@email.address
[ req_attributes ]
challengePassword = A challenge password
Example of giving the most common attributes (subject and extensions)
on the command line:
openssl req -new -subj "/C=GB/CN=foo" \
-addext "subjectAltName = DNS:foo.co.uk" \
-addext "certificatePolicies = 1.2.3.4" \
-newkey rsa:2048 -keyout key.pem -out req.pem
=head1 NOTES
The header and footer lines in the B<PEM> format are normally:
-----BEGIN CERTIFICATE REQUEST-----
-----END CERTIFICATE REQUEST-----
some software (some versions of Netscape certificate server) instead needs:
-----BEGIN NEW CERTIFICATE REQUEST-----
-----END NEW CERTIFICATE REQUEST-----
which is produced with the B<-newhdr> option but is otherwise compatible.
Either form is accepted transparently on input.
The certificate requests generated by B<Xenroll> with MSIE have extensions
added. It includes the B<keyUsage> extension which determines the type of
key (signature only or general purpose) and any additional OIDs entered
by the script in an extendedKeyUsage extension.
=head1 DIAGNOSTICS
The following messages are frequently asked about:
Using configuration from /some/path/openssl.cnf
Unable to load config info
This is followed some time later by...
unable to find 'distinguished_name' in config
problems making Certificate Request
The first error message is the clue: it can't find the configuration
file! Certain operations (like examining a certificate request) don't
need a configuration file so its use isn't enforced. Generation of
certificates or requests however does need a configuration file. This
could be regarded as a bug.
Another puzzling message is this:
Attributes:
a0:00
this is displayed when no attributes are present and the request includes
the correct empty B<SET OF> structure (the DER encoding of which is 0xa0
0x00). If you just see:
Attributes:
then the B<SET OF> is missing and the encoding is technically invalid (but
it is tolerated). See the description of the command line option B<-asn1-kludge>
for more information.
=head1 BUGS
OpenSSL's handling of T61Strings (aka TeletexStrings) is broken: it effectively
treats them as ISO-8859-1 (Latin 1), Netscape and MSIE have similar behaviour.
This can cause problems if you need characters that aren't available in
PrintableStrings and you don't want to or can't use BMPStrings.
As a consequence of the T61String handling the only correct way to represent
accented characters in OpenSSL is to use a BMPString: unfortunately Netscape
currently chokes on these. If you have to use accented characters with Netscape
and MSIE then you currently need to use the invalid T61String form.
The current prompting is not very friendly. It doesn't allow you to confirm what
you've just entered. Other things like extensions in certificate requests are
statically defined in the configuration file. Some of these: like an email
address in subjectAltName should be input by the user.
=head1 SEE ALSO
L<x509(1)>, L<ca(1)>, L<genrsa(1)>,
L<gendsa(1)>, L<config(5)>,
L<x509v3_config(5)>
=head1 COPYRIGHT
Copyright 2000-2018 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/rsa.pod b/doc/man1/rsa.pod
index 14a8fb1e2989..37f64616c00f 100644
--- a/doc/man1/rsa.pod
+++ b/doc/man1/rsa.pod
@@ -1,220 +1,205 @@
=pod
=head1 NAME
openssl-rsa,
rsa - RSA key processing tool
=head1 SYNOPSIS
B<openssl> B<rsa>
[B<-help>]
-[B<-inform PEM|NET|DER>]
-[B<-outform PEM|NET|DER>]
+[B<-inform PEM|DER>]
+[B<-outform PEM|DER>]
[B<-in filename>]
[B<-passin arg>]
[B<-out filename>]
[B<-passout arg>]
[B<-aes128>]
[B<-aes192>]
[B<-aes256>]
[B<-aria128>]
[B<-aria192>]
[B<-aria256>]
[B<-camellia128>]
[B<-camellia192>]
[B<-camellia256>]
[B<-des>]
[B<-des3>]
[B<-idea>]
[B<-text>]
[B<-noout>]
[B<-modulus>]
[B<-check>]
[B<-pubin>]
[B<-pubout>]
[B<-RSAPublicKey_in>]
[B<-RSAPublicKey_out>]
[B<-engine id>]
=head1 DESCRIPTION
The B<rsa> command processes RSA keys. They can be converted between various
forms and their components printed out. B<Note> this command uses the
traditional SSLeay compatible format for private key encryption: newer
applications should use the more secure PKCS#8 format using the B<pkcs8>
utility.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
-=item B<-inform DER|NET|PEM>
+=item B<-inform DER|PEM>
This specifies the input format. The B<DER> option uses an ASN1 DER encoded
form compatible with the PKCS#1 RSAPrivateKey or SubjectPublicKeyInfo format.
The B<PEM> form is the default format: it consists of the B<DER> format base64
encoded with additional header and footer lines. On input PKCS#8 format private
-keys are also accepted. The B<NET> form is a format is described in the B<NOTES>
-section.
+keys are also accepted.
-=item B<-outform DER|NET|PEM>
+=item B<-outform DER|PEM>
This specifies the output format, the options have the same meaning and default
as the B<-inform> option.
=item B<-in filename>
This specifies the input filename to read a key from or standard input if this
option is not specified. If the key is encrypted a pass phrase will be
prompted for.
=item B<-passin arg>
The input 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<-out filename>
This specifies the output filename to write a key to or standard output if this
option is not specified. If any encryption options are set then a pass phrase
will be prompted for. The output filename should B<not> be the same as the input
filename.
=item B<-passout password>
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<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
These options encrypt the private key with the specified
cipher before outputting it. A pass phrase is prompted for.
If none of these options is specified the key is written in plain text. This
means that using the B<rsa> utility to read in an encrypted key with no
encryption option can be used to remove the pass phrase from a key, or by
setting the encryption options it can be use to add or change the pass phrase.
These options can only be used with PEM format output files.
=item B<-text>
Prints out the various public or private key components in
plain text in addition to the encoded version.
=item B<-noout>
This option prevents output of the encoded version of the key.
=item B<-modulus>
This option prints out the value of the modulus of the key.
=item B<-check>
This option checks the consistency of an RSA private key.
=item B<-pubin>
By default a private key is read from the input file: with this
option a public key is read instead.
=item B<-pubout>
By default a private key is output: with this option a public
key will be output instead. This option is automatically set if
the input is a public key.
=item B<-RSAPublicKey_in>, B<-RSAPublicKey_out>
Like B<-pubin> and B<-pubout> except B<RSAPublicKey> format is used instead.
=item B<-engine id>
Specifying an engine (by its unique B<id> string) will cause B<rsa>
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.
=back
=head1 NOTES
The PEM private key format uses the header and footer lines:
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
The PEM public key format uses the header and footer lines:
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
The PEM B<RSAPublicKey> format uses the header and footer lines:
-----BEGIN RSA PUBLIC KEY-----
-----END RSA PUBLIC KEY-----
-The B<NET> form is a format compatible with older Netscape servers
-and Microsoft IIS .key files, this uses unsalted RC4 for its encryption.
-It is not very secure and so should only be used when necessary.
-
-Some newer version of IIS have additional data in the exported .key
-files. To use these with the utility, view the file with a binary editor
-and look for the string "private-key", then trace back to the byte
-sequence 0x30, 0x82 (this is an ASN1 SEQUENCE). Copy all the data
-from this point onwards to another file and use that as the input
-to the B<rsa> utility with the B<-inform NET> option.
-
=head1 EXAMPLES
To remove the pass phrase on an RSA private key:
openssl rsa -in key.pem -out keyout.pem
To encrypt a private key using triple DES:
openssl rsa -in key.pem -des3 -out keyout.pem
To convert a private key from PEM to DER format:
openssl rsa -in key.pem -outform DER -out keyout.der
To print out the components of a private key to standard output:
openssl rsa -in key.pem -text -noout
To just output the public part of a private key:
openssl rsa -in key.pem -pubout -out pubkey.pem
Output the public part of a private key in B<RSAPublicKey> format:
openssl rsa -in key.pem -RSAPublicKey_out -out pubkey.pem
=head1 BUGS
-The command line password arguments don't currently work with
-B<NET> format.
-
There should be an option that automatically handles .key files,
without having to manually edit them.
=head1 SEE ALSO
L<pkcs8(1)>, L<dsa(1)>, L<genrsa(1)>,
L<gendsa(1)>
=head1 COPYRIGHT
Copyright 2000-2018 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 07016fc46131..f4c4eda35313 100644
--- a/doc/man1/s_server.pod
+++ b/doc/man1/s_server.pod
@@ -1,834 +1,838 @@
=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<-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<-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.
+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.
+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).
+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>.
+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
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.
=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<-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.
+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 first added to OpenSSL 1.1.0.
The -allow-no-dhe-kex and -prioritize_chacha options were first added to
OpenSSL 1.1.1.
=head1 COPYRIGHT
Copyright 2000-2018 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/storeutl.pod b/doc/man1/storeutl.pod
index 3f26ab500b83..083f0282469e 100644
--- a/doc/man1/storeutl.pod
+++ b/doc/man1/storeutl.pod
@@ -1,130 +1,133 @@
=pod
=head1 NAME
openssl-storeutl,
storeutl - STORE utility
=head1 SYNOPSIS
B<openssl> B<storeutl>
[B<-help>]
[B<-out file>]
[B<-noout>]
[B<-passin arg>]
[B<-text arg>]
[B<-engine id>]
[B<-r>]
[B<-certs>]
[B<-keys>]
[B<-crls>]
[B<-subject arg>]
[B<-issuer arg>]
[B<-serial arg>]
[B<-alias arg>]
[B<-fingerprint arg>]
[B<-I<digest>>]
B<uri> ...
=head1 DESCRIPTION
The B<storeutl> command can be used to display the contents (after decryption
as the case may be) fetched from the given URIs.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-out filename>
specifies the output filename to write to or standard output by
default.
=item B<-noout>
this option prevents output of the PEM data.
=item B<-passin arg>
the 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<-text>
Prints out the objects in text form, similarly to the B<-text> output from
B<openssl x509>, B<openssl pkey>, etc.
=item B<-engine id>
specifying an engine (by its unique B<id> string) will cause B<storeutl>
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<-r>
Fetch objects recursively when possible.
=item B<-certs>
=item B<-keys>
=item B<-crls>
Only select the certificates, keys or CRLs from the given URI.
However, if this URI would return a set of names (URIs), those are always
returned.
=item B<-subject arg>
Search for an object having the subject name B<arg>.
-The arg must be formatted as I</type0=value0/type1=value1/type2=...>,
-characters may be escaped by \ (backslash), no spaces are skipped.
+The arg must be formatted as I</type0=value0/type1=value1/type2=...>.
+Keyword characters may be escaped by \ (backslash), and whitespace is retained.
+Empty values are permitted but are ignored for the search. That is,
+a search with an empty value will have the same effect as not specifying
+the type at all.
=item B<-issuer arg>
=item B<-serial arg>
Search for an object having the given issuer name and serial number.
These two options I<must> be used together.
The issuer arg must be formatted as I</type0=value0/type1=value1/type2=...>,
characters may be escaped by \ (backslash), no spaces are skipped.
The serial arg may be specified as a decimal value or a hex value if preceded
by B<0x>.
=item B<-alias arg>
Search for an object having the given alias.
=item B<-fingerprint arg>
Search for an object having the given fingerprint.
=item B<-I<digest>>
The digest that was used to compute the fingerprint given with B<-fingerprint>.
=back
=head1 SEE ALSO
L<openssl(1)>
=head1 HISTORY
B<openssl> B<storeutl> was added to OpenSSL 1.1.1.
=head1 COPYRIGHT
Copyright 2016-2018 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/x509.pod b/doc/man1/x509.pod
index 6e4d28815530..547da5da2368 100644
--- a/doc/man1/x509.pod
+++ b/doc/man1/x509.pod
@@ -1,936 +1,935 @@
=pod
=head1 NAME
openssl-x509,
x509 - Certificate display and signing utility
=head1 SYNOPSIS
B<openssl> B<x509>
[B<-help>]
-[B<-inform DER|PEM|NET>]
-[B<-outform DER|PEM|NET>]
+[B<-inform DER|PEM>]
+[B<-outform DER|PEM>]
[B<-keyform DER|PEM>]
[B<-CAform DER|PEM>]
[B<-CAkeyform DER|PEM>]
[B<-in filename>]
[B<-out filename>]
[B<-serial>]
[B<-hash>]
[B<-subject_hash>]
[B<-issuer_hash>]
[B<-ocspid>]
[B<-subject>]
[B<-issuer>]
[B<-nameopt option>]
[B<-email>]
[B<-ocsp_uri>]
[B<-startdate>]
[B<-enddate>]
[B<-purpose>]
[B<-dates>]
[B<-checkend num>]
[B<-modulus>]
[B<-pubkey>]
[B<-fingerprint>]
[B<-alias>]
[B<-noout>]
[B<-trustout>]
[B<-clrtrust>]
[B<-clrreject>]
[B<-addtrust arg>]
[B<-addreject arg>]
[B<-setalias arg>]
[B<-days arg>]
[B<-set_serial n>]
[B<-signkey filename>]
[B<-passin arg>]
[B<-x509toreq>]
[B<-req>]
[B<-CA filename>]
[B<-CAkey filename>]
[B<-CAcreateserial>]
[B<-CAserial filename>]
[B<-force_pubkey key>]
[B<-text>]
[B<-ext extensions>]
[B<-certopt option>]
[B<-C>]
[B<-I<digest>>]
[B<-clrext>]
[B<-extfile filename>]
[B<-extensions section>]
[B<-rand file...>]
[B<-writerand file>]
[B<-engine id>]
[B<-preserve_dates>]
=head1 DESCRIPTION
The B<x509> command is a multi purpose certificate utility. It can be
used to display certificate information, convert certificates to
various forms, sign certificate requests like a "mini CA" or edit
certificate trust settings.
Since there are a large number of options they will split up into
various sections.
=head1 OPTIONS
=head2 Input, Output, and General Purpose Options
=over 4
=item B<-help>
Print out a usage message.
-=item B<-inform DER|PEM|NET>
+=item B<-inform DER|PEM>
This specifies the input format normally the command will expect an X509
certificate but this can change if other options such as B<-req> are
present. The DER format is the DER encoding of the certificate and PEM
is the base64 encoding of the DER encoding with header and footer lines
-added. The NET option is an obscure Netscape server format that is now
-obsolete. The default format is PEM.
+added. The default format is PEM.
-=item B<-outform DER|PEM|NET>
+=item B<-outform DER|PEM>
This specifies the output format, the options have the same meaning and default
as the B<-inform> option.
=item B<-in filename>
This specifies the input filename to read a certificate from or standard input
if this option is not specified.
=item B<-out filename>
This specifies the output filename to write to or standard output by
default.
=item B<-I<digest>>
The digest to use.
This affects any signing or display option that uses a message
digest, such as the B<-fingerprint>, B<-signkey> and B<-CA> options.
Any digest supported by the OpenSSL B<dgst> command can be used.
If not specified then SHA1 is used with B<-fingerprint> or
the default digest for the signing algorithm is used, typically SHA256.
=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<x509>
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<-preserve_dates>
When signing a certificate, preserve the "notBefore" and "notAfter" dates instead
of adjusting them to current time and duration. Cannot be used with the B<-days> option.
=back
=head2 Display Options
Note: the B<-alias> and B<-purpose> options are also display options
but are described in the B<TRUST SETTINGS> section.
=over 4
=item B<-text>
Prints out the certificate in text form. Full details are output including the
public key, signature algorithms, issuer and subject names, serial number
any extensions present and any trust settings.
=item B<-ext extensions>
Prints out the certificate extensions in text form. Extensions are specified
with a comma separated string, e.g., "subjectAltName,subjectKeyIdentifier".
See the L<x509v3_config(5)> manual page for the extension names.
=item B<-certopt option>
Customise the output format used with B<-text>. The B<option> argument
can be a single option or multiple options separated by commas. The
B<-certopt> switch may be also be used more than once to set multiple
options. See the B<TEXT OPTIONS> section for more information.
=item B<-noout>
This option prevents output of the encoded version of the request.
=item B<-pubkey>
Outputs the certificate's SubjectPublicKeyInfo block in PEM format.
=item B<-modulus>
This option prints out the value of the modulus of the public key
contained in the certificate.
=item B<-serial>
Outputs the certificate serial number.
=item B<-subject_hash>
Outputs the "hash" of the certificate subject name. This is used in OpenSSL to
form an index to allow certificates in a directory to be looked up by subject
name.
=item B<-issuer_hash>
Outputs the "hash" of the certificate issuer name.
=item B<-ocspid>
Outputs the OCSP hash values for the subject name and public key.
=item B<-hash>
Synonym for "-subject_hash" for backward compatibility reasons.
=item B<-subject_hash_old>
Outputs the "hash" of the certificate subject name using the older algorithm
as used by OpenSSL before version 1.0.0.
=item B<-issuer_hash_old>
Outputs the "hash" of the certificate issuer name using the older algorithm
as used by OpenSSL before version 1.0.0.
=item B<-subject>
Outputs the subject name.
=item B<-issuer>
Outputs the issuer name.
=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 B<NAME OPTIONS> section for more information.
=item B<-email>
Outputs the email address(es) if any.
=item B<-ocsp_uri>
Outputs the OCSP responder address(es) if any.
=item B<-startdate>
Prints out the start date of the certificate, that is the notBefore date.
=item B<-enddate>
Prints out the expiry date of the certificate, that is the notAfter date.
=item B<-dates>
Prints out the start and expiry dates of a certificate.
=item B<-checkend arg>
Checks if the certificate expires within the next B<arg> seconds and exits
non-zero if yes it will expire or zero if not.
=item B<-fingerprint>
Calculates and outputs the digest of the DER encoded version of the entire
certificate (see digest options).
This is commonly called a "fingerprint". Because of the nature of message
digests, the fingerprint of a certificate is unique to that certificate and
two certificates with the same fingerprint can be considered to be the same.
=item B<-C>
This outputs the certificate in the form of a C source file.
=back
=head2 Trust Settings
A B<trusted certificate> is an ordinary certificate which has several
additional pieces of information attached to it such as the permitted
and prohibited uses of the certificate and an "alias".
Normally when a certificate is being verified at least one certificate
must be "trusted". By default a trusted certificate must be stored
locally and must be a root CA: any certificate chain ending in this CA
is then usable for any purpose.
Trust settings currently are only used with a root CA. They allow a finer
control over the purposes the root CA can be used for. For example a CA
may be trusted for SSL client but not SSL server use.
See the description of the B<verify> utility for more information on the
meaning of trust settings.
Future versions of OpenSSL will recognize trust settings on any
certificate: not just root CAs.
=over 4
=item B<-trustout>
This causes B<x509> to output a B<trusted> certificate. An ordinary
or trusted certificate can be input but by default an ordinary
certificate is output and any trust settings are discarded. With the
B<-trustout> option a trusted certificate is output. A trusted
certificate is automatically output if any trust settings are modified.
=item B<-setalias arg>
Sets the alias of the certificate. This will allow the certificate
to be referred to using a nickname for example "Steve's Certificate".
=item B<-alias>
Outputs the certificate alias, if any.
=item B<-clrtrust>
Clears all the permitted or trusted uses of the certificate.
=item B<-clrreject>
Clears all the prohibited or rejected uses of the certificate.
=item B<-addtrust arg>
Adds a trusted certificate use.
Any object name can be used here but currently only B<clientAuth> (SSL client
use), B<serverAuth> (SSL server use), B<emailProtection> (S/MIME email) and
B<anyExtendedKeyUsage> are used.
As of OpenSSL 1.1.0, the last of these blocks all purposes when rejected or
enables all purposes when trusted.
Other OpenSSL applications may define additional uses.
=item B<-addreject arg>
Adds a prohibited use. It accepts the same values as the B<-addtrust>
option.
=item B<-purpose>
This option performs tests on the certificate extensions and outputs
the results. For a more complete description see the B<CERTIFICATE
EXTENSIONS> section.
=back
=head2 Signing Options
The B<x509> utility can be used to sign certificates and requests: it
can thus behave like a "mini CA".
=over 4
=item B<-signkey filename>
This option causes the input file to be self signed using the supplied
private key.
If the input file is a certificate it sets the issuer name to the
subject name (i.e. makes it self signed) changes the public key to the
supplied value and changes the start and end dates. The start date is
set to the current time and the end date is set to a value determined
by the B<-days> option. Any certificate extensions are retained unless
the B<-clrext> option is supplied; this includes, for example, any existing
key identifier extensions.
If the input is a certificate request then a self signed certificate
is created using the supplied private key using the subject name in
the request.
=item B<-passin arg>
The 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<-clrext>
Delete any extensions from a certificate. This option is used when a
certificate is being created from another certificate (for example with
the B<-signkey> or the B<-CA> options). Normally all extensions are
retained.
=item B<-keyform PEM|DER>
Specifies the format (DER or PEM) of the private key file used in the
B<-signkey> option.
=item B<-days arg>
Specifies the number of days to make a certificate valid for. The default
is 30 days. Cannot be used with the B<-preserve_dates> option.
=item B<-x509toreq>
Converts a certificate into a certificate request. The B<-signkey> option
is used to pass the required private key.
=item B<-req>
By default a certificate is expected on input. With this option a
certificate request is expected instead.
=item B<-set_serial n>
Specifies the serial number to use. This option can be used with either
the B<-signkey> or B<-CA> options. If used in conjunction with the B<-CA>
option the serial number file (as specified by the B<-CAserial> or
B<-CAcreateserial> options) is not used.
The serial number can be decimal or hex (if preceded by B<0x>).
=item B<-CA filename>
Specifies the CA certificate to be used for signing. When this option is
present B<x509> behaves like a "mini CA". The input file is signed by this
CA using this option: that is its issuer name is set to the subject name
of the CA and it is digitally signed using the CAs private key.
This option is normally combined with the B<-req> option. Without the
B<-req> option the input is a certificate which must be self signed.
=item B<-CAkey filename>
Sets the CA private key to sign a certificate with. If this option is
not specified then it is assumed that the CA private key is present in
the CA certificate file.
=item B<-CAserial filename>
Sets the CA serial number file to use.
When the B<-CA> option is used to sign a certificate it uses a serial
number specified in a file. This file consists of one line containing
an even number of hex digits with the serial number to use. After each
use the serial number is incremented and written out to the file again.
The default filename consists of the CA certificate file base name with
".srl" appended. For example if the CA certificate file is called
"mycacert.pem" it expects to find a serial number file called "mycacert.srl".
=item B<-CAcreateserial>
With this option the CA serial number file is created if it does not exist:
it will contain the serial number "02" and the certificate being signed will
have the 1 as its serial number. If the B<-CA> option is specified
and the serial number file does not exist a random number is generated;
this is the recommended practice.
=item B<-extfile filename>
File containing certificate extensions to use. If not specified then
no extensions are added to the certificate.
=item B<-extensions section>
The section to add certificate extensions from. If this option is not
specified then the extensions should either be contained in the unnamed
(default) section or the default section should contain a variable called
"extensions" which contains the section to use. See the
L<x509v3_config(5)> manual page for details of the
extension section format.
=item B<-force_pubkey key>
When a certificate is created set its public key to B<key> instead of the
key in the certificate or certificate request. This option is useful for
creating certificates where the algorithm can't normally sign requests, for
example DH.
The format or B<key> can be specified using the B<-keyform> option.
=back
=head2 Name Options
The B<nameopt> command line switch determines how the subject and issuer
names are displayed. If no B<nameopt> switch is present the default "oneline"
format is used which is compatible with previous versions of OpenSSL.
Each option is described in detail below, all options can be preceded by
a B<-> to turn the option off. Only the first four will normally be used.
=over 4
=item B<compat>
Use the old format.
=item B<RFC2253>
Displays names compatible with RFC2253 equivalent to B<esc_2253>, B<esc_ctrl>,
B<esc_msb>, B<utf8>, B<dump_nostr>, B<dump_unknown>, B<dump_der>,
B<sep_comma_plus>, B<dn_rev> and B<sname>.
=item B<oneline>
A oneline format which is more readable than RFC2253. It is equivalent to
specifying the B<esc_2253>, B<esc_ctrl>, B<esc_msb>, B<utf8>, B<dump_nostr>,
B<dump_der>, B<use_quote>, B<sep_comma_plus_space>, B<space_eq> and B<sname>
options. This is the I<default> of no name options are given explicitly.
=item B<multiline>
A multiline format. It is equivalent B<esc_ctrl>, B<esc_msb>, B<sep_multiline>,
B<space_eq>, B<lname> and B<align>.
=item B<esc_2253>
Escape the "special" characters required by RFC2253 in a field. That is
B<,+"E<lt>E<gt>;>. Additionally B<#> is escaped at the beginning of a string
and a space character at the beginning or end of a string.
=item B<esc_2254>
Escape the "special" characters required by RFC2254 in a field. That is
the B<NUL> character as well as and B<()*>.
=item B<esc_ctrl>
Escape control characters. That is those with ASCII values less than
0x20 (space) and the delete (0x7f) character. They are escaped using the
RFC2253 \XX notation (where XX are two hex digits representing the
character value).
=item B<esc_msb>
Escape characters with the MSB set, that is with ASCII values larger than
127.
=item B<use_quote>
Escapes some characters by surrounding the whole string with B<"> characters,
without the option all escaping is done with the B<\> character.
=item B<utf8>
Convert all strings to UTF8 format first. This is required by RFC2253. If
you are lucky enough to have a UTF8 compatible terminal then the use
of this option (and B<not> setting B<esc_msb>) may result in the correct
display of multibyte (international) characters. Is this option is not
present then multibyte characters larger than 0xff will be represented
using the format \UXXXX for 16 bits and \WXXXXXXXX for 32 bits.
Also if this option is off any UTF8Strings will be converted to their
character form first.
=item B<ignore_type>
This option does not attempt to interpret multibyte characters in any
way. That is their content octets are merely dumped as though one octet
represents each character. This is useful for diagnostic purposes but
will result in rather odd looking output.
=item B<show_type>
Show the type of the ASN1 character string. The type precedes the
field contents. For example "BMPSTRING: Hello World".
=item B<dump_der>
When this option is set any fields that need to be hexdumped will
be dumped using the DER encoding of the field. Otherwise just the
content octets will be displayed. Both options use the RFC2253
B<#XXXX...> format.
=item B<dump_nostr>
Dump non character string types (for example OCTET STRING) if this
option is not set then non character string types will be displayed
as though each content octet represents a single character.
=item B<dump_all>
Dump all fields. This option when used with B<dump_der> allows the
DER encoding of the structure to be unambiguously determined.
=item B<dump_unknown>
Dump any field whose OID is not recognised by OpenSSL.
=item B<sep_comma_plus>, B<sep_comma_plus_space>, B<sep_semi_plus_space>,
B<sep_multiline>
These options determine the field separators. The first character is
between RDNs and the second between multiple AVAs (multiple AVAs are
very rare and their use is discouraged). The options ending in
"space" additionally place a space after the separator to make it
more readable. The B<sep_multiline> uses a linefeed character for
the RDN separator and a spaced B<+> for the AVA separator. It also
indents the fields by four characters. If no field separator is specified
then B<sep_comma_plus_space> is used by default.
=item B<dn_rev>
Reverse the fields of the DN. This is required by RFC2253. As a side
effect this also reverses the order of multiple AVAs but this is
permissible.
=item B<nofname>, B<sname>, B<lname>, B<oid>
These options alter how the field name is displayed. B<nofname> does
not display the field at all. B<sname> uses the "short name" form
(CN for commonName for example). B<lname> uses the long form.
B<oid> represents the OID in numerical form and is useful for
diagnostic purpose.
=item B<align>
Align field values for a more readable output. Only usable with
B<sep_multiline>.
=item B<space_eq>
Places spaces round the B<=> character which follows the field
name.
=back
=head2 Text Options
As well as customising the name output format, it is also possible to
customise the actual fields printed using the B<certopt> options when
the B<text> option is present. The default behaviour is to print all fields.
=over 4
=item B<compatible>
Use the old format. This is equivalent to specifying no output options at all.
=item B<no_header>
Don't print header information: that is the lines saying "Certificate"
and "Data".
=item B<no_version>
Don't print out the version number.
=item B<no_serial>
Don't print out the serial number.
=item B<no_signame>
Don't print out the signature algorithm used.
=item B<no_validity>
Don't print the validity, that is the B<notBefore> and B<notAfter> fields.
=item B<no_subject>
Don't print out the subject name.
=item B<no_issuer>
Don't print out the issuer name.
=item B<no_pubkey>
Don't print out the public key.
=item B<no_sigdump>
Don't give a hexadecimal dump of the certificate signature.
=item B<no_aux>
Don't print out certificate trust information.
=item B<no_extensions>
Don't print out any X509V3 extensions.
=item B<ext_default>
Retain default extension behaviour: attempt to print out unsupported
certificate extensions.
=item B<ext_error>
Print an error message for unsupported certificate extensions.
=item B<ext_parse>
ASN1 parse unsupported extensions.
=item B<ext_dump>
Hex dump unsupported extensions.
=item B<ca_default>
The value used by the B<ca> utility, equivalent to B<no_issuer>, B<no_pubkey>,
B<no_header>, and B<no_version>.
=back
=head1 EXAMPLES
Note: in these examples the '\' means the example should be all on one
line.
Display the contents of a certificate:
openssl x509 -in cert.pem -noout -text
Display the "Subject Alternative Name" extension of a certificate:
openssl x509 -in cert.pem -noout -ext subjectAltName
Display more extensions of a certificate:
openssl x509 -in cert.pem -noout -ext subjectAltName,nsCertType
Display the certificate serial number:
openssl x509 -in cert.pem -noout -serial
Display the certificate subject name:
openssl x509 -in cert.pem -noout -subject
Display the certificate subject name in RFC2253 form:
openssl x509 -in cert.pem -noout -subject -nameopt RFC2253
Display the certificate subject name in oneline form on a terminal
supporting UTF8:
openssl x509 -in cert.pem -noout -subject -nameopt oneline,-esc_msb
Display the certificate SHA1 fingerprint:
openssl x509 -sha1 -in cert.pem -noout -fingerprint
Convert a certificate from PEM to DER format:
openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
Convert a certificate to a certificate request:
openssl x509 -x509toreq -in cert.pem -out req.pem -signkey key.pem
Convert a certificate request into a self signed certificate using
extensions for a CA:
openssl x509 -req -in careq.pem -extfile openssl.cnf -extensions v3_ca \
-signkey key.pem -out cacert.pem
Sign a certificate request using the CA certificate above and add user
certificate extensions:
openssl x509 -req -in req.pem -extfile openssl.cnf -extensions v3_usr \
-CA cacert.pem -CAkey key.pem -CAcreateserial
Set a certificate to be trusted for SSL client use and change set its alias to
"Steve's Class 1 CA"
openssl x509 -in cert.pem -addtrust clientAuth \
-setalias "Steve's Class 1 CA" -out trust.pem
=head1 NOTES
The PEM format uses the header and footer lines:
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
it will also handle files containing:
-----BEGIN X509 CERTIFICATE-----
-----END X509 CERTIFICATE-----
Trusted certificates have the lines
-----BEGIN TRUSTED CERTIFICATE-----
-----END TRUSTED CERTIFICATE-----
The conversion to UTF8 format used with the name options assumes that
T61Strings use the ISO8859-1 character set. This is wrong but Netscape
and MSIE do this as do many certificates. So although this is incorrect
it is more likely to display the majority of certificates correctly.
The B<-email> option searches the subject name and the subject alternative
name extension. Only unique email addresses will be printed out: it will
not print the same address more than once.
=head1 CERTIFICATE EXTENSIONS
The B<-purpose> option checks the certificate extensions and determines
what the certificate can be used for. The actual checks done are rather
complex and include various hacks and workarounds to handle broken
certificates and software.
The same code is used when verifying untrusted certificates in chains
so this section is useful if a chain is rejected by the verify code.
The basicConstraints extension CA flag is used to determine whether the
certificate can be used as a CA. If the CA flag is true then it is a CA,
if the CA flag is false then it is not a CA. B<All> CAs should have the
CA flag set to true.
If the basicConstraints extension is absent then the certificate is
considered to be a "possible CA" other extensions are checked according
to the intended use of the certificate. A warning is given in this case
because the certificate should really not be regarded as a CA: however
it is allowed to be a CA to work around some broken software.
If the certificate is a V1 certificate (and thus has no extensions) and
it is self signed it is also assumed to be a CA but a warning is again
given: this is to work around the problem of Verisign roots which are V1
self signed certificates.
If the keyUsage extension is present then additional restraints are
made on the uses of the certificate. A CA certificate B<must> have the
keyCertSign bit set if the keyUsage extension is present.
The extended key usage extension places additional restrictions on the
certificate uses. If this extension is present (whether critical or not)
the key can only be used for the purposes specified.
A complete description of each test is given below. The comments about
basicConstraints and keyUsage and V1 certificates above apply to B<all>
CA certificates.
=over 4
=item B<SSL Client>
The extended key usage extension must be absent or include the "web client
authentication" OID. keyUsage must be absent or it must have the
digitalSignature bit set. Netscape certificate type must be absent or it must
have the SSL client bit set.
=item B<SSL Client CA>
The extended key usage extension must be absent or include the "web client
authentication" OID. Netscape certificate type must be absent or it must have
the SSL CA bit set: this is used as a work around if the basicConstraints
extension is absent.
=item B<SSL Server>
The extended key usage extension must be absent or include the "web server
authentication" and/or one of the SGC OIDs. keyUsage must be absent or it
must have the digitalSignature, the keyEncipherment set or both bits set.
Netscape certificate type must be absent or have the SSL server bit set.
=item B<SSL Server CA>
The extended key usage extension must be absent or include the "web server
authentication" and/or one of the SGC OIDs. Netscape certificate type must
be absent or the SSL CA bit must be set: this is used as a work around if the
basicConstraints extension is absent.
=item B<Netscape SSL Server>
For Netscape SSL clients to connect to an SSL server it must have the
keyEncipherment bit set if the keyUsage extension is present. This isn't
always valid because some cipher suites use the key for digital signing.
Otherwise it is the same as a normal SSL server.
=item B<Common S/MIME Client Tests>
The extended key usage extension must be absent or include the "email
protection" OID. Netscape certificate type must be absent or should have the
S/MIME bit set. If the S/MIME bit is not set in Netscape certificate type
then the SSL client bit is tolerated as an alternative but a warning is shown:
this is because some Verisign certificates don't set the S/MIME bit.
=item B<S/MIME Signing>
In addition to the common S/MIME client tests the digitalSignature bit or
the nonRepudiation bit must be set if the keyUsage extension is present.
=item B<S/MIME Encryption>
In addition to the common S/MIME tests the keyEncipherment bit must be set
if the keyUsage extension is present.
=item B<S/MIME CA>
The extended key usage extension must be absent or include the "email
protection" OID. Netscape certificate type must be absent or must have the
S/MIME CA bit set: this is used as a work around if the basicConstraints
extension is absent.
=item B<CRL Signing>
The keyUsage extension must be absent or it must have the CRL signing bit
set.
=item B<CRL Signing CA>
The normal CA tests apply. Except in this case the basicConstraints extension
must be present.
=back
=head1 BUGS
Extensions in certificates are not transferred to certificate requests and
vice versa.
It is possible to produce invalid certificates or requests by specifying the
wrong private key or using inconsistent options in some cases: these should
be checked.
There should be options to explicitly set such things as start and end
dates rather than an offset from the current time.
=head1 SEE ALSO
L<req(1)>, L<ca(1)>, L<genrsa(1)>,
L<gendsa(1)>, L<verify(1)>,
L<x509v3_config(5)>
=head1 HISTORY
The hash algorithm used in the B<-subject_hash> and B<-issuer_hash> options
before OpenSSL 1.0.0 was based on the deprecated MD5 algorithm and the encoding
of the distinguished name. In OpenSSL 1.0.0 and later it is based on a
canonical version of the DN using SHA1. This means that any directories using
the old form must have their links rebuilt using B<c_rehash> or similar.
=head1 COPYRIGHT
Copyright 2000-2018 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 f543bea1ee7b..6e0394d637b2 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 is
+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
-an C<C=E(ks3,D(ks2,E(ks1,M)))>. This mode is used by SSL.
+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() encrypt/decrypts using the propagating cipher block
+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() encrypt/decrypts using cipher feedback mode. This
-method takes an array of characters as input and outputs and array of
+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 small numbers of characters.
+suggested for use when sending a small number of characters.
DES_cfb64_encrypt()
-implements CFB mode of DES with 64bit feedback. Why is this
+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, no 8 byte padding. Each call to this
+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 :-).
+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 and array of
+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 numbits, this function is only
-suggested for use when sending small numbers of characters.
+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
+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.
+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 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.
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_DigestInit.pod b/doc/man3/EVP_DigestInit.pod
index 0fedd17ce6c6..5ecbcc5e8992 100644
--- a/doc/man3/EVP_DigestInit.pod
+++ b/doc/man3/EVP_DigestInit.pod
@@ -1,390 +1,391 @@
=pod
=head1 NAME
EVP_MD_CTX_new, EVP_MD_CTX_reset, EVP_MD_CTX_free, EVP_MD_CTX_copy_ex,
EVP_MD_CTX_ctrl, EVP_MD_CTX_set_flags, EVP_MD_CTX_clear_flags,
EVP_MD_CTX_test_flags, EVP_DigestInit_ex, EVP_DigestInit, EVP_DigestUpdate,
EVP_DigestFinal_ex, EVP_DigestFinalXOF, EVP_DigestFinal,
EVP_MD_CTX_copy, EVP_MD_type, EVP_MD_pkey_type, EVP_MD_size,
EVP_MD_block_size, EVP_MD_CTX_md, EVP_MD_CTX_size,
EVP_MD_CTX_block_size, EVP_MD_CTX_type, EVP_MD_CTX_md_data,
EVP_md_null,
EVP_get_digestbyname, EVP_get_digestbynid,
EVP_get_digestbyobj,
EVP_MD_CTX_set_pkey_ctx - EVP digest routines
=head1 SYNOPSIS
#include <openssl/evp.h>
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);
void EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void* p2);
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);
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len);
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in);
int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
int EVP_MD_CTX_copy(EVP_MD_CTX *out, EVP_MD_CTX *in);
int EVP_MD_type(const EVP_MD *md);
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);
const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
int EVP_MD_CTX_size(const EVP_MD *ctx);
int EVP_MD_CTX_block_size(const EVP_MD *ctx);
int EVP_MD_CTX_type(const EVP_MD *ctx);
void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx);
const EVP_MD *EVP_md_null(void);
const EVP_MD *EVP_get_digestbyname(const char *name);
const EVP_MD *EVP_get_digestbynid(int type);
const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *o);
void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx);
=head1 DESCRIPTION
The EVP digest routines are a high level interface to message digests,
and should be used instead of the cipher-specific functions.
=over 4
=item EVP_MD_CTX_new()
Allocates and returns a digest context.
=item EVP_MD_CTX_reset()
Resets the digest context B<ctx>. This can be used to reuse an already
existing context.
=item EVP_MD_CTX_free()
Cleans up digest context B<ctx> and frees up the space allocated to it.
=item EVP_MD_CTX_ctrl()
Performs digest-specific control actions on context B<ctx>.
=item EVP_MD_CTX_set_flags(), EVP_MD_CTX_clear_flags(), EVP_MD_CTX_test_flags()
Sets, clears and tests B<ctx> flags. See L</FLAGS> below for more information.
=item EVP_DigestInit_ex()
Sets up digest context B<ctx> to use a digest B<type> from ENGINE B<impl>.
B<type> will typically be supplied by a function such as EVP_sha1(). If
B<impl> is NULL then the default implementation of digest B<type> is used.
=item EVP_DigestUpdate()
Hashes B<cnt> bytes of data at B<d> into the digest context B<ctx>. This
function can be called several times on the same B<ctx> to hash additional
data.
=item EVP_DigestFinal_ex()
Retrieves the digest value from B<ctx> and places it in B<md>. If the B<s>
parameter is not NULL then the number of bytes of data written (i.e. the
length of the digest) will be written to the integer at B<s>, at most
B<EVP_MAX_MD_SIZE> bytes will be written. After calling EVP_DigestFinal_ex()
no additional calls to EVP_DigestUpdate() can be made, but
EVP_DigestInit_ex() can be called to initialize a new digest operation.
=item EVP_DigestFinalXOF()
Interfaces to extendable-output functions, XOFs, such as SHAKE128 and SHAKE256.
It retrieves the digest value from B<ctx> and places it in B<len>-sized <B>md.
After calling this function no additional calls to EVP_DigestUpdate() can be
made, but EVP_DigestInit_ex() can be called to initialize a new operation.
=item EVP_MD_CTX_copy_ex()
Can be used to copy the message digest state from B<in> to B<out>. This is
useful if large amounts of data are to be hashed which only differ in the last
few bytes.
=item EVP_DigestInit()
Behaves in the same way as EVP_DigestInit_ex() except it always uses the
default digest implementation.
=item EVP_DigestFinal()
Similar to EVP_DigestFinal_ex() except the digest context B<ctx> is
automatically cleaned up.
=item EVP_MD_CTX_copy()
Similar to EVP_MD_CTX_copy_ex() except the destination B<out> does not have to
be initialized.
=item EVP_MD_size(),
EVP_MD_CTX_size()
Return the size of the message digest when passed an B<EVP_MD> or an
B<EVP_MD_CTX> structure, i.e. the size of the hash.
=item EVP_MD_block_size(),
EVP_MD_CTX_block_size()
Return the block size of the message digest when passed an B<EVP_MD> or an
B<EVP_MD_CTX> structure.
=item EVP_MD_type(),
EVP_MD_CTX_type()
Return the NID of the OBJECT IDENTIFIER representing the given message digest
when passed an B<EVP_MD> structure. For example, C<EVP_MD_type(EVP_sha1())>
returns B<NID_sha1>. This function is normally used when setting ASN1 OIDs.
=item EVP_MD_CTX_md_data()
Return the digest method private data for the passed B<EVP_MD_CTX>.
The space is allocated by OpenSSL and has the size originally set with
EVP_MD_meth_set_app_datasize().
=item EVP_MD_CTX_md()
Returns the B<EVP_MD> structure corresponding to the passed B<EVP_MD_CTX>.
=item EVP_MD_pkey_type()
Returns the NID of the public key signing algorithm associated with this
digest. For example EVP_sha1() is associated with RSA so this will return
B<NID_sha1WithRSAEncryption>. Since digests and signature algorithms are no
longer linked this function is only retained for compatibility reasons.
=item EVP_md_null()
A "null" message digest that does nothing: i.e. the hash it returns is of zero
length.
=item EVP_get_digestbyname(),
EVP_get_digestbynid(),
EVP_get_digestbyobj()
Returns an B<EVP_MD> structure when passed a digest name, a digest B<NID> or an
B<ASN1_OBJECT> structure respectively.
=item EVP_MD_CTX_set_pkey_ctx()
Assigns an B<EVP_PKEY_CTX> to B<EVP_MD_CTX>. This is usually used to provide
a customzied B<EVP_PKEY_CTX> to L<EVP_DigestSignInit(3)> or
L<EVP_DigestVerifyInit(3)>. The B<pctx> passed to this function should be freed
by the caller. A NULL B<pctx> pointer is also allowed to clear the B<EVP_PKEY_CTX>
assigned to B<ctx>. In such case, freeing the cleared B<EVP_PKEY_CTX> or not
depends on how the B<EVP_PKEY_CTX> is created.
=back
=head1 FLAGS
EVP_MD_CTX_set_flags(), EVP_MD_CTX_clear_flags() and EVP_MD_CTX_test_flags()
can be used the manipulate and test these B<EVP_MD_CTX> flags:
=over 4
=item EVP_MD_CTX_FLAG_ONESHOT
This flag instructs the digest to optimize for one update only, if possible.
=for comment EVP_MD_CTX_FLAG_CLEANED is internal, don't mention it
=for comment EVP_MD_CTX_FLAG_REUSE is internal, don't mention it
=for comment We currently avoid documenting flags that are only bit holder:
EVP_MD_CTX_FLAG_NON_FIPS_ALLOW, EVP_MD_CTX_FLAGS_PAD_*
=item EVP_MD_CTX_FLAG_NO_INIT
This flag instructs EVP_DigestInit() and similar not to initialise the
implementation specific data.
=item EVP_MD_CTX_FLAG_FINALISE
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, and can be
disabled with this flag.
=back
=head1 RETURN VALUES
=over 4
=item EVP_DigestInit_ex(),
EVP_DigestUpdate(),
EVP_DigestFinal_ex()
Returns 1 for
success and 0 for failure.
=item EVP_MD_CTX_ctrl()
Returns 1 if successful or 0 for failure.
=item EVP_MD_CTX_copy_ex()
Returns 1 if successful or 0 for failure.
=item EVP_MD_type(),
EVP_MD_pkey_type(),
EVP_MD_type()
Returns the NID of the corresponding OBJECT IDENTIFIER or NID_undef if none
exists.
=item EVP_MD_size(),
EVP_MD_block_size(),
EVP_MD_CTX_size(),
EVP_MD_CTX_block_size()
Returns the digest or block size in bytes.
=item EVP_md_null()
Returns a pointer to the B<EVP_MD> structure of the "null" message digest.
=item EVP_get_digestbyname(),
EVP_get_digestbynid(),
EVP_get_digestbyobj()
Returns either an B<EVP_MD> structure or NULL if an error occurs.
=item EVP_MD_CTX_set_pkey_ctx()
This function has no return value.
=back
=head1 NOTES
The B<EVP> interface to message digests should almost always be used in
preference to the low level interfaces. This is because the code then becomes
transparent to the digest used and much more flexible.
New applications should use the SHA-2 (such as L<EVP_sha256(3)>) or the SHA-3
digest algorithms (such as L<EVP_sha3_512(3)>). The other digest algorithms
are still in common use.
For most applications the B<impl> parameter to EVP_DigestInit_ex() will be
set to NULL to use the default digest implementation.
The functions EVP_DigestInit(), EVP_DigestFinal() and EVP_MD_CTX_copy() are
obsolete but are retained to maintain compatibility with existing code. New
applications should use EVP_DigestInit_ex(), EVP_DigestFinal_ex() and
EVP_MD_CTX_copy_ex() because they can efficiently reuse a digest context
instead of initializing and cleaning it up on each call and allow non default
implementations of digests to be specified.
If digest contexts are not cleaned up after use,
memory leaks will occur.
EVP_MD_CTX_size(), EVP_MD_CTX_block_size(), EVP_MD_CTX_type(),
EVP_get_digestbynid() and EVP_get_digestbyobj() are defined as
macros.
EVP_MD_CTX_ctrl() sends commands to message digests for additional configuration
or control.
=head1 EXAMPLE
This example digests the data "Test Message\n" and "Hello World\n", using the
digest name passed on the command line.
#include <stdio.h>
+ #include <string.h>
#include <openssl/evp.h>
- main(int argc, char *argv[])
+ int main(int argc, char *argv[])
{
EVP_MD_CTX *mdctx;
const EVP_MD *md;
char mess1[] = "Test Message\n";
char mess2[] = "Hello World\n";
unsigned char md_value[EVP_MAX_MD_SIZE];
- int md_len, i;
+ unsigned int md_len, i;
if (argv[1] == NULL) {
printf("Usage: mdtest digestname\n");
exit(1);
}
md = EVP_get_digestbyname(argv[1]);
if (md == NULL) {
printf("Unknown message digest %s\n", argv[1]);
exit(1);
}
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, mess1, strlen(mess1));
EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_free(mdctx);
printf("Digest is: ");
for (i = 0; i < md_len; i++)
printf("%02x", md_value[i]);
printf("\n");
exit(0);
}
=head1 SEE ALSO
L<dgst(1)>,
L<evp(7)>
The full list of digest algorithms are provided below.
L<EVP_blake2b512(3)>,
L<EVP_md2(3)>,
L<EVP_md4(3)>,
L<EVP_md5(3)>,
L<EVP_mdc2(3)>,
L<EVP_ripemd160(3)>,
L<EVP_sha1(3)>,
L<EVP_sha224(3)>,
L<EVP_sha3_224(3)>,
L<EVP_sm3(3)>,
L<EVP_whirlpool(3)>
=head1 HISTORY
EVP_MD_CTX_create() and EVP_MD_CTX_destroy() were renamed to
EVP_MD_CTX_new() and EVP_MD_CTX_free() in OpenSSL 1.1.0.
The link between digests and signing algorithms was fixed in OpenSSL 1.0 and
later, so now EVP_sha1() can be used with RSA and DSA.
EVP_dss1() was removed in OpenSSL 1.1.0.
EVP_MD_CTX_set_pkey_ctx() was added in 1.1.1.
=head1 COPYRIGHT
Copyright 2000-2018 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_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod
index e1a107c06e3c..4982e9205305 100644
--- a/doc/man3/EVP_PKEY_CTX_ctrl.pod
+++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod
@@ -1,211 +1,454 @@
=pod
=head1 NAME
EVP_PKEY_CTX_ctrl,
EVP_PKEY_CTX_ctrl_str,
+EVP_PKEY_CTX_ctrl_uint64,
+EVP_PKEY_CTX_md,
EVP_PKEY_CTX_set_signature_md,
EVP_PKEY_CTX_get_signature_md,
EVP_PKEY_CTX_set_mac_key,
EVP_PKEY_CTX_set_rsa_padding,
+EVP_PKEY_CTX_get_rsa_padding,
EVP_PKEY_CTX_set_rsa_pss_saltlen,
+EVP_PKEY_CTX_get_rsa_pss_saltlen,
EVP_PKEY_CTX_set_rsa_keygen_bits,
EVP_PKEY_CTX_set_rsa_keygen_pubexp,
+EVP_PKEY_CTX_set_rsa_keygen_primes,
+EVP_PKEY_CTX_set_rsa_mgf1_md,
+EVP_PKEY_CTX_get_rsa_mgf1_md,
+EVP_PKEY_CTX_set_rsa_oaep_md,
+EVP_PKEY_CTX_get_rsa_oaep_md,
+EVP_PKEY_CTX_set0_rsa_oaep_label,
+EVP_PKEY_CTX_get0_rsa_oaep_label,
EVP_PKEY_CTX_set_dsa_paramgen_bits,
EVP_PKEY_CTX_set_dh_paramgen_prime_len,
+EVP_PKEY_CTX_set_dh_paramgen_subprime_len,
EVP_PKEY_CTX_set_dh_paramgen_generator,
+EVP_PKEY_CTX_set_dh_paramgen_type,
+EVP_PKEY_CTX_set_dh_rfc5114,
+EVP_PKEY_CTX_set_dhx_rfc5114,
EVP_PKEY_CTX_set_dh_pad,
EVP_PKEY_CTX_set_dh_nid,
+EVP_PKEY_CTX_set_dh_kdf_type,
+EVP_PKEY_CTX_get_dh_kdf_type,
+EVP_PKEY_CTX_set0_dh_kdf_oid,
+EVP_PKEY_CTX_get0_dh_kdf_oid,
+EVP_PKEY_CTX_set_dh_kdf_md,
+EVP_PKEY_CTX_get_dh_kdf_md,
+EVP_PKEY_CTX_set_dh_kdf_outlen,
+EVP_PKEY_CTX_get_dh_kdf_outlen,
+EVP_PKEY_CTX_set0_dh_kdf_ukm,
+EVP_PKEY_CTX_get0_dh_kdf_ukm,
EVP_PKEY_CTX_set_ec_paramgen_curve_nid,
EVP_PKEY_CTX_set_ec_param_enc,
+EVP_PKEY_CTX_set_ecdh_cofactor_mode,
+EVP_PKEY_CTX_get_ecdh_cofactor_mode,
+EVP_PKEY_CTX_set_ecdh_kdf_type,
+EVP_PKEY_CTX_get_ecdh_kdf_type,
+EVP_PKEY_CTX_set_ecdh_kdf_md,
+EVP_PKEY_CTX_get_ecdh_kdf_md,
+EVP_PKEY_CTX_set_ecdh_kdf_outlen,
+EVP_PKEY_CTX_get_ecdh_kdf_outlen,
+EVP_PKEY_CTX_set0_ecdh_kdf_ukm,
+EVP_PKEY_CTX_get0_ecdh_kdf_ukm,
EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
- algorithm specific control operations
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, int p1, void *p2);
+ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
+ int cmd, uint64_t value);
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value);
+ int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md);
+
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd);
int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, unsigned char *key, int len);
#include <openssl/rsa.h>
int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad);
+ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad);
int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int len);
+ int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *len);
int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int mbits);
int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
+ int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes);
+ int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+ int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+ int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+ int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char *label, int len);
+ int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label);
#include <openssl/dsa.h>
+
int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits);
#include <openssl/dh.h>
+
int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int len);
+ int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX *ctx, int len);
int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX *ctx, int gen);
+ int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX *ctx, int type);
int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad);
int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid);
+ int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int rfc5114);
+ int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int rfc5114);
+ int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf);
+ int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid);
+ int EVP_PKEY_CTX_get0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT **oid);
+ int EVP_PKEY_CTX_set_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+ int EVP_PKEY_CTX_get_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+ int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int len);
+ int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len);
+ int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len);
+ int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
#include <openssl/ec.h>
+
int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid);
int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc);
+ int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode);
+ int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf);
+ int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+ int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+ int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int len);
+ int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len);
+ int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len);
+ int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, void *id, size_t id_len);
int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id);
int EVP_PKEY_CTX_get1_id_len(EVP_PKEY_CTX *ctx, size_t *id_len);
=head1 DESCRIPTION
The function EVP_PKEY_CTX_ctrl() sends a control operation to the context
B<ctx>. The key type used must match B<keytype> if it is not -1. The parameter
B<optype> is a mask indicating which operations the control can be applied to.
The control command is indicated in B<cmd> and any additional arguments in
B<p1> and B<p2>.
For B<cmd> = B<EVP_PKEY_CTRL_SET_MAC_KEY>, B<p1> is the length of the MAC key,
and B<p2> is MAC key. This is used by Poly1305, SipHash, HMAC and CMAC.
Applications will not normally call EVP_PKEY_CTX_ctrl() directly but will
instead call one of the algorithm specific macros below.
+The function EVP_PKEY_CTX_ctrl_uint64() is a wrapper that directly passes a
+uint64 value as B<p2> to EVP_PKEY_CTX_ctrl().
+
The function EVP_PKEY_CTX_ctrl_str() allows an application to send an algorithm
specific control operation to a context B<ctx> in string form. This is
intended to be used for options specified on the command line or in text
files. The commands supported are documented in the openssl utility
command line pages for the option B<-pkeyopt> which is supported by the
B<pkeyutl>, B<genpkey> and B<req> commands.
+The function EVP_PKEY_CTX_md() sends a message digest control operation
+to the context B<ctx>. The message digest is specified by its name B<md>.
+
All the remaining "functions" are implemented as macros.
The EVP_PKEY_CTX_set_signature_md() macro sets the message digest type used
in a signature. It can be used in the RSA, DSA and ECDSA algorithms.
The EVP_PKEY_CTX_get_signature_md() macro gets the message digest type used in a
signature. It can be used in the RSA, DSA and ECDSA algorithms.
Key generation typically involves setting up parameters to be used and
generating the private and public key data. Some algorithm implementations
allow private key data to be set explicitly using the EVP_PKEY_CTX_set_mac_key()
macro. In this case key generation is simply the process of setting up the
parameters for the key and then setting the raw key data to the value explicitly
provided by that macro. Normally applications would call
L<EVP_PKEY_new_raw_private_key(3)> or similar functions instead of this macro.
The EVP_PKEY_CTX_set_mac_key() macro can be used with any of the algorithms
supported by the L<EVP_PKEY_new_raw_private_key(3)> function.
-The macro EVP_PKEY_CTX_set_rsa_padding() sets the RSA padding mode for B<ctx>.
-The B<pad> parameter can take the value RSA_PKCS1_PADDING for PKCS#1 padding,
-RSA_SSLV23_PADDING for SSLv23 padding, RSA_NO_PADDING for no padding,
-RSA_PKCS1_OAEP_PADDING for OAEP padding (encrypt and decrypt only),
-RSA_X931_PADDING for X9.31 padding (signature operations only) and
-RSA_PKCS1_PSS_PADDING (sign and verify only).
+=head2 RSA parameters
+
+The EVP_PKEY_CTX_set_rsa_padding() macro sets the RSA padding mode for B<ctx>.
+The B<pad> parameter can take the value B<RSA_PKCS1_PADDING> for PKCS#1
+padding, B<RSA_SSLV23_PADDING> for SSLv23 padding, B<RSA_NO_PADDING> for
+no padding, B<RSA_PKCS1_OAEP_PADDING> for OAEP padding (encrypt and
+decrypt only), B<RSA_X931_PADDING> for X9.31 padding (signature operations
+only) and B<RSA_PKCS1_PSS_PADDING> (sign and verify only).
Two RSA padding modes behave differently if EVP_PKEY_CTX_set_signature_md()
is used. If this macro is called for PKCS#1 padding the plaintext buffer is
an actual digest value and is encapsulated in a DigestInfo structure according
to PKCS#1 when signing and this structure is expected (and stripped off) when
verifying. If this control is not used with RSA and PKCS#1 padding then the
supplied data is used directly and not encapsulated. In the case of X9.31
padding for RSA the algorithm identifier byte is added or checked and removed
if this control is called. If it is not called then the first byte of the plaintext
buffer is expected to be the algorithm identifier byte.
+The EVP_PKEY_CTX_get_rsa_padding() macro gets the RSA padding mode for B<ctx>.
+
The EVP_PKEY_CTX_set_rsa_pss_saltlen() macro sets the RSA PSS salt length to
-B<len> as its name implies it is only supported for PSS padding. Three special
-values are supported: RSA_PSS_SALTLEN_DIGEST sets the salt length to the
-digest length, RSA_PSS_SALTLEN_MAX sets the salt length to the maximum
-permissible value. When verifying RSA_PSS_SALTLEN_AUTO causes the salt length
+B<len>. As its name implies it is only supported for PSS padding. Three special
+values are supported: B<RSA_PSS_SALTLEN_DIGEST> sets the salt length to the
+digest length, B<RSA_PSS_SALTLEN_MAX> sets the salt length to the maximum
+permissible value. When verifying B<RSA_PSS_SALTLEN_AUTO> causes the salt length
to be automatically determined based on the B<PSS> block structure. If this
macro is not called maximum salt length is used when signing and auto detection
when verifying is used by default.
+The EVP_PKEY_CTX_get_rsa_pss_saltlen() macro gets the RSA PSS salt length
+for B<ctx>. The padding mode must have been set to B<RSA_PKCS1_PSS_PADDING>.
+
The EVP_PKEY_CTX_set_rsa_keygen_bits() macro sets the RSA key length for
RSA key generation to B<bits>. If not specified 1024 bits is used.
The EVP_PKEY_CTX_set_rsa_keygen_pubexp() macro sets the public exponent value
-for RSA key generation to B<pubexp> currently it should be an odd integer. The
+for RSA key generation to B<pubexp>. Currently it should be an odd integer. The
B<pubexp> pointer is used internally by this function so it should not be
-modified or free after the call. If this macro is not called then 65537 is used.
+modified or freed after the call. If not specified 65537 is used.
+
+The EVP_PKEY_CTX_set_rsa_keygen_primes() macro sets the number of primes for
+RSA key generation to B<primes>. If not specified 2 is used.
+
+The EVP_PKEY_CTX_set_rsa_mgf1_md() macro sets the MGF1 digest for RSA padding
+schemes to B<md>. If not explicitly set the signing digest is used. The
+padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING>
+or B<RSA_PKCS1_PSS_PADDING>.
+
+The EVP_PKEY_CTX_get_rsa_mgf1_md() macro gets the MGF1 digest for B<ctx>.
+If not explicitly set the signing digest is used. The padding mode must have
+been set to B<RSA_PKCS1_OAEP_PADDING> or B<RSA_PKCS1_PSS_PADDING>.
+
+The EVP_PKEY_CTX_set_rsa_oaep_md() macro sets the message digest type used
+in RSA OAEP to B<md>. The padding mode must have been set to
+B<RSA_PKCS1_OAEP_PADDING>.
+
+The EVP_PKEY_CTX_get_rsa_oaep_md() macro gets the message digest type used
+in RSA OAEP to B<md>. The padding mode must have been set to
+B<RSA_PKCS1_OAEP_PADDING>.
+
+The EVP_PKEY_CTX_set0_rsa_oaep_label() macro sets the RSA OAEP label to
+B<label> and its length to B<len>. If B<label> is NULL or B<len> is 0,
+the label is cleared. The library takes ownership of the label so the
+caller should not free the original memory pointed to by B<label>.
+The padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING>.
+
+The EVP_PKEY_CTX_get0_rsa_oaep_label() macro gets the RSA OAEP label to
+B<label>. The return value is the label length. The padding mode
+must have been set to B<RSA_PKCS1_OAEP_PADDING>. The resulting pointer is owned
+by the library and should not be freed by the caller.
+
+=head2 DSA parameters
-The macro EVP_PKEY_CTX_set_dsa_paramgen_bits() sets the number of bits used
+The EVP_PKEY_CTX_set_dsa_paramgen_bits() macro sets the number of bits used
for DSA parameter generation to B<bits>. If not specified 1024 is used.
-The macro EVP_PKEY_CTX_set_dh_paramgen_prime_len() sets the length of the DH
+=head2 DH parameters
+
+The EVP_PKEY_CTX_set_dh_paramgen_prime_len() macro sets the length of the DH
prime parameter B<p> for DH parameter generation. If this macro is not called
-then 1024 is used.
+then 1024 is used. Only accepts lengths greater than or equal to 256.
+
+The EVP_PKEY_CTX_set_dh_paramgen_subprime_len() macro sets the length of the DH
+optional subprime parameter B<q> for DH parameter generation. The default is
+256 if the prime is at least 2048 bits long or 160 otherwise. The DH
+paramgen type must have been set to x9.42.
The EVP_PKEY_CTX_set_dh_paramgen_generator() macro sets DH generator to B<gen>
for DH parameter generation. If not specified 2 is used.
+The EVP_PKEY_CTX_set_dh_paramgen_type() macro sets the key type for DH
+parameter generation. Use 0 for PKCS#3 DH and 1 for X9.42 DH.
+The default is 0.
+
The EVP_PKEY_CTX_set_dh_pad() macro sets the DH padding mode. If B<pad> is
1 the shared secret is padded with zeroes up to the size of the DH prime B<p>.
If B<pad> is zero (the default) then no padding is performed.
EVP_PKEY_CTX_set_dh_nid() sets the DH parameters to values corresponding to
-B<nid>. The B<nid> parameter must be B<NID_ffdhe2048>, B<NID_ffdhe3072>,
-B<NID_ffdhe4096>, B<NID_ffdhe6144> or B<NID_ffdhe8192>. This macro can be
-called during parameter or key generation.
+B<nid> as defined in RFC7919. The B<nid> parameter must be B<NID_ffdhe2048>,
+B<NID_ffdhe3072>, B<NID_ffdhe4096>, B<NID_ffdhe6144>, B<NID_ffdhe8192>
+or B<NID_undef> to clear the stored value. This macro can be called during
+parameter or key generation.
+The nid parameter and the rfc5114 parameter are mutually exclusive.
+
+The EVP_PKEY_CTX_set_dh_rfc5114() and EVP_PKEY_CTX_set_dhx_rfc5114() macros are
+synonymous. They set the DH parameters to the values defined in RFC5114. The
+B<rfc5114> parameter must be 1, 2 or 3 corresponding to RFC5114 sections
+2.1, 2.2 and 2.3. or 0 to clear the stored value. This macro can be called
+during parameter generation. The B<ctx> must have a key type of
+B<EVP_PKEY_DHX>.
+The rfc5114 parameter and the nid parameter are mutually exclusive.
+
+=head2 DH key derivation function parameters
+
+Note that all of the following functions require that the B<ctx> parameter has
+a private key type of B<EVP_PKEY_DHX>. When using key derivation, the output of
+EVP_PKEY_derive() is the output of the KDF instead of the DH shared secret.
+The KDF output is typically used as a Key Encryption Key (KEK) that in turn
+encrypts a Content Encryption Key (CEK).
+
+The EVP_PKEY_CTX_set_dh_kdf_type() macro sets the key derivation function type
+to B<kdf> for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE>
+and B<EVP_PKEY_DH_KDF_X9_42> which uses the key derivation specified in RFC2631
+(based on the keying algorithm described in X9.42). When using key derivation,
+the B<kdf_oid>, B<kdf_md> and B<kdf_outlen> parameters must also be specified.
+
+The EVP_PKEY_CTX_get_dh_kdf_type() macro gets the key derivation function type
+for B<ctx> used for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE>
+and B<EVP_PKEY_DH_KDF_X9_42>.
+
+The EVP_PKEY_CTX_set0_dh_kdf_oid() macro sets the key derivation function
+object identifier to B<oid> for DH key derivation. This OID should identify
+the algorithm to be used with the Content Encryption Key.
+The library takes ownership of the object identifier so the caller should not
+free the original memory pointed to by B<oid>.
+
+The EVP_PKEY_CTX_get0_dh_kdf_oid() macro gets the key derivation function oid
+for B<ctx> used for DH key derivation. The resulting pointer is owned by the
+library and should not be freed by the caller.
+
+The EVP_PKEY_CTX_set_dh_kdf_md() macro sets the key derivation function
+message digest to B<md> for DH key derivation. Note that RFC2631 specifies
+that this digest should be SHA1 but OpenSSL tolerates other digests.
+
+The EVP_PKEY_CTX_get_dh_kdf_md() macro gets the key derivation function
+message digest for B<ctx> used for DH key derivation.
+
+The EVP_PKEY_CTX_set_dh_kdf_outlen() macro sets the key derivation function
+output length to B<len> for DH key derivation.
+
+The EVP_PKEY_CTX_get_dh_kdf_outlen() macro gets the key derivation function
+output length for B<ctx> used for DH key derivation.
+
+The EVP_PKEY_CTX_set0_dh_kdf_ukm() macro sets the user key material to
+B<ukm> and its length to B<len> for DH key derivation. This parameter is optional
+and corresponds to the partyAInfo field in RFC2631 terms. The specification
+requires that it is 512 bits long but this is not enforced by OpenSSL.
+The library takes ownership of the user key material so the caller should not
+free the original memory pointed to by B<ukm>.
+
+The EVP_PKEY_CTX_get0_dh_kdf_ukm() macro gets the user key material for B<ctx>.
+The return value is the user key material length. The resulting pointer is owned
+by the library and should not be freed by the caller.
+
+=head2 EC parameters
The EVP_PKEY_CTX_set_ec_paramgen_curve_nid() sets the EC curve for EC parameter
generation to B<nid>. For EC parameter generation this macro must be called
or an error occurs because there is no default curve.
This function can also be called to set the curve explicitly when
generating an EC key.
-The EVP_PKEY_CTX_set_ec_param_enc() sets the EC parameter encoding to
+The EVP_PKEY_CTX_set_ec_param_enc() macro sets the EC parameter encoding to
B<param_enc> when generating EC parameters or an EC key. The encoding can be
B<OPENSSL_EC_EXPLICIT_CURVE> for explicit parameters (the default in versions
of OpenSSL before 1.1.0) or B<OPENSSL_EC_NAMED_CURVE> to use named curve form.
For maximum compatibility the named curve form should be used. Note: the
B<OPENSSL_EC_NAMED_CURVE> value was only added to OpenSSL 1.1.0; previous
versions should use 0 instead.
+=head2 ECDH parameters
+
+The EVP_PKEY_CTX_set_ecdh_cofactor_mode() macro sets the cofactor mode to
+B<cofactor_mode> for ECDH key derivation. Possible values are 1 to enable
+cofactor key derivation, 0 to disable it and -1 to clear the stored cofactor
+mode and fallback to the private key cofactor mode.
+
+The EVP_PKEY_CTX_get_ecdh_cofactor_mode() macro returns the cofactor mode for
+B<ctx> used for ECDH key derivation. Possible values are 1 when cofactor key
+derivation is enabled and 0 otherwise.
+
+=head2 ECDH key derivation function parameters
+
+The EVP_PKEY_CTX_set_ecdh_kdf_type() macro sets the key derivation function type
+to B<kdf> for ECDH key derivation. Possible values are B<EVP_PKEY_ECDH_KDF_NONE>
+and B<EVP_PKEY_ECDH_KDF_X9_63> which uses the key derivation specified in X9.63.
+When using key derivation, the B<kdf_md> and B<kdf_outlen> parameters must
+also be specified.
+
+The EVP_PKEY_CTX_get_ecdh_kdf_type() macro returns the key derivation function
+type for B<ctx> used for ECDH key derivation. Possible values are
+B<EVP_PKEY_ECDH_KDF_NONE> and B<EVP_PKEY_ECDH_KDF_X9_63>.
+
+The EVP_PKEY_CTX_set_ecdh_kdf_md() macro sets the key derivation function
+message digest to B<md> for ECDH key derivation. Note that X9.63 specifies
+that this digest should be SHA1 but OpenSSL tolerates other digests.
+
+The EVP_PKEY_CTX_get_ecdh_kdf_md() macro gets the key derivation function
+message digest for B<ctx> used for ECDH key derivation.
+
+The EVP_PKEY_CTX_set_ecdh_kdf_outlen() macro sets the key derivation function
+output length to B<len> for ECDH key derivation.
+
+The EVP_PKEY_CTX_get_ecdh_kdf_outlen() macro gets the key derivation function
+output length for B<ctx> used for ECDH key derivation.
+
+The EVP_PKEY_CTX_set0_ecdh_kdf_ukm() macro sets the user key material to B<ukm>
+for ECDH key derivation. This parameter is optional and corresponds to the
+shared info in X9.63 terms. The library takes ownership of the user key material
+so the caller should not free the original memory pointed to by B<ukm>.
+
+The EVP_PKEY_CTX_get0_ecdh_kdf_ukm() macro gets the user key material for B<ctx>.
+The return value is the user key material length. The resulting pointer is owned
+by the library and should not be freed by the caller.
+
+=head2 Other parameters
+
The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len()
macros are used to manipulate the special identifier field for specific signature
algorithms such as SM2. The EVP_PKEY_CTX_set1_id() sets an ID pointed by B<id> with
the length B<id_len> to the library. The library takes a copy of the id so that
the caller can safely free the original memory pointed to by B<id>. The
EVP_PKEY_CTX_get1_id_len() macro returns the length of the ID set via a previous
call to EVP_PKEY_CTX_set1_id(). The length is usually used to allocate adequate
memory for further calls to EVP_PKEY_CTX_get1_id(). The EVP_PKEY_CTX_get1_id()
macro returns the previously set ID value to caller in B<id>. The caller should
allocate adequate memory space for the B<id> before calling EVP_PKEY_CTX_get1_id().
=head1 RETURN VALUES
EVP_PKEY_CTX_ctrl() and its macros return a positive value for success and 0
or a negative value for failure. In particular a return value of -2
indicates the operation is not supported by the public key algorithm.
=head1 SEE ALSO
L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_encrypt(3)>,
L<EVP_PKEY_decrypt(3)>,
L<EVP_PKEY_sign(3)>,
L<EVP_PKEY_verify(3)>,
L<EVP_PKEY_verify_recover(3)>,
-L<EVP_PKEY_derive(3)>
+L<EVP_PKEY_derive(3)>,
L<EVP_PKEY_keygen(3)>
=head1 HISTORY
EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len()
macros were added in 1.1.1, other functions were first added to OpenSSL 1.0.0.
=head1 COPYRIGHT
Copyright 2006-2018 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_CTX_set_hkdf_md.pod b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
index 1433a50a6ffe..e8f19cfc9980 100644
--- a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
@@ -1,166 +1,166 @@
=pod
=head1 NAME
EVP_PKEY_CTX_set_hkdf_md, EVP_PKEY_CTX_set1_hkdf_salt,
EVP_PKEY_CTX_set1_hkdf_key, EVP_PKEY_CTX_add1_hkdf_info,
EVP_PKEY_CTX_hkdf_mode -
HMAC-based Extract-and-Expand key derivation algorithm
=head1 SYNOPSIS
#include <openssl/kdf.h>
int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *pctx, int mode);
int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *pctx, const EVP_MD *md);
int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *pctx, unsigned char *salt,
int saltlen);
int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *pctx, unsigned char *key,
int keylen);
int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *pctx, unsigned char *info,
int infolen);
=head1 DESCRIPTION
The EVP_PKEY_HKDF algorithm implements the HKDF key derivation function.
HKDF follows the "extract-then-expand" paradigm, where the KDF logically
consists of two modules. The first stage takes the input keying material
and "extracts" from it a fixed-length pseudorandom key K. The second stage
"expands" the key K into several additional pseudorandom keys (the output
of the KDF).
EVP_PKEY_CTX_hkdf_mode() sets the mode for the HKDF operation. There are three
modes that are currently defined:
=over 4
=item EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND
This is the default mode. Calling L<EVP_PKEY_derive(3)> on an EVP_PKEY_CTX set
up for HKDF will perform an extract followed by an expand operation in one go.
The derived key returned will be the result after the expand operation. The
intermediate fixed-length pseudorandom key K is not returned.
In this mode the digest, key, salt and info values must be set before a key is
derived or an error occurs.
=item EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY
In this mode calling L<EVP_PKEY_derive(3)> will just perform the extract
operation. The value returned will be the intermediate fixed-length pseudorandom
key K.
The digest, key and salt values must be set before a key is derived or an
error occurs.
=item EVP_PKEY_HKDEF_MODE_EXPAND_ONLY
In this mode calling L<EVP_PKEY_derive(3)> will just perform the expand
operation. The input key should be set to the intermediate fixed-length
pseudorandom key K returned from a previous extract operation.
The digest, key and info values must be set before a key is derived or an
error occurs.
=back
-EVP_PKEY_set_hkdf_md() sets the message digest associated with the HKDF.
+EVP_PKEY_CTX_set_hkdf_md() sets the message digest associated with the HKDF.
EVP_PKEY_CTX_set1_hkdf_salt() sets the salt to B<saltlen> bytes of the
buffer B<salt>. Any existing value is replaced.
-EVP_PKEY_CTX_set_hkdf_key() sets the key to B<keylen> bytes of the buffer
+EVP_PKEY_CTX_set1_hkdf_key() sets the key to B<keylen> bytes of the buffer
B<key>. Any existing value is replaced.
EVP_PKEY_CTX_add1_hkdf_info() sets the info value to B<infolen> bytes of the
buffer B<info>. If a value is already set, it is appended to the existing
value.
=head1 STRING CTRLS
HKDF also supports string based control operations via
L<EVP_PKEY_CTX_ctrl_str(3)>.
The B<type> parameter "md" uses the supplied B<value> as the name of the digest
algorithm to use.
The B<type> parameter "mode" uses the values "EXTRACT_AND_EXPAND",
"EXTRACT_ONLY" and "EXPAND_ONLY" to determine the mode to use.
The B<type> parameters "salt", "key" and "info" use the supplied B<value>
parameter as a B<seed>, B<key> or B<info> value.
The names "hexsalt", "hexkey" and "hexinfo" are similar except they take a hex
string which is converted to binary.
=head1 NOTES
All these functions are implemented as macros.
A context for HKDF can be obtained by calling:
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
The total length of the info buffer cannot exceed 1024 bytes in length: this
should be more than enough for any normal use of HKDF.
The output length of an HKDF expand operation is specified via the length
parameter to the L<EVP_PKEY_derive(3)> function.
Since the HKDF output length is variable, passing a B<NULL> buffer as a means
to obtain the requisite length is not meaningful with HKDF in any mode that
performs an expand operation. Instead, the caller must allocate a buffer of the
desired length, and pass that buffer to L<EVP_PKEY_derive(3)> along with (a
pointer initialized to) the desired length. Passing a B<NULL> buffer to obtain
the length is allowed when using EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY.
Optimised versions of HKDF can be implemented in an ENGINE.
=head1 RETURN VALUES
All these functions return 1 for success and 0 or a negative value for failure.
In particular a return value of -2 indicates the operation is not supported by
the public key algorithm.
=head1 EXAMPLE
This example derives 10 bytes using SHA-256 with the secret key "secret",
salt value "salt" and info value "label":
EVP_PKEY_CTX *pctx;
unsigned char out[10];
size_t outlen = sizeof(out);
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
if (EVP_PKEY_derive_init(pctx) <= 0)
/* Error */
if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0)
/* Error */
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, "salt", 4) <= 0)
/* Error */
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, "secret", 6) <= 0)
/* Error */
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, "label", 5) <= 0)
/* Error */
if (EVP_PKEY_derive(pctx, out, &outlen) <= 0)
/* Error */
=head1 CONFORMING TO
RFC 5869
=head1 SEE ALSO
L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_CTX_ctrl_str(3)>,
L<EVP_PKEY_derive(3)>
=head1 COPYRIGHT
Copyright 2016-2018 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_CTX_set_rsa_pss_keygen_md.pod b/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
index bd1193e24a5b..7578278a6cfc 100644
--- a/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
@@ -1,94 +1,94 @@
=pod
=head1 NAME
EVP_PKEY_CTX_set_rsa_pss_keygen_md,
EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md,
EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen
- EVP_PKEY RSA-PSS algorithm support functions
=head1 SYNOPSIS
#include <openssl/rsa.h>
int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *pctx,
const EVP_MD *md);
int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *pctx,
const EVP_MD *md);
int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *pctx,
int saltlen);
=head1 DESCRIPTION
These are the functions that implement L<RSA-PSS(7)>.
=head2 Signing and Verification
The macro EVP_PKEY_CTX_set_rsa_padding() is supported but an error is
returned if an attempt is made to set the padding mode to anything other
than B<PSS>. It is otherwise similar to the B<RSA> version.
The EVP_PKEY_CTX_set_rsa_pss_saltlen() macro is used to set the salt length.
If the key has usage restrictions then an error is returned if an attempt is
made to set the salt length below the minimum value. It is otherwise similar
to the B<RSA> operation except detection of the salt length (using
-RSA_PSS_SALTLEN_AUTO is not supported for verification if the key has
+RSA_PSS_SALTLEN_AUTO) is not supported for verification if the key has
usage restrictions.
The EVP_PKEY_CTX_set_signature_md() and EVP_PKEY_CTX_set_rsa_mgf1_md() macros
are used to set the digest and MGF1 algorithms respectively. If the key has
usage restrictions then an error is returned if an attempt is made to set the
digest to anything other than the restricted value. Otherwise these are
similar to the B<RSA> versions.
=head2 Key Generation
-As with RSA key generation the EVP_PKEY_CTX_set_rsa_rsa_keygen_bits()
+As with RSA key generation the EVP_PKEY_CTX_set_rsa_keygen_bits()
and EVP_PKEY_CTX_set_rsa_keygen_pubexp() macros are supported for RSA-PSS:
they have exactly the same meaning as for the RSA algorithm.
Optional parameter restrictions can be specified when generating a PSS key.
If any restrictions are set (using the macros described below) then B<all>
parameters are restricted. For example, setting a minimum salt length also
restricts the digest and MGF1 algorithms. If any restrictions are in place
then they are reflected in the corresponding parameters of the public key
when (for example) a certificate request is signed.
EVP_PKEY_CTX_set_rsa_pss_keygen_md() restricts the digest algorithm the
generated key can use to B<md>.
EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md() restricts the MGF1 algorithm the
generated key can use to B<md>.
EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen() restricts the minimum salt length
to B<saltlen>.
=head1 NOTES
A context for the B<RSA-PSS> algorithm can be obtained by calling:
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA_PSS, NULL);
=head1 RETURN VALUES
All these functions return 1 for success and 0 or a negative value for failure.
In particular a return value of -2 indicates the operation is not supported by
the public key algorithm.
=head1 SEE ALSO
L<RSA-PSS(7)>,
L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_CTX_ctrl_str(3)>,
L<EVP_PKEY_derive(3)>
=head1 COPYRIGHT
Copyright 2017-2018 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 749c52c375af..d10fc59d8bcc 100644
--- a/doc/man3/EVP_PKEY_set1_RSA.pod
+++ b/doc/man3/EVP_PKEY_set1_RSA.pod
@@ -1,145 +1,154 @@
=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_get0_hmac, 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_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
=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);
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_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_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()
-and EVP_PKEY_assign_EC_KEY() also set the referenced key to B<key>
+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_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()
-and EVP_PKEY_assign_EC_KEY() are implemented as macros.
+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()
-and EVP_PKEY_assign_EC_KEY() return 1 for success and 0 for failure.
+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 SEE ALSO
L<EVP_PKEY_new(3)>
=head1 COPYRIGHT
Copyright 2002-2018 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_aes.pod b/doc/man3/EVP_aes.pod
index 6a893993c6a8..4192a9ec369f 100644
--- a/doc/man3/EVP_aes.pod
+++ b/doc/man3/EVP_aes.pod
@@ -1,181 +1,187 @@
=pod
=head1 NAME
EVP_aes_128_cbc,
EVP_aes_192_cbc,
EVP_aes_256_cbc,
EVP_aes_128_cfb,
EVP_aes_192_cfb,
EVP_aes_256_cfb,
EVP_aes_128_cfb1,
EVP_aes_192_cfb1,
EVP_aes_256_cfb1,
EVP_aes_128_cfb8,
EVP_aes_192_cfb8,
EVP_aes_256_cfb8,
+EVP_aes_128_cfb128,
+EVP_aes_192_cfb128,
+EVP_aes_256_cfb128,
EVP_aes_128_ctr,
EVP_aes_192_ctr,
EVP_aes_256_ctr,
EVP_aes_128_ecb,
EVP_aes_192_ecb,
EVP_aes_256_ecb,
EVP_aes_128_ofb,
EVP_aes_192_ofb,
EVP_aes_256_ofb,
EVP_aes_128_cbc_hmac_sha1,
EVP_aes_256_cbc_hmac_sha1,
EVP_aes_128_cbc_hmac_sha256,
EVP_aes_256_cbc_hmac_sha256,
EVP_aes_128_ccm,
EVP_aes_192_ccm,
EVP_aes_256_ccm,
EVP_aes_128_gcm,
EVP_aes_192_gcm,
EVP_aes_256_gcm,
EVP_aes_128_ocb,
EVP_aes_192_ocb,
EVP_aes_256_ocb,
EVP_aes_128_wrap,
EVP_aes_192_wrap,
EVP_aes_256_wrap,
EVP_aes_128_wrap_pad,
EVP_aes_192_wrap_pad,
EVP_aes_256_wrap_pad,
EVP_aes_128_xts,
EVP_aes_256_xts
- EVP AES cipher
=head1 SYNOPSIS
=for comment generic
#include <openssl/evp.h>
const EVP_CIPHER *EVP_ciphername(void)
I<EVP_ciphername> is used a placeholder for any of the described cipher
functions, such as I<EVP_aes_128_cbc>.
=head1 DESCRIPTION
The AES encryption algorithm for EVP.
=over 4
=item EVP_aes_128_cbc(),
EVP_aes_192_cbc(),
EVP_aes_256_cbc(),
EVP_aes_128_cfb(),
EVP_aes_192_cfb(),
EVP_aes_256_cfb(),
EVP_aes_128_cfb1(),
EVP_aes_192_cfb1(),
EVP_aes_256_cfb1(),
EVP_aes_128_cfb8(),
EVP_aes_192_cfb8(),
EVP_aes_256_cfb8(),
+EVP_aes_128_cfb128(),
+EVP_aes_192_cfb128(),
+EVP_aes_256_cfb128(),
EVP_aes_128_ctr(),
EVP_aes_192_ctr(),
EVP_aes_256_ctr(),
EVP_aes_128_ecb(),
EVP_aes_192_ecb(),
EVP_aes_256_ecb(),
EVP_aes_128_ofb(),
EVP_aes_192_ofb(),
EVP_aes_256_ofb()
AES for 128, 192 and 256 bit keys in the following modes: CBC, CFB with 128-bit
shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB, and OFB.
=item EVP_aes_128_cbc_hmac_sha1(),
EVP_aes_256_cbc_hmac_sha1()
Authenticated encryption with AES in CBC mode using SHA-1 as HMAC, with keys of
128 and 256 bits length respectively. The authentication tag is 160 bits long.
WARNING: this is not intended for usage outside of TLS and requires calling of
some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
interface.
=item EVP_aes_128_cbc_hmac_sha256(),
EVP_aes_256_cbc_hmac_sha256()
Authenticated encryption with AES in CBC mode using SHA256 (SHA-2, 256-bits) as
HMAC, with keys of 128 and 256 bits length respectively. The authentication tag
is 256 bits long.
WARNING: this is not intended for usage outside of TLS and requires calling of
some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
interface.
=item EVP_aes_128_ccm(),
EVP_aes_192_ccm(),
EVP_aes_256_ccm(),
EVP_aes_128_gcm(),
EVP_aes_192_gcm(),
EVP_aes_256_gcm(),
EVP_aes_128_ocb(),
EVP_aes_192_ocb(),
EVP_aes_256_ocb()
AES for 128, 192 and 256 bit keys in CBC-MAC Mode (CCM), Galois Counter Mode
(GCM) and OCB Mode respectively. These ciphers require additional control
operations to function correctly, see the L<EVP_EncryptInit(3)/AEAD Interface>
section for details.
=item EVP_aes_128_wrap(),
EVP_aes_192_wrap(),
EVP_aes_256_wrap(),
EVP_aes_128_wrap_pad(),
EVP_aes_128_wrap(),
EVP_aes_192_wrap(),
EVP_aes_256_wrap(),
EVP_aes_192_wrap_pad(),
EVP_aes_128_wrap(),
EVP_aes_192_wrap(),
EVP_aes_256_wrap(),
EVP_aes_256_wrap_pad()
AES key wrap with 128, 192 and 256 bit keys, as according to RFC 3394 section
2.2.1 ("wrap") and RFC 5649 section 4.1 ("wrap with padding") respectively.
=item EVP_aes_128_xts(),
EVP_aes_256_xts()
AES XTS mode (XTS-AES) is standardized in IEEE Std. 1619-2007 and described in NIST
SP 800-38E. The XTS (XEX-based tweaked-codebook mode with ciphertext stealing)
mode was designed by Prof. Phillip Rogaway of University of California, Davis,
intended for encrypting data on a storage device.
XTS-AES provides confidentiality but not authentication of data. It also
requires a key of double-length for protection of a certain key size.
In particular, XTS-AES-128 (B<EVP_aes_128_xts>) takes input of a 256-bit key to
achieve AES 128-bit security, and XTS-AES-256 (B<EVP_aes_256_xts>) takes input
of a 512-bit key to achieve AES 256-bit security.
=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-2018 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_aria.pod b/doc/man3/EVP_aria.pod
index 3b6ad3576ed1..fbb79187546c 100644
--- a/doc/man3/EVP_aria.pod
+++ b/doc/man3/EVP_aria.pod
@@ -1,111 +1,117 @@
=pod
=head1 NAME
EVP_aria_128_cbc,
EVP_aria_192_cbc,
EVP_aria_256_cbc,
EVP_aria_128_cfb,
EVP_aria_192_cfb,
EVP_aria_256_cfb,
EVP_aria_128_cfb1,
EVP_aria_192_cfb1,
EVP_aria_256_cfb1,
EVP_aria_128_cfb8,
EVP_aria_192_cfb8,
EVP_aria_256_cfb8,
+EVP_aria_128_cfb128,
+EVP_aria_192_cfb128,
+EVP_aria_256_cfb128,
EVP_aria_128_ctr,
EVP_aria_192_ctr,
EVP_aria_256_ctr,
EVP_aria_128_ecb,
EVP_aria_192_ecb,
EVP_aria_256_ecb,
EVP_aria_128_ofb,
EVP_aria_192_ofb,
EVP_aria_256_ofb,
EVP_aria_128_ccm,
EVP_aria_192_ccm,
EVP_aria_256_ccm,
EVP_aria_128_gcm,
EVP_aria_192_gcm,
EVP_aria_256_gcm,
- EVP AES cipher
=head1 SYNOPSIS
=for comment generic
#include <openssl/evp.h>
const EVP_CIPHER *EVP_ciphername(void)
I<EVP_ciphername> is used a placeholder for any of the described cipher
functions, such as I<EVP_aria_128_cbc>.
=head1 DESCRIPTION
The ARIA encryption algorithm for EVP.
=over 4
=item EVP_aria_128_cbc(),
EVP_aria_192_cbc(),
EVP_aria_256_cbc(),
EVP_aria_128_cfb(),
EVP_aria_192_cfb(),
EVP_aria_256_cfb(),
EVP_aria_128_cfb1(),
EVP_aria_192_cfb1(),
EVP_aria_256_cfb1(),
EVP_aria_128_cfb8(),
EVP_aria_192_cfb8(),
EVP_aria_256_cfb8(),
+EVP_aria_128_cfb128(),
+EVP_aria_192_cfb128(),
+EVP_aria_256_cfb128(),
EVP_aria_128_ctr(),
EVP_aria_192_ctr(),
EVP_aria_256_ctr(),
EVP_aria_128_ecb(),
EVP_aria_192_ecb(),
EVP_aria_256_ecb(),
EVP_aria_128_ofb(),
EVP_aria_192_ofb(),
EVP_aria_256_ofb()
ARIA for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
128-bit shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB and OFB.
=item EVP_aria_128_ccm(),
EVP_aria_192_ccm(),
EVP_aria_256_ccm(),
EVP_aria_128_gcm(),
EVP_aria_192_gcm(),
EVP_aria_256_gcm(),
ARIA for 128, 192 and 256 bit keys in CBC-MAC Mode (CCM) and Galois Counter
Mode (GCM). These ciphers require additional control operations to function
correctly, see the L<EVP_EncryptInit(3)/AEAD Interface> section for details.
=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-2018 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_bf_cbc.pod b/doc/man3/EVP_bf_cbc.pod
index 4a9d3a9f5e76..505d41b4943f 100644
--- a/doc/man3/EVP_bf_cbc.pod
+++ b/doc/man3/EVP_bf_cbc.pod
@@ -1,59 +1,62 @@
=pod
=head1 NAME
EVP_bf_cbc,
EVP_bf_cfb,
+EVP_bf_cfb64,
EVP_bf_ecb,
EVP_bf_ofb
- EVP Blowfish cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_bf_cbc(void)
const EVP_CIPHER *EVP_bf_cfb(void)
+ const EVP_CIPHER *EVP_bf_cfb64(void)
const EVP_CIPHER *EVP_bf_ecb(void)
const EVP_CIPHER *EVP_bf_ofb(void)
=head1 DESCRIPTION
The Blowfish encryption algorithm for EVP.
This is a variable key length cipher.
=over 4
=item EVP_bf_cbc(),
EVP_bf_cfb(),
+EVP_bf_cfb64(),
EVP_bf_ecb(),
EVP_bf_ofb()
Blowfish encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
=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-2018 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_camellia.pod b/doc/man3/EVP_camellia.pod
index 75602cf64573..6ad59f84b110 100644
--- a/doc/man3/EVP_camellia.pod
+++ b/doc/man3/EVP_camellia.pod
@@ -1,94 +1,100 @@
=pod
=head1 NAME
EVP_camellia_128_cbc,
EVP_camellia_192_cbc,
EVP_camellia_256_cbc,
EVP_camellia_128_cfb,
EVP_camellia_192_cfb,
EVP_camellia_256_cfb,
EVP_camellia_128_cfb1,
EVP_camellia_192_cfb1,
EVP_camellia_256_cfb1,
EVP_camellia_128_cfb8,
EVP_camellia_192_cfb8,
EVP_camellia_256_cfb8,
+EVP_camellia_128_cfb128,
+EVP_camellia_192_cfb128,
+EVP_camellia_256_cfb128,
EVP_camellia_128_ctr,
EVP_camellia_192_ctr,
EVP_camellia_256_ctr,
EVP_camellia_128_ecb,
EVP_camellia_192_ecb,
EVP_camellia_256_ecb,
EVP_camellia_128_ofb,
EVP_camellia_192_ofb,
EVP_camellia_256_ofb
- EVP Camellia cipher
=head1 SYNOPSIS
=for comment generic
#include <openssl/evp.h>
const EVP_CIPHER *EVP_ciphername(void)
I<EVP_ciphername> is used a placeholder for any of the described cipher
functions, such as I<EVP_camellia_128_cbc>.
=head1 DESCRIPTION
The Camellia encryption algorithm for EVP.
=over 4
=item EVP_camellia_128_cbc(),
EVP_camellia_192_cbc(),
EVP_camellia_256_cbc(),
EVP_camellia_128_cfb(),
EVP_camellia_192_cfb(),
EVP_camellia_256_cfb(),
EVP_camellia_128_cfb1(),
EVP_camellia_192_cfb1(),
EVP_camellia_256_cfb1(),
EVP_camellia_128_cfb8(),
EVP_camellia_192_cfb8(),
EVP_camellia_256_cfb8(),
+EVP_camellia_128_cfb128(),
+EVP_camellia_192_cfb128(),
+EVP_camellia_256_cfb128(),
EVP_camellia_128_ctr(),
EVP_camellia_192_ctr(),
EVP_camellia_256_ctr(),
EVP_camellia_128_ecb(),
EVP_camellia_192_ecb(),
EVP_camellia_256_ecb(),
EVP_camellia_128_ofb(),
EVP_camellia_192_ofb(),
EVP_camellia_256_ofb()
Camellia for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
128-bit shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB and OFB.
=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-2018 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_cast5_cbc.pod b/doc/man3/EVP_cast5_cbc.pod
index 01c38414698b..0be07279259f 100644
--- a/doc/man3/EVP_cast5_cbc.pod
+++ b/doc/man3/EVP_cast5_cbc.pod
@@ -1,59 +1,62 @@
=pod
=head1 NAME
EVP_cast5_cbc,
EVP_cast5_cfb,
+EVP_cast5_cfb64,
EVP_cast5_ecb,
EVP_cast5_ofb
- EVP CAST cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_cast5_cbc(void)
const EVP_CIPHER *EVP_cast5_cfb(void)
+ const EVP_CIPHER *EVP_cast5_cfb64(void)
const EVP_CIPHER *EVP_cast5_ecb(void)
const EVP_CIPHER *EVP_cast5_ofb(void)
=head1 DESCRIPTION
The CAST encryption algorithm for EVP.
This is a variable key length cipher.
=over 4
=item EVP_cast5_cbc(),
EVP_cast5_ecb(),
EVP_cast5_cfb(),
+EVP_cast5_cfb64(),
EVP_cast5_ofb()
CAST encryption algorithm in CBC, ECB, CFB and OFB modes respectively.
=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-2018 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_des.pod b/doc/man3/EVP_des.pod
index 836c399c849e..a05149ff8586 100644
--- a/doc/man3/EVP_des.pod
+++ b/doc/man3/EVP_des.pod
@@ -1,96 +1,106 @@
=pod
=head1 NAME
EVP_des_cbc,
EVP_des_cfb,
EVP_des_cfb1,
EVP_des_cfb8,
+EVP_des_cfb64,
EVP_des_ecb,
+EVP_des_ofb,
EVP_des_ede,
+EVP_des_ede_cbc,
EVP_des_ede_cfb,
+EVP_des_ede_cfb64,
+EVP_des_ede_ecb,
EVP_des_ede_ofb,
-EVP_des_ofb,
EVP_des_ede3,
EVP_des_ede3_cbc,
EVP_des_ede3_cfb,
EVP_des_ede3_cfb1,
EVP_des_ede3_cfb8,
+EVP_des_ede3_cfb64,
+EVP_des_ede3_ecb,
EVP_des_ede3_ofb,
-EVP_des_ede3_wrap,
-EVP_des_ede_cbc
+EVP_des_ede3_wrap
- EVP DES cipher
=head1 SYNOPSIS
=for comment generic
#include <openssl/evp.h>
const EVP_CIPHER *EVP_ciphername(void)
I<EVP_ciphername> is used a placeholder for any of the described cipher
functions, such as I<EVP_des_cbc>.
=head1 DESCRIPTION
The DES encryption algorithm for EVP.
=over 4
=item EVP_des_cbc(),
EVP_des_ecb(),
EVP_des_cfb(),
EVP_des_cfb1(),
EVP_des_cfb8(),
+EVP_des_cfb64(),
EVP_des_ofb()
-DES in CBC, ECB, CFB with 128-bit shift, CFB with 1-bit shift, CFB with 8-bit
-shift and OFB modes respectively.
+DES in CBC, ECB, CFB with 64-bit shift, CFB with 1-bit shift, CFB with 8-bit
+shift and OFB modes.
=item EVP_des_ede(),
EVP_des_ede_cbc(),
-EVP_des_ede_ofb(),
-EVP_des_ede_cfb()
+EVP_des_ede_cfb(),
+EVP_des_ede_cfb64(),
+EVP_des_ede_ecb(),
+EVP_des_ede_ofb()
-Two key triple DES in ECB, CBC, CFB and OFB modes respectively.
+Two key triple DES in ECB, CBC, CFB with 64-bit shift and OFB modes.
=item EVP_des_ede3(),
EVP_des_ede3_cbc(),
EVP_des_ede3_cfb(),
EVP_des_ede3_cfb1(),
EVP_des_ede3_cfb8(),
+EVP_des_ede3_cfb64(),
+EVP_des_ede3_ecb(),
EVP_des_ede3_ofb()
-Three-key triple DES in ECB, CBC, CFB with 128-bit shift, CFB with 1-bit shift,
-CFB with 8-bit shift and OFB modes respectively.
+Three-key triple DES in ECB, CBC, CFB with 64-bit shift, CFB with 1-bit shift,
+CFB with 8-bit shift and OFB modes.
=item EVP_des_ede3_wrap()
Triple-DES key wrap according to RFC 3217 Section 3.
=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-2018 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_idea_cbc.pod b/doc/man3/EVP_idea_cbc.pod
index ace79885e9a3..14dcc903b525 100644
--- a/doc/man3/EVP_idea_cbc.pod
+++ b/doc/man3/EVP_idea_cbc.pod
@@ -1,57 +1,60 @@
=pod
=head1 NAME
EVP_idea_cbc,
EVP_idea_cfb,
+EVP_idea_cfb64,
EVP_idea_ecb,
EVP_idea_ofb
- EVP IDEA cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_idea_cbc(void)
const EVP_CIPHER *EVP_idea_cfb(void)
+ const EVP_CIPHER *EVP_idea_cfb64(void)
const EVP_CIPHER *EVP_idea_ecb(void)
const EVP_CIPHER *EVP_idea_ofb(void)
=head1 DESCRIPTION
The IDEA encryption algorithm for EVP.
=over 4
=item EVP_idea_cbc(),
EVP_idea_cfb(),
+EVP_idea_cfb64(),
EVP_idea_ecb(),
EVP_idea_ofb()
The IDEA encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
=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-2018 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_md5.pod b/doc/man3/EVP_md5.pod
index 8101143b54ec..725fcbf5e227 100644
--- a/doc/man3/EVP_md5.pod
+++ b/doc/man3/EVP_md5.pod
@@ -1,63 +1,65 @@
=pod
=head1 NAME
-EVP_md5
+EVP_md5,
+EVP_md5_sha1
- MD5 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_md5(void);
+ const EVP_MD *EVP_md5_sha1(void);
=head1 DESCRIPTION
MD5 is a cryptographic hash function standardized in RFC 1321 and designed by
Ronald Rivest.
The CMU Software Engineering Institute considers MD5 unsuitable for further
use since its security has been severely compromised.
=over 4
=item EVP_md5()
The MD5 algorithm which produces a 128-bit output from a given input.
=item EVP_md5_sha1()
A hash algorithm of SSL v3 that combines MD5 with SHA-1 as decirbed in RFC
6101.
WARNING: this algorithm is not intended for non-SSL usage.
=back
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
IETF RFC 1321.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
Copyright 2017-2018 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_rc2_cbc.pod b/doc/man3/EVP_rc2_cbc.pod
index 0958e930537e..79769b82635a 100644
--- a/doc/man3/EVP_rc2_cbc.pod
+++ b/doc/man3/EVP_rc2_cbc.pod
@@ -1,73 +1,76 @@
=pod
=head1 NAME
EVP_rc2_cbc,
EVP_rc2_cfb,
+EVP_rc2_cfb64,
EVP_rc2_ecb,
EVP_rc2_ofb,
EVP_rc2_40_cbc,
EVP_rc2_64_cbc
- EVP RC2 cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_rc2_cbc(void)
const EVP_CIPHER *EVP_rc2_cfb(void)
+ const EVP_CIPHER *EVP_rc2_cfb64(void)
const EVP_CIPHER *EVP_rc2_ecb(void)
const EVP_CIPHER *EVP_rc2_ofb(void)
const EVP_CIPHER *EVP_rc2_40_cbc(void)
const EVP_CIPHER *EVP_rc2_64_cbc(void)
=head1 DESCRIPTION
The RC2 encryption algorithm for EVP.
=over 4
=item EVP_rc2_cbc(),
EVP_rc2_cfb(),
+EVP_rc2_cfb64(),
EVP_rc2_ecb(),
EVP_rc2_ofb()
RC2 encryption algorithm in CBC, CFB, ECB and OFB modes respectively. This is a
variable key length cipher with an additional parameter called "effective key
bits" or "effective key length". By default both are set to 128 bits.
=item EVP_rc2_40_cbc(),
EVP_rc2_64_cbc()
RC2 algorithm in CBC mode with a default key length and effective key length of
40 and 64 bits.
WARNING: these functions are obsolete. Their usage should be replaced with the
EVP_rc2_cbc(), EVP_CIPHER_CTX_set_key_length() and EVP_CIPHER_CTX_ctrl()
functions to set the key length and effective key length.
=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-2018 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_rc5_32_12_16_cbc.pod b/doc/man3/EVP_rc5_32_12_16_cbc.pod
index 56175e99c44b..442a114ea9ce 100644
--- a/doc/man3/EVP_rc5_32_12_16_cbc.pod
+++ b/doc/man3/EVP_rc5_32_12_16_cbc.pod
@@ -1,64 +1,67 @@
=pod
=head1 NAME
EVP_rc5_32_12_16_cbc,
EVP_rc5_32_12_16_cfb,
+EVP_rc5_32_12_16_cfb64,
EVP_rc5_32_12_16_ecb,
EVP_rc5_32_12_16_ofb
- EVP RC5 cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void)
const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void)
+ const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void)
const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void)
const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void)
=head1 DESCRIPTION
The RC5 encryption algorithm for EVP.
=over 4
=item EVP_rc5_32_12_16_cbc(),
EVP_rc5_32_12_16_cfb(),
+EVP_rc5_32_12_16_cfb64(),
EVP_rc5_32_12_16_ecb(),
EVP_rc5_32_12_16_ofb()
RC5 encryption algorithm in CBC, CFB, ECB and OFB modes respectively. This is a
variable key length cipher with an additional "number of rounds" parameter. By
default the key length is set to 128 bits and 12 rounds.
=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 BUGS
Currently the number of rounds in RC5 can only be set to 8, 12 or 16.
This is a limitation of the current RC5 code rather than the EVP interface.
=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-2018 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_seed_cbc.pod b/doc/man3/EVP_seed_cbc.pod
index e9f1f695a915..0d2329510d5e 100644
--- a/doc/man3/EVP_seed_cbc.pod
+++ b/doc/man3/EVP_seed_cbc.pod
@@ -1,59 +1,62 @@
=pod
=head1 NAME
EVP_seed_cbc,
EVP_seed_cfb,
+EVP_seed_cfb128,
EVP_seed_ecb,
EVP_seed_ofb
- EVP SEED cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_seed_cbc(void)
const EVP_CIPHER *EVP_seed_cfb(void)
+ const EVP_CIPHER *EVP_seed_cfb128(void)
const EVP_CIPHER *EVP_seed_ecb(void)
const EVP_CIPHER *EVP_seed_ofb(void)
=head1 DESCRIPTION
The SEED encryption algorithm for EVP.
All modes below use a key length of 128 bits and acts on blocks of 128-bits.
=over 4
=item EVP_seed_cbc(),
EVP_seed_cfb(),
+EVP_seed_cfb128(),
EVP_seed_ecb(),
EVP_seed_ofb()
The SEED encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
=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-2018 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_sm4_cbc.pod b/doc/man3/EVP_sm4_cbc.pod
index 4e0240919836..ecd51f09d41f 100644
--- a/doc/man3/EVP_sm4_cbc.pod
+++ b/doc/man3/EVP_sm4_cbc.pod
@@ -1,64 +1,67 @@
=pod
=head1 NAME
EVP_sm4_cbc,
EVP_sm4_ecb,
EVP_sm4_cfb,
+EVP_sm4_cfb128,
EVP_sm4_ofb,
EVP_sm4_ctr
- EVP SM4 cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_sm4_cbc(void);
const EVP_CIPHER *EVP_sm4_ecb(void);
const EVP_CIPHER *EVP_sm4_cfb(void);
+ const EVP_CIPHER *EVP_sm4_cfb128(void);
const EVP_CIPHER *EVP_sm4_ofb(void);
const EVP_CIPHER *EVP_sm4_ctr(void);
=head1 DESCRIPTION
The SM4 blockcipher (GB/T 32907-2016) for EVP.
All modes below use a key length of 128 bits and acts on blocks of 128 bits.
=over 4
=item EVP_sm4_cbc(),
EVP_sm4_ecb(),
EVP_sm4_cfb(),
+EVP_sm4_cfb128(),
EVP_sm4_ofb(),
EVP_sm4_ctr()
The SM4 blockcipher with a 128-bit key in CBC, ECB, CFB, OFB and CTR modes
respectively.
=back
=head1 RETURN VALUES
These functions return a 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-2018 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2017 Ribose Inc. 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/OPENSSL_VERSION_NUMBER.pod b/doc/man3/OPENSSL_VERSION_NUMBER.pod
index 6eca1134b161..55a55c706a51 100644
--- a/doc/man3/OPENSSL_VERSION_NUMBER.pod
+++ b/doc/man3/OPENSSL_VERSION_NUMBER.pod
@@ -1,108 +1,113 @@
=pod
=head1 NAME
-OPENSSL_VERSION_NUMBER, OpenSSL_version,
+OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT, OpenSSL_version,
OpenSSL_version_num - get OpenSSL version number
=head1 SYNOPSIS
#include <openssl/opensslv.h>
#define OPENSSL_VERSION_NUMBER 0xnnnnnnnnnL
+ #define OPENSSL_VERSION_TEXT "OpenSSL x.y.z xx XXX xxxx"
#include <openssl/crypto.h>
unsigned long OpenSSL_version_num();
const char *OpenSSL_version(int t);
=head1 DESCRIPTION
OPENSSL_VERSION_NUMBER is a 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.
for example
0x000906000 == 0.9.6 dev
0x000906023 == 0.9.6b beta 3
0x00090605f == 0.9.6e release
Versions prior to 0.9.3 have identifiers E<lt> 0x0930.
Versions between 0.9.3 and 0.9.5 had a version identifier with this
interpretation:
MMNNFFRBB major minor fix final beta/patch
for example
0x000904100 == 0.9.4 release
0x000905000 == 0.9.5 dev
Version 0.9.5a had an interim interpretation that is like the current one,
except the patch level got the highest bit set, to keep continuity. The
number was therefore 0x0090581f.
+OPENSSL_VERSION_TEXT is the text variant of the version number and the
+release date. For example,
+"OpenSSL 1.0.1a 15 Oct 2015".
+
OpenSSL_version_num() returns the version number.
OpenSSL_version() returns different strings depending on B<t>:
=over 4
=item OPENSSL_VERSION
The text variant of the version number and the release date. For example,
"OpenSSL 1.0.1a 15 Oct 2015".
=item OPENSSL_CFLAGS
The compiler flags set for the compilation process in the form
"compiler: ..." if available or "compiler: information not available"
otherwise.
=item OPENSSL_BUILT_ON
The date of the build process in the form "built on: ..." if available
or "built on: date not available" otherwise.
=item OPENSSL_PLATFORM
The "Configure" target of the library build in the form "platform: ..."
if available or "platform: information not available" otherwise.
=item OPENSSL_DIR
The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "...""
if available or "OPENSSLDIR: N/A" otherwise.
=item OPENSSL_ENGINES_DIR
The "ENGINESDIR" setting of the library build in the form "ENGINESDIR: "...""
if available or "ENGINESDIR: N/A" otherwise.
=back
For an unknown B<t>, the text "not available" is returned.
=head1 RETURN VALUES
OpenSSL_version_num() returns the version number.
OpenSSL_version() returns requested version strings.
=head1 SEE ALSO
L<crypto(7)>
=head1 COPYRIGHT
Copyright 2000-2018 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_meth_new.pod b/doc/man3/RSA_meth_new.pod
index 69ba9dfc5ac3..f21095156c0f 100644
--- a/doc/man3/RSA_meth_new.pod
+++ b/doc/man3/RSA_meth_new.pod
@@ -1,262 +1,262 @@
=pod
=head1 NAME
RSA_meth_get0_app_data, RSA_meth_set0_app_data,
RSA_meth_new, RSA_meth_free, RSA_meth_dup, RSA_meth_get0_name,
RSA_meth_set1_name, RSA_meth_get_flags, RSA_meth_set_flags,
RSA_meth_get_pub_enc,
RSA_meth_set_pub_enc, RSA_meth_get_pub_dec, RSA_meth_set_pub_dec,
RSA_meth_get_priv_enc, RSA_meth_set_priv_enc, RSA_meth_get_priv_dec,
RSA_meth_set_priv_dec, RSA_meth_get_mod_exp, RSA_meth_set_mod_exp,
RSA_meth_get_bn_mod_exp, RSA_meth_set_bn_mod_exp, RSA_meth_get_init,
RSA_meth_set_init, RSA_meth_get_finish, RSA_meth_set_finish,
RSA_meth_get_sign, RSA_meth_set_sign, RSA_meth_get_verify,
RSA_meth_set_verify, RSA_meth_get_keygen, RSA_meth_set_keygen,
RSA_meth_get_multi_prime_keygen, RSA_meth_set_multi_prime_keygen
- Routines to build up RSA methods
=head1 SYNOPSIS
#include <openssl/rsa.h>
RSA_METHOD *RSA_meth_new(const char *name, int flags);
void RSA_meth_free(RSA_METHOD *meth);
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
const char *RSA_meth_get0_name(const RSA_METHOD *meth);
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
int RSA_meth_get_flags(const RSA_METHOD *meth);
int RSA_meth_set_flags(RSA_METHOD *meth, int flags);
void *RSA_meth_get0_app_data(const RSA_METHOD *meth);
int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data);
int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth))(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_meth_set_pub_enc(RSA_METHOD *rsa,
int (*pub_enc)(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_meth_set_pub_dec(RSA_METHOD *rsa,
int (*pub_dec)(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth))(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding);
int RSA_meth_set_priv_enc(RSA_METHOD *rsa,
int (*priv_enc)(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding));
int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth))(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding);
int RSA_meth_set_priv_dec(RSA_METHOD *rsa,
int (*priv_dec)(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding));
/* Can be null */
- int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth))(BIGNUM *r0, const BIGNUM *I,
+ int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth))(BIGNUM *r0, const BIGNUM *i,
RSA *rsa, BN_CTX *ctx);
int RSA_meth_set_mod_exp(RSA_METHOD *rsa,
- int (*mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+ int (*mod_exp)(BIGNUM *r0, const BIGNUM *i, RSA *rsa,
BN_CTX *ctx));
/* Can be null */
int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth))(BIGNUM *r, const BIGNUM *a,
const BIGNUM *p, const BIGNUM *m,
BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int RSA_meth_set_bn_mod_exp(RSA_METHOD *rsa,
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a,
const BIGNUM *p, const BIGNUM *m,
BN_CTX *ctx, BN_MONT_CTX *m_ctx));
/* called at new */
int (*RSA_meth_get_init(const RSA_METHOD *meth) (RSA *rsa);
int RSA_meth_set_init(RSA_METHOD *rsa, int (*init (RSA *rsa));
/* called at free */
int (*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa);
int RSA_meth_set_finish(RSA_METHOD *rsa, int (*finish)(RSA *rsa));
int (*RSA_meth_get_sign(const RSA_METHOD *meth))(int type, const unsigned char *m,
unsigned int m_length,
unsigned char *sigret,
unsigned int *siglen, const RSA *rsa);
int RSA_meth_set_sign(RSA_METHOD *rsa,
int (*sign)(int type, const unsigned char *m,
unsigned int m_length, unsigned char *sigret,
unsigned int *siglen, const RSA *rsa));
int (*RSA_meth_get_verify(const RSA_METHOD *meth))(int dtype, const unsigned char *m,
unsigned int m_length,
const unsigned char *sigbuf,
unsigned int siglen, const RSA *rsa);
int RSA_meth_set_verify(RSA_METHOD *rsa,
int (*verify)(int dtype, const unsigned char *m,
unsigned int m_length,
const unsigned char *sigbuf,
unsigned int siglen, const RSA *rsa));
int (*RSA_meth_get_keygen(const RSA_METHOD *meth))(RSA *rsa, int bits, BIGNUM *e,
BN_GENCB *cb);
int RSA_meth_set_keygen(RSA_METHOD *rsa,
int (*keygen)(RSA *rsa, int bits, BIGNUM *e,
BN_GENCB *cb));
int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth))(RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb);
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb));
=head1 DESCRIPTION
The B<RSA_METHOD> type is a structure used for the provision of custom
RSA implementations. It provides a set of functions used by OpenSSL
for the implementation of the various RSA capabilities. See the L<rsa>
page for more information.
RSA_meth_new() creates a new B<RSA_METHOD> structure. It should be
given a unique B<name> and a set of B<flags>. The B<name> should be a
NULL terminated string, which will be duplicated and stored in the
B<RSA_METHOD> object. It is the callers responsibility to free the
original string. The flags will be used during the construction of a
new B<RSA> object based on this B<RSA_METHOD>. Any new B<RSA> object
will have those flags set by default.
RSA_meth_dup() creates a duplicate copy of the B<RSA_METHOD> object
passed as a parameter. This might be useful for creating a new
B<RSA_METHOD> based on an existing one, but with some differences.
RSA_meth_free() destroys an B<RSA_METHOD> structure and frees up any
memory associated with it.
RSA_meth_get0_name() will return a pointer to the name of this
RSA_METHOD. This is a pointer to the internal name string and so
should not be freed by the caller. RSA_meth_set1_name() sets the name
of the RSA_METHOD to B<name>. The string is duplicated and the copy is
stored in the RSA_METHOD structure, so the caller remains responsible
for freeing the memory associated with the name.
RSA_meth_get_flags() returns the current value of the flags associated
with this RSA_METHOD. RSA_meth_set_flags() provides the ability to set
these flags.
The functions RSA_meth_get0_app_data() and RSA_meth_set0_app_data()
provide the ability to associate implementation specific data with the
RSA_METHOD. It is the application's responsibility to free this data
before the RSA_METHOD is freed via a call to RSA_meth_free().
RSA_meth_get_sign() and RSA_meth_set_sign() get and set the function
used for creating an RSA signature respectively. This function will be
called in response to the application calling RSA_sign(). The
parameters for the function have the same meaning as for RSA_sign().
RSA_meth_get_verify() and RSA_meth_set_verify() get and set the
function used for verifying an RSA signature respectively. This
function will be called in response to the application calling
RSA_verify(). The parameters for the function have the same meaning as
for RSA_verify().
RSA_meth_get_mod_exp() and RSA_meth_set_mod_exp() get and set the
function used for CRT computations.
RSA_meth_get_bn_mod_exp() and RSA_meth_set_bn_mod_exp() get and set
the function used for CRT computations, specifically the following
value:
r = a ^ p mod m
Both the mod_exp() and bn_mod_exp() functions are called by the
default OpenSSL method during encryption, decryption, signing and
verification.
RSA_meth_get_init() and RSA_meth_set_init() get and set the function
used for creating a new RSA instance respectively. This function will
be called in response to the application calling RSA_new() (if the
current default RSA_METHOD is this one) or RSA_new_method(). The
RSA_new() and RSA_new_method() functions will allocate the memory for
the new RSA object, and a pointer to this newly allocated structure
will be passed as a parameter to the function. This function may be
NULL.
RSA_meth_get_finish() and RSA_meth_set_finish() get and set the
function used for destroying an instance of an RSA object respectively.
This function will be called in response to the application calling
RSA_free(). A pointer to the RSA to be destroyed is passed as a
parameter. The destroy function should be used for RSA implementation
specific clean up. The memory for the RSA itself should not be freed
by this function. This function may be NULL.
RSA_meth_get_keygen() and RSA_meth_set_keygen() get and set the
function used for generating a new RSA key pair respectively. This
function will be called in response to the application calling
RSA_generate_key_ex(). The parameter for the function has the same
meaning as for RSA_generate_key_ex().
RSA_meth_get_multi_prime_keygen() and RSA_meth_set_multi_prime_keygen() get
and set the function used for generating a new multi-prime RSA key pair
respectively. This function will be called in response to the application calling
RSA_generate_multi_prime_key(). The parameter for the function has the same
meaning as for RSA_generate_multi_prime_key().
RSA_meth_get_pub_enc(), RSA_meth_set_pub_enc(),
RSA_meth_get_pub_dec(), RSA_meth_set_pub_dec(),
RSA_meth_get_priv_enc(), RSA_meth_set_priv_enc(),
RSA_meth_get_priv_dec(), RSA_meth_set_priv_dec() get and set the
functions used for public and private key encryption and decryption.
These functions will be called in response to the application calling
RSA_public_encrypt(), RSA_private_decrypt(), RSA_private_encrypt() and
RSA_public_decrypt() and take the same parameters as those.
=head1 RETURN VALUES
RSA_meth_new() and RSA_meth_dup() return the newly allocated
RSA_METHOD object or NULL on failure.
RSA_meth_get0_name() and RSA_meth_get_flags() return the name and
flags associated with the RSA_METHOD respectively.
All other RSA_meth_get_*() functions return the appropriate function
pointer that has been set in the RSA_METHOD, or NULL if no such
pointer has yet been set.
RSA_meth_set1_name and all RSA_meth_set_*() functions return 1 on
success or 0 on failure.
=head1 SEE ALSO
L<RSA_new(3)>, L<RSA_generate_key_ex(3)>, L<RSA_sign(3)>,
L<RSA_set_method(3)>, L<RSA_size(3)>, L<RSA_get0_key(3)>,
L<RSA_generate_multi_prime_key(3)>
=head1 HISTORY
RSA_meth_get_multi_prime_keygen() and RSA_meth_set_multi_prime_keygen() were
added in OpenSSL 1.1.1.
Other functions described here were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
Copyright 2016-2018 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_set0_CA_list.pod b/doc/man3/SSL_CTX_set0_CA_list.pod
index 618bd73e0420..d7ed89775b2e 100644
--- a/doc/man3/SSL_CTX_set0_CA_list.pod
+++ b/doc/man3/SSL_CTX_set0_CA_list.pod
@@ -1,92 +1,188 @@
=pod
=head1 NAME
-SSL_set0_CA_list, SSL_CTX_set0_CA_list, SSL_get0_CA_list,
-SSL_CTX_get0_CA_list, SSL_add1_to_CA_list, SSL_CTX_add1_to_CA_list,
-SSL_get0_peer_CA_list - get or set CA list
+SSL_CTX_set_client_CA_list,
+SSL_set_client_CA_list,
+SSL_get_client_CA_list,
+SSL_CTX_get_client_CA_list,
+SSL_CTX_add_client_CA,
+SSL_add_client_CA,
+SSL_set0_CA_list,
+SSL_CTX_set0_CA_list,
+SSL_get0_CA_list,
+SSL_CTX_get0_CA_list,
+SSL_add1_to_CA_list,
+SSL_CTX_add1_to_CA_list,
+SSL_get0_peer_CA_list
+- get or set CA list
=head1 SYNOPSIS
#include <openssl/ssl.h>
+ void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *list);
+ void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *list);
+ STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
+ STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx);
+ int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *cacert);
+ int SSL_add_client_CA(SSL *ssl, X509 *cacert);
+
void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx);
const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s);
int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x);
int SSL_add1_to_CA_list(SSL *ssl, const X509 *x);
const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s);
=head1 DESCRIPTION
+The functions described here set and manage the list of CA names that are sent
+between two communicating peers.
+
+For TLS versions 1.2 and earlier the list of CA names is only sent from the
+server to the client when requesting a client certificate. So any list of CA
+names set is never sent from client to server and the list of CA names retrieved
+by SSL_get0_peer_CA_list() is always B<NULL>.
+
+For TLS 1.3 the list of CA names is sent using the B<certificate_authorities>
+extension and may be sent by a client (in the ClientHello message) or by
+a server (when requesting a certificate).
+
+In most cases it is not necessary to set CA names on the client side. The list
+of CA names that are acceptable to the client will be sent in plaintext to the
+server. This has privacy implications and may also have performance implications
+if the list is large. This optional capability was introduced as part of TLSv1.3
+and therefore setting CA names on the client side will have no impact if that
+protocol version has been disabled. Most servers do not need this and so this
+should be avoided unless required.
+
+The "client CA list" functions below only have an effect when called on the
+server side.
+
+SSL_CTX_set_client_CA_list() sets the B<list> of CAs sent to the client when
+requesting a client certificate for B<ctx>. Ownership of B<list> is transferred
+to B<ctx> and it should not be freed by the caller.
+
+SSL_set_client_CA_list() sets the B<list> of CAs sent to the client when
+requesting a client certificate for the chosen B<ssl>, overriding the
+setting valid for B<ssl>'s SSL_CTX object. Ownership of B<list> is transferred
+to B<s> and it should not be freed by the caller.
+
+SSL_CTX_get_client_CA_list() returns the list of client CAs explicitly set for
+B<ctx> using SSL_CTX_set_client_CA_list(). The returned list should not be freed
+by the caller.
+
+SSL_get_client_CA_list() returns the list of client CAs explicitly
+set for B<ssl> using SSL_set_client_CA_list() or B<ssl>'s SSL_CTX object with
+SSL_CTX_set_client_CA_list(), when in server mode. In client mode,
+SSL_get_client_CA_list returns the list of client CAs sent from the server, if
+any. The returned list should not be freed by the caller.
+
+SSL_CTX_add_client_CA() adds the CA name extracted from B<cacert> to the
+list of CAs sent to the client when requesting a client certificate for
+B<ctx>.
+
+SSL_add_client_CA() adds the CA name extracted from B<cacert> to the
+list of CAs sent to the client when requesting a client certificate for
+the chosen B<ssl>, overriding the setting valid for B<ssl>'s SSL_CTX object.
+
+SSL_get0_peer_CA_list() retrieves the list of CA names (if any) the peer
+has sent. This can be called on either the server or the client side. The
+returned list should not be freed by the caller.
+
+The "generic CA list" functions below are very similar to the "client CA
+list" functions except that they have an effect on both the server and client
+sides. The lists of CA names managed are separate - so you cannot (for example)
+set CA names using the "client CA list" functions and then get them using the
+"generic CA list" functions. Where a mix of the two types of functions has been
+used on the server side then the "client CA list" functions take precedence.
+Typically, on the server side, the "client CA list " functions should be used in
+preference. As noted above in most cases it is not necessary to set CA names on
+the client side.
+
SSL_CTX_set0_CA_list() sets the list of CAs to be sent to the peer to
B<name_list>. Ownership of B<name_list> is transferred to B<ctx> and
it should not be freed by the caller.
SSL_set0_CA_list() sets the list of CAs to be sent to the peer to B<name_list>
overriding any list set in the parent B<SSL_CTX> of B<s>. Ownership of
B<name_list> is transferred to B<s> and it should not be freed by the caller.
SSL_CTX_get0_CA_list() retrieves any previously set list of CAs set for
-B<ctx>.
+B<ctx>. The returned list should not be freed by the caller.
-SSL_CTX_get0_CA_list() retrieves any previously set list of CAs set for
-B<s> or if none are set the list from the parent B<SSL_CTX> is retrieved.
+SSL_get0_CA_list() retrieves any previously set list of CAs set for
+B<s> or if none are set the list from the parent B<SSL_CTX> is retrieved. The
+returned list should not be freed by the caller.
SSL_CTX_add1_to_CA_list() appends the CA subject name extracted from B<x> to the
list of CAs sent to peer for B<ctx>.
SSL_add1_to_CA_list() appends the CA subject name extracted from B<x> to the
list of CAs sent to the peer for B<s>, overriding the setting in the parent
B<SSL_CTX>.
-SSL_get0_peer_CA_list() retrieves the list of CA names (if any) the peer
-has sent.
-
=head1 NOTES
-These functions are generalised versions of the client authentication
-CA list functions such as L<SSL_CTX_set_client_CA_list(3)>.
+When a TLS/SSL server requests a client certificate (see
+B<SSL_CTX_set_verify(3)>), it sends a list of CAs, for which it will accept
+certificates, to the client.
-For TLS versions before 1.3 the list of CA names is only sent from the server
-to client when requesting a client certificate. So any list of CA names set
-is never sent from client to server and the list of CA names retrieved by
-SSL_get0_peer_CA_list() is always B<NULL>.
+This list must explicitly be set using SSL_CTX_set_client_CA_list() or
+SSL_CTX_set0_CA_list() for B<ctx> and SSL_set_client_CA_list() or
+SSL_set0_CA_list() for the specific B<ssl>. The list specified
+overrides the previous setting. The CAs listed do not become trusted (B<list>
+only contains the names, not the complete certificates); use
+L<SSL_CTX_load_verify_locations(3)> to additionally load them for verification.
-For TLS 1.3 the list of CA names is sent using the B<certificate_authorities>
-extension and will be sent by a client (in the ClientHello message) or by
-a server (when requesting a certificate).
+If the list of acceptable CAs is compiled in a file, the
+L<SSL_load_client_CA_file(3)> function can be used to help to import the
+necessary data.
+
+SSL_CTX_add_client_CA(), SSL_CTX_add1_to_CA_list(), SSL_add_client_CA() and
+SSL_add1_to_CA_list() can be used to add additional items the list of CAs. If no
+list was specified before using SSL_CTX_set_client_CA_list(),
+SSL_CTX_set0_CA_list(), SSL_set_client_CA_list() or SSL_set0_CA_list(), a
+new CA list for B<ctx> or B<ssl> (as appropriate) is opened.
=head1 RETURN VALUES
-SSL_CTX_set0_CA_list() and SSL_set0_CA_list() do not return a value.
+SSL_CTX_set_client_CA_list(), SSL_set_client_CA_list(),
+SSL_CTX_set_client_CA_list(), SSL_set_client_CA_list(), SSL_CTX_set0_CA_list()
+and SSL_set0_CA_list() do not return a value.
-SSL_CTX_get0_CA_list() and SSL_get0_CA_list() return a stack of CA names
-or B<NULL> is no CA names are set.
+SSL_CTX_get_client_CA_list(), SSL_get_client_CA_list(), SSL_CTX_get0_CA_list()
+and SSL_get0_CA_list() return a stack of CA names or B<NULL> is no CA names are
+set.
-SSL_CTX_add1_to_CA_list() and SSL_add1_to_CA_list() return 1 for success and 0
-for failure.
+SSL_CTX_add_client_CA(),SSL_add_client_CA(), SSL_CTX_add1_to_CA_list() and
+SSL_add1_to_CA_list() return 1 for success and 0 for failure.
SSL_get0_peer_CA_list() returns a stack of CA names sent by the peer or
B<NULL> or an empty stack if no list was sent.
+=head1 EXAMPLES
+
+Scan all certificates in B<CAfile> and list them as acceptable CAs:
+
+ SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile));
+
=head1 SEE ALSO
L<ssl(7)>,
-L<SSL_CTX_set_client_CA_list(3)>,
-L<SSL_get_client_CA_list(3)>,
L<SSL_load_client_CA_file(3)>,
L<SSL_CTX_load_verify_locations(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2018 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_curves.pod b/doc/man3/SSL_CTX_set1_curves.pod
index a250f20c2206..7dca0e0161d9 100644
--- a/doc/man3/SSL_CTX_set1_curves.pod
+++ b/doc/man3/SSL_CTX_set1_curves.pod
@@ -1,109 +1,112 @@
=pod
=head1 NAME
SSL_CTX_set1_groups, SSL_CTX_set1_groups_list, SSL_set1_groups,
SSL_set1_groups_list, SSL_get1_groups, SSL_get_shared_group,
SSL_CTX_set1_curves, SSL_CTX_set1_curves_list, SSL_set1_curves,
SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve
- EC supported curve functions
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_CTX_set1_groups(SSL_CTX *ctx, int *glist, int glistlen);
int SSL_CTX_set1_groups_list(SSL_CTX *ctx, char *list);
int SSL_set1_groups(SSL *ssl, int *glist, int glistlen);
int SSL_set1_groups_list(SSL *ssl, char *list);
int SSL_get1_groups(SSL *ssl, int *groups);
int SSL_get_shared_group(SSL *s, int n);
int SSL_CTX_set1_curves(SSL_CTX *ctx, int *clist, int clistlen);
int SSL_CTX_set1_curves_list(SSL_CTX *ctx, char *list);
int SSL_set1_curves(SSL *ssl, int *clist, int clistlen);
int SSL_set1_curves_list(SSL *ssl, char *list);
int SSL_get1_curves(SSL *ssl, int *curves);
int SSL_get_shared_curve(SSL *s, int n);
=head1 DESCRIPTION
+For all of the functions below that set the supported groups there must be at
+least one group in the list.
+
SSL_CTX_set1_groups() sets the supported groups for B<ctx> to B<glistlen>
groups in the array B<glist>. The array consist of all NIDs of groups in
preference order. For a TLS client the groups are used directly in the
supported groups extension. For a TLS server the groups are used to
determine the set of shared groups.
SSL_CTX_set1_groups_list() sets the supported groups for B<ctx> to
string B<list>. The string is a colon separated list of group NIDs or
names, for example "P-521:P-384:P-256".
SSL_set1_groups() and SSL_set1_groups_list() are similar except they set
supported groups for the SSL structure B<ssl>.
SSL_get1_groups() returns the set of supported groups sent by a client
in the supported groups extension. It returns the total number of
supported groups. The B<groups> parameter can be B<NULL> to simply
return the number of groups for memory allocation purposes. The
B<groups> array is in the form of a set of group NIDs in preference
order. It can return zero if the client did not send a supported groups
extension.
SSL_get_shared_group() returns shared group B<n> for a server-side
SSL B<ssl>. If B<n> is -1 then the total number of shared groups is
returned, which may be zero. Other than for diagnostic purposes,
most applications will only be interested in the first shared group
so B<n> is normally set to zero. If the value B<n> is out of range,
NID_undef is returned.
All these functions are implemented as macros.
The curve functions are synonyms for the equivalently named group functions and
are identical in every respect. They exist because, prior to TLS1.3, there was
only the concept of supported curves. In TLS1.3 this was renamed to supported
groups, and extended to include Diffie Hellman groups. The group functions
should be used in preference.
=head1 NOTES
If an application wishes to make use of several of these functions for
configuration purposes either on a command line or in a file it should
consider using the SSL_CONF interface instead of manually parsing options.
=head1 RETURN VALUES
SSL_CTX_set1_groups(), SSL_CTX_set1_groups_list(), SSL_set1_groups() and
SSL_set1_groups_list(), return 1 for success and 0 for failure.
SSL_get1_groups() returns the number of groups, which may be zero.
SSL_get_shared_group() returns the NID of shared group B<n> or NID_undef if there
is no shared group B<n>; or the total number of shared groups if B<n>
is -1.
When called on a client B<ssl>, SSL_get_shared_group() has no meaning and
returns -1.
=head1 SEE ALSO
L<SSL_CTX_add_extra_chain_cert(3)>
=head1 HISTORY
The curve functions were first added to OpenSSL 1.0.2. The equivalent group
functions were first added to OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2018 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_CA_list.pod b/doc/man3/SSL_CTX_set_client_CA_list.pod
deleted file mode 100644
index 76fd65e6fcaa..000000000000
--- a/doc/man3/SSL_CTX_set_client_CA_list.pod
+++ /dev/null
@@ -1,103 +0,0 @@
-=pod
-
-=head1 NAME
-
-SSL_CTX_set_client_CA_list, SSL_set_client_CA_list, SSL_CTX_add_client_CA,
-SSL_add_client_CA - set list of CAs sent to the client when requesting a
-client certificate
-
-=head1 SYNOPSIS
-
- #include <openssl/ssl.h>
-
- void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *list);
- void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *list);
- int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *cacert);
- int SSL_add_client_CA(SSL *ssl, X509 *cacert);
-
-=head1 DESCRIPTION
-
-SSL_CTX_set_client_CA_list() sets the B<list> of CAs sent to the client when
-requesting a client certificate for B<ctx>.
-
-SSL_set_client_CA_list() sets the B<list> of CAs sent to the client when
-requesting a client certificate for the chosen B<ssl>, overriding the
-setting valid for B<ssl>'s SSL_CTX object.
-
-SSL_CTX_add_client_CA() adds the CA name extracted from B<cacert> to the
-list of CAs sent to the client when requesting a client certificate for
-B<ctx>.
-
-SSL_add_client_CA() adds the CA name extracted from B<cacert> to the
-list of CAs sent to the client when requesting a client certificate for
-the chosen B<ssl>, overriding the setting valid for B<ssl>'s SSL_CTX object.
-
-=head1 NOTES
-
-When a TLS/SSL server requests a client certificate (see
-B<SSL_CTX_set_verify(3)>), it sends a list of CAs, for which
-it will accept certificates, to the client.
-
-This list must explicitly be set using SSL_CTX_set_client_CA_list() for
-B<ctx> and SSL_set_client_CA_list() for the specific B<ssl>. The list
-specified overrides the previous setting. The CAs listed do not become
-trusted (B<list> only contains the names, not the complete certificates); use
-L<SSL_CTX_load_verify_locations(3)>
-to additionally load them for verification.
-
-If the list of acceptable CAs is compiled in a file, the
-L<SSL_load_client_CA_file(3)>
-function can be used to help importing the necessary data.
-
-SSL_CTX_add_client_CA() and SSL_add_client_CA() can be used to add additional
-items the list of client CAs. If no list was specified before using
-SSL_CTX_set_client_CA_list() or SSL_set_client_CA_list(), a new client
-CA list for B<ctx> or B<ssl> (as appropriate) is opened.
-
-These functions are only useful for TLS/SSL servers.
-
-=head1 RETURN VALUES
-
-SSL_CTX_set_client_CA_list() and SSL_set_client_CA_list() do not return
-diagnostic information.
-
-SSL_CTX_add_client_CA() and SSL_add_client_CA() have the following return
-values:
-
-=over 4
-
-=item Z<>0
-
-A failure while manipulating the STACK_OF(X509_NAME) object occurred or
-the X509_NAME could not be extracted from B<cacert>. Check the error stack
-to find out the reason.
-
-=item Z<>1
-
-The operation succeeded.
-
-=back
-
-=head1 EXAMPLES
-
-Scan all certificates in B<CAfile> and list them as acceptable CAs:
-
- SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile));
-
-=head1 SEE ALSO
-
-L<ssl(7)>,
-L<SSL_get_client_CA_list(3)>,
-L<SSL_load_client_CA_file(3)>,
-L<SSL_CTX_load_verify_locations(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2016 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_quiet_shutdown.pod b/doc/man3/SSL_CTX_set_quiet_shutdown.pod
index 99922eb5bf8d..8ed9315df5c4 100644
--- a/doc/man3/SSL_CTX_set_quiet_shutdown.pod
+++ b/doc/man3/SSL_CTX_set_quiet_shutdown.pod
@@ -1,72 +1,72 @@
=pod
=head1 NAME
SSL_CTX_set_quiet_shutdown, SSL_CTX_get_quiet_shutdown, SSL_set_quiet_shutdown, SSL_get_quiet_shutdown - manipulate shutdown behaviour
=head1 SYNOPSIS
#include <openssl/ssl.h>
void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
void SSL_set_quiet_shutdown(SSL *ssl, int mode);
int SSL_get_quiet_shutdown(const SSL *ssl);
=head1 DESCRIPTION
SSL_CTX_set_quiet_shutdown() sets the "quiet shutdown" flag for B<ctx> to be
B<mode>. SSL objects created from B<ctx> inherit the B<mode> valid at the time
L<SSL_new(3)> is called. B<mode> may be 0 or 1.
SSL_CTX_get_quiet_shutdown() returns the "quiet shutdown" setting of B<ctx>.
SSL_set_quiet_shutdown() sets the "quiet shutdown" flag for B<ssl> to be
B<mode>. The setting stays valid until B<ssl> is removed with
L<SSL_free(3)> or SSL_set_quiet_shutdown() is called again.
It is not changed when L<SSL_clear(3)> is called.
B<mode> may be 0 or 1.
SSL_get_quiet_shutdown() returns the "quiet shutdown" setting of B<ssl>.
=head1 NOTES
Normally when a SSL connection is finished, the parties must send out
-"close notify" alert messages using L<SSL_shutdown(3)>
+close_notify alert messages using L<SSL_shutdown(3)>
for a clean shutdown.
When setting the "quiet shutdown" flag to 1, L<SSL_shutdown(3)>
will set the internal flags to SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN.
(L<SSL_shutdown(3)> then behaves like
L<SSL_set_shutdown(3)> called with
SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN.)
-The session is thus considered to be shutdown, but no "close notify" alert
+The session is thus considered to be shutdown, but no close_notify alert
is sent to the peer. This behaviour violates the TLS standard.
The default is normal shutdown behaviour as described by the TLS standard.
=head1 RETURN VALUES
SSL_CTX_set_quiet_shutdown() and SSL_set_quiet_shutdown() do not return
diagnostic information.
SSL_CTX_get_quiet_shutdown() and SSL_get_quiet_shutdown return the current
setting.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_shutdown(3)>,
L<SSL_set_shutdown(3)>, L<SSL_new(3)>,
L<SSL_clear(3)>, L<SSL_free(3)>
=head1 COPYRIGHT
-Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2018 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_client_CA_list.pod b/doc/man3/SSL_get_client_CA_list.pod
deleted file mode 100644
index 40c3561efcee..000000000000
--- a/doc/man3/SSL_get_client_CA_list.pod
+++ /dev/null
@@ -1,62 +0,0 @@
-=pod
-
-=head1 NAME
-
-SSL_get_client_CA_list, SSL_CTX_get_client_CA_list - get list of client CAs
-
-=head1 SYNOPSIS
-
- #include <openssl/ssl.h>
-
- STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
- STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx);
-
-=head1 DESCRIPTION
-
-SSL_CTX_get_client_CA_list() returns the list of client CAs explicitly set for
-B<ctx> using L<SSL_CTX_set_client_CA_list(3)>.
-
-SSL_get_client_CA_list() returns the list of client CAs explicitly
-set for B<ssl> using SSL_set_client_CA_list() or B<ssl>'s SSL_CTX object with
-L<SSL_CTX_set_client_CA_list(3)>, when in
-server mode. In client mode, SSL_get_client_CA_list returns the list of
-client CAs sent from the server, if any.
-
-=head1 RETURN VALUES
-
-SSL_CTX_set_client_CA_list() and SSL_set_client_CA_list() do not return
-diagnostic information.
-
-SSL_CTX_add_client_CA() and SSL_add_client_CA() have the following return
-values:
-
-=over 4
-
-=item STACK_OF(X509_NAMES)
-
-List of CA names explicitly set (for B<ctx> or in server mode) or send
-by the server (client mode).
-
-=item NULL
-
-No client CA list was explicitly set (for B<ctx> or in server mode) or
-the server did not send a list of CAs (client mode).
-
-=back
-
-=head1 SEE ALSO
-
-L<ssl(7)>,
-L<SSL_CTX_set_client_CA_list(3)>,
-L<SSL_CTX_set_client_cert_cb(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2016 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 01446a24a1e1..b3ab50568731 100644
--- a/doc/man3/SSL_get_error.pod
+++ b/doc/man3/SSL_get_error.pod
@@ -1,173 +1,173 @@
=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.
+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 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.
This value can also be returned for other errors, check the error queue for
details.
=item SSL_ERROR_SSL
A failure in the SSL library occurred, usually a protocol error. The
OpenSSL error queue contains more information on the error.
=back
=head1 SEE ALSO
L<ssl(7)>
=head1 HISTORY
SSL_ERROR_WANT_ASYNC was added in OpenSSL 1.1.0.
SSL_ERROR_WANT_CLIENT_HELLO_CB was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
Copyright 2000-2018 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_peer_signature_nid.pod b/doc/man3/SSL_get_peer_signature_nid.pod
index ce6ab61f5e11..dbca8cffb920 100644
--- a/doc/man3/SSL_get_peer_signature_nid.pod
+++ b/doc/man3/SSL_get_peer_signature_nid.pod
@@ -1,47 +1,53 @@
=pod
=head1 NAME
-SSL_get_peer_signature_nid, SSL_get_peer_signature_type_nid - get TLS
-message signing types
+SSL_get_peer_signature_nid, SSL_get_peer_signature_type_nid,
+SSL_get_signature_nid, SSL_get_signature_type_nid - get TLS message signing
+types
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_get_peer_signature_nid(SSL *ssl, int *psig_nid);
int SSL_get_peer_signature_type_nid(const SSL *ssl, int *psigtype_nid);
+ int SSL_get_signature_nid(SSL *ssl, int *psig_nid);
+ int SSL_get_signature_type_nid(const SSL *ssl, int *psigtype_nid);
=head1 DESCRIPTION
SSL_get_peer_signature_nid() sets B<*psig_nid> to the NID of the digest used
by the peer to sign TLS messages. It is implemented as a macro.
SSL_get_peer_signature_type_nid() sets B<*psigtype_nid> to the signature
type used by the peer to sign TLS messages. Currently the signature type
is the NID of the public key type used for signing except for PSS signing
where it is B<EVP_PKEY_RSA_PSS>. To differentiate between
B<rsa_pss_rsae_*> and B<rsa_pss_pss_*> signatures, it's necessary to check
the type of public key in the peer's certificate.
+SSL_get_signature_nid() and SSL_get_signature_type_nid() return the equivalent
+information for the local end of the connection.
+
=head1 RETURN VALUES
These functions return 1 for success and 0 for failure. There are several
possible reasons for failure: the cipher suite has no signature (e.g. it
uses RSA key exchange or is anonymous), the TLS version is below 1.2 or
-the functions were called before the peer signed a message.
+the functions were called too early, e.g. before the peer signed a message.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_get_peer_certificate(3)>,
=head1 COPYRIGHT
Copyright 2017-2018 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_peer_tmp_key.pod b/doc/man3/SSL_get_peer_tmp_key.pod
new file mode 100644
index 000000000000..a722a813bff8
--- /dev/null
+++ b/doc/man3/SSL_get_peer_tmp_key.pod
@@ -0,0 +1,53 @@
+=pod
+
+=head1 NAME
+
+SSL_get_peer_tmp_key, SSL_get_server_tmp_key, SSL_get_tmp_key - get information
+about temporary keys used during a handshake
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ long SSL_get_peer_tmp_key(SSL *ssl, EVP_PKEY **key);
+ long SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **key);
+ long SSL_get_tmp_key(SSL *ssl, EVP_PKEY **key);
+
+=head1 DESCRIPTION
+
+SSL_get_peer_tmp_key() returns the temporary key provided by the peer and
+used during key exchange. For example, if ECDHE is in use, then this represents
+the peer's public ECDHE key. On success a pointer to the key is stored in
+B<*key>. It is the caller's responsibility to free this key after use using
+L<EVP_PKEY_free(3)>.
+
+SSL_get_server_tmp_key() is a backwards compatibility alias for
+SSL_get_peer_tmp_key().
+Under that name it worked just on the client side of the connection, its
+behaviour on the server end is release-dependent.
+
+SSL_get_tmp_key() returns the equivalent information for the local
+end of the connection.
+
+=head1 RETURN VALUES
+
+All these functions return 1 on success and 0 otherwise.
+
+=head1 NOTES
+
+This function is implemented as a macro.
+
+=head1 SEE ALSO
+
+L<ssl(7)>, L<EVP_PKEY_free(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2017-2018 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_server_tmp_key.pod b/doc/man3/SSL_get_server_tmp_key.pod
deleted file mode 100644
index fda891b7a837..000000000000
--- a/doc/man3/SSL_get_server_tmp_key.pod
+++ /dev/null
@@ -1,43 +0,0 @@
-=pod
-
-=head1 NAME
-
-SSL_get_server_tmp_key - get information about the server's temporary key used
-during a handshake
-
-=head1 SYNOPSIS
-
- #include <openssl/ssl.h>
-
- long SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **key);
-
-=head1 DESCRIPTION
-
-SSL_get_server_tmp_key() returns the temporary key provided by the server and
-used during key exchange. For example, if ECDHE is in use, then this represents
-the server's public ECDHE key. On success a pointer to the key is stored in
-B<*key>. It is the caller's responsibility to free this key after use using
-L<EVP_PKEY_free(3)>. This function may only be called by the client.
-
-=head1 RETURN VALUES
-
-SSL_get_server_tmp_key() returns 1 on success or 0 otherwise.
-
-=head1 NOTES
-
-This function is implemented as a macro.
-
-=head1 SEE ALSO
-
-L<ssl(7)>, L<EVP_PKEY_free(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2017 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_set_bio.pod b/doc/man3/SSL_set_bio.pod
index 01617521bf52..1fa0d3492600 100644
--- a/doc/man3/SSL_set_bio.pod
+++ b/doc/man3/SSL_set_bio.pod
@@ -1,114 +1,114 @@
=pod
=head1 NAME
SSL_set_bio, SSL_set0_rbio, SSL_set0_wbio - connect the SSL object with a BIO
=head1 SYNOPSIS
#include <openssl/ssl.h>
void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio);
void SSL_set0_rbio(SSL *s, BIO *rbio);
void SSL_set0_wbio(SSL *s, BIO *wbio);
=head1 DESCRIPTION
SSL_set0_rbio() connects the BIO B<rbio> for the read operations of the B<ssl>
object. The SSL engine inherits the behaviour of B<rbio>. If the BIO is
non-blocking then the B<ssl> object will also have non-blocking behaviour. This
function transfers ownership of B<rbio> to B<ssl>. It will be automatically
freed using L<BIO_free_all(3)> when the B<ssl> is freed. On calling this
function, any existing B<rbio> that was previously set will also be freed via a
call to L<BIO_free_all(3)> (this includes the case where the B<rbio> is set to
the same value as previously).
SSL_set0_wbio() works in the same as SSL_set0_rbio() except that it connects
the BIO B<wbio> for the write operations of the B<ssl> object. Note that if the
rbio and wbio are the same then SSL_set0_rbio() and SSL_set0_wbio() each take
ownership of one reference. Therefore it may be necessary to increment the
number of references available using L<BIO_up_ref(3)> before calling the set0
functions.
SSL_set_bio() is similar to SSL_set0_rbio() and SSL_set0_wbio() except
that it connects both the B<rbio> and the B<wbio> at the same time, and
transfers the ownership of B<rbio> and B<wbio> to B<ssl> according to
the following set of rules:
=over 2
=item *
If neither the B<rbio> or B<wbio> have changed from their previous values
then nothing is done.
=item *
If the B<rbio> and B<wbio> parameters are different and both are different
to their
previously set values then one reference is consumed for the rbio and one
reference is consumed for the wbio.
=item *
If the B<rbio> and B<wbio> parameters are the same and the B<rbio> is not
the same as the previously set value then one reference is consumed.
=item *
If the B<rbio> and B<wbio> parameters are the same and the B<rbio> is the
same as the previously set value, then no additional references are consumed.
=item *
If the B<rbio> and B<wbio> parameters are different and the B<rbio> is the
same as the
previously set value then one reference is consumed for the B<wbio> and no
references are consumed for the B<rbio>.
=item *
If the B<rbio> and B<wbio> parameters are different and the B<wbio> is the
same as the previously set value and the old B<rbio> and B<wbio> values
were the same as each other then one reference is consumed for the B<rbio>
and no references are consumed for the B<wbio>.
=item *
If the B<rbio> and B<wbio> parameters are different and the B<wbio>
is the same as the
previously set value and the old B<rbio> and B<wbio> values were different
to each
other then one reference is consumed for the B<rbio> and one reference
is consumed
for the B<wbio>.
=back
Because of this complexity, this function should be avoided;
use SSL_set0_rbio() and SSL_set0_wbio() instead.
=head1 RETURN VALUES
-SSL_set_bio(), SSL_set_rbio() and SSL_set_wbio() cannot fail.
+SSL_set_bio(), SSL_set0_rbio() and SSL_set0_wbio() cannot fail.
=head1 SEE ALSO
L<SSL_get_rbio(3)>,
L<SSL_connect(3)>, L<SSL_accept(3)>,
L<SSL_shutdown(3)>, L<ssl(7)>, L<bio(7)>
=head1 HISTORY
SSL_set0_rbio() and SSL_set0_wbio() were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2018 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_set_shutdown.pod b/doc/man3/SSL_set_shutdown.pod
index 04bcc47814e3..b1cf58920be4 100644
--- a/doc/man3/SSL_set_shutdown.pod
+++ b/doc/man3/SSL_set_shutdown.pod
@@ -1,81 +1,81 @@
=pod
=head1 NAME
SSL_set_shutdown, SSL_get_shutdown - manipulate shutdown state of an SSL connection
=head1 SYNOPSIS
#include <openssl/ssl.h>
void SSL_set_shutdown(SSL *ssl, int mode);
int SSL_get_shutdown(const SSL *ssl);
=head1 DESCRIPTION
SSL_set_shutdown() sets the shutdown state of B<ssl> to B<mode>.
SSL_get_shutdown() returns the shutdown mode of B<ssl>.
=head1 NOTES
The shutdown state of an ssl connection is a bitmask of:
=over 4
=item Z<>0
No shutdown setting, yet.
=item SSL_SENT_SHUTDOWN
-A "close notify" shutdown alert was sent to the peer, the connection is being
+A close_notify shutdown alert was sent to the peer, the connection is being
considered closed and the session is closed and correct.
=item SSL_RECEIVED_SHUTDOWN
-A shutdown alert was received form the peer, either a normal "close notify"
+A shutdown alert was received form the peer, either a normal close_notify
or a fatal error.
=back
SSL_SENT_SHUTDOWN and SSL_RECEIVED_SHUTDOWN can be set at the same time.
The shutdown state of the connection is used to determine the state of
the ssl session. If the session is still open, when
L<SSL_clear(3)> or L<SSL_free(3)> is called,
it is considered bad and removed according to RFC2246.
The actual condition for a correctly closed session is SSL_SENT_SHUTDOWN
-(according to the TLS RFC, it is acceptable to only send the "close notify"
+(according to the TLS RFC, it is acceptable to only send the close_notify
alert but to not wait for the peer's answer, when the underlying connection
is closed).
SSL_set_shutdown() can be used to set this state without sending a
close alert to the peer (see L<SSL_shutdown(3)>).
-If a "close notify" was received, SSL_RECEIVED_SHUTDOWN will be set,
+If a close_notify was received, SSL_RECEIVED_SHUTDOWN will be set,
for setting SSL_SENT_SHUTDOWN the application must however still call
L<SSL_shutdown(3)> or SSL_set_shutdown() itself.
=head1 RETURN VALUES
SSL_set_shutdown() does not return diagnostic information.
SSL_get_shutdown() returns the current setting.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_shutdown(3)>,
L<SSL_CTX_set_quiet_shutdown(3)>,
L<SSL_clear(3)>, L<SSL_free(3)>
=head1 COPYRIGHT
-Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2018 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 453853d672fc..0a3d6d370d8b 100644
--- a/doc/man3/SSL_shutdown.pod
+++ b/doc/man3/SSL_shutdown.pod
@@ -1,151 +1,163 @@
=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.
+close_notify shutdown alert to the peer.
=head1 NOTES
-SSL_shutdown() tries to send the "close notify" shutdown alert to the peer.
+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.
-The shutdown procedure consists of 2 steps: the sending of the "close notify"
-shutdown alert and the reception of the peer's "close notify" shutdown
-alert. According to the TLS standard, 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).
-When the underlying connection shall be used for more communications, the
-complete shutdown procedure (bidirectional "close notify" alerts) must be
-performed, so that the peers stay synchronized.
+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.
-SSL_shutdown() supports both uni- and bidirectional shutdown by its 2 step
-behaviour.
+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"
+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).
-SSL_shutdown() will then return with 0.
+If successful, SSL_shutdown() will return 0.
+
If a unidirectional shutdown is enough (the underlying connection shall be
-closed anyway), this first call to SSL_shutdown() is sufficient.
+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.
+to send back a close_notify alert.
The SSL_RECEIVED_SHUTDOWN flag will be set after receiving and processing
it.
-SSL_shutdown() will return 1 when it has been received.
-The peer is still allowed to send data after receiving the "close notify"
+The peer is still allowed to send data after receiving the close_notify
event.
-If the peer did send data it needs to be processed by calling SSL_read()
-before calling SSL_shutdown() a second time.
+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.
-It is recommended to call SSL_read() between SSL_shutdown() calls.
=head2 Peer closes the connection
-If the peer already sent the "close notify" alert B<and> it was
+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 and will immediately return with 1.
+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
-It is recommended to do a bidirectional shutdown by checking the return value
-of SSL_shutdown() and call it again until it returns 1 or a fatal error.
-
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,
+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 send but the peer
+The shutdown is not yet finished: the close_notify was sent but the peer
did not send it back yet.
-Call SSL_shutdown() again to do a bidirectional shutdown.
+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.
+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.
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/man7/RAND_DRBG.pod b/doc/man7/RAND_DRBG.pod
index b89c30d43edd..ba457f050483 100644
--- a/doc/man7/RAND_DRBG.pod
+++ b/doc/man7/RAND_DRBG.pod
@@ -1,301 +1,301 @@
=pod
=head1 NAME
RAND_DRBG - the deterministic random bit generator
=head1 SYNOPSIS
#include <openssl/rand_drbg.h>
=head1 DESCRIPTION
The default OpenSSL RAND method is based on the RAND_DRBG class,
which implements a deterministic random bit generator (DRBG).
A DRBG is a certain type of cryptographically-secure pseudo-random
number generator (CSPRNG), which is described in
[NIST SP 800-90A Rev. 1].
While the RAND API is the 'frontend' which is intended to be used by
application developers for obtaining random bytes, the RAND_DRBG API
serves as the 'backend', connecting the former with the operating
systems's entropy sources and providing access to the DRBG's
configuration parameters.
=head2 Disclaimer
Unless you have very specific requirements for your random generator,
it is in general not necessary to utilize the RAND_DRBG API directly.
The usual way to obtain random bytes is to use L<RAND_bytes(3)> or
L<RAND_priv_bytes(3)>, see also L<RAND(7)>.
=head2 Typical Use Cases
Typical examples for such special use cases are the following:
=over 2
=item *
You want to use your own private DRBG instances.
Multiple DRBG instances which are accessed only by a single thread provide
additional security (because their internal states are independent) and
better scalability in multithreaded applications (because they don't need
to be locked).
=item *
You need to integrate a previously unsupported entropy source.
=item *
You need to change the default settings of the standard OpenSSL RAND
implementation to meet specific requirements.
=back
=head1 CHAINING
A DRBG instance can be used as the entropy source of another DRBG instance,
provided it has itself access to a valid entropy source.
The DRBG instance which acts as entropy source is called the I<parent> DRBG,
the other instance the I<child> DRBG.
This is called chaining. A chained DRBG instance is created by passing
a pointer to the parent DRBG as argument to the RAND_DRBG_new() call.
It is possible to create chains of more than two DRBG in a row.
=head1 THE THREE SHARED DRBG INSTANCES
Currently, there are three shared DRBG instances,
the <master>, <public>, and <private> DRBG.
While the <master> DRBG is a single global instance, the <public> and <private>
DRBG are created per thread and accessed through thread-local storage.
By default, the functions L<RAND_bytes(3)> and L<RAND_priv_bytes(3)> use
the thread-local <public> and <private> DRBG instance, respectively.
=head2 The <master> DRBG instance
The <master> DRBG is not used directly by the application, only for reseeding
the two other two DRBG instances. It reseeds itself by obtaining randomness
either from os entropy sources or by consuming randomness which was added
previously by L<RAND_add(3)>.
=head2 The <public> DRBG instance
This instance is used per default by L<RAND_bytes(3)>.
=head2 The <private> DRBG instance
This instance is used per default by L<RAND_priv_bytes(3)>
=head1 LOCKING
The <master> DRBG is intended to be accessed concurrently for reseeding
by its child DRBG instances. The necessary locking is done internally.
It is I<not> thread-safe to access the <master> DRBG directly via the
RAND_DRBG interface.
The <public> and <private> DRBG are thread-local, i.e. there is an
instance of each per thread. So they can safely be accessed without
locking via the RAND_DRBG interface.
Pointers to these DRBG instances can be obtained using
RAND_DRBG_get0_master(),
RAND_DRBG_get0_public(), and
RAND_DRBG_get0_private(), respectively.
Note that it is not allowed to store a pointer to one of the thread-local
DRBG instances in a variable or other memory location where it will be
accessed and used by multiple threads.
All other DRBG instances created by an application don't support locking,
because they are intended to be used by a single thread.
Instead of accessing a single DRBG instance concurrently from different
threads, it is recommended to instantiate a separate DRBG instance per
thread. Using the <master> DRBG as entropy source for multiple DRBG
instances on different threads is thread-safe, because the DRBG instance
will lock the <master> DRBG automatically for obtaining random input.
=head1 THE OVERALL PICTURE
The following picture gives an overview over how the DRBG instances work
together and are being used.
+--------------------+
| os entropy sources |
+--------------------+
|
v +-----------------------------+
RAND_add() ==> <master> <-| shared DRBG (with locking) |
/ \ +-----------------------------+
/ \ +---------------------------+
<public> <private> <- | per-thread DRBG instances |
| | +---------------------------+
v v
RAND_bytes() RAND_priv_bytes()
| ^
| |
+------------------+ +------------------------------------+
| general purpose | | used for secrets like session keys |
| random generator | | and private keys for certificates |
+------------------+ +------------------------------------+
The usual way to obtain random bytes is to call RAND_bytes(...) or
RAND_priv_bytes(...). These calls are roughly equivalent to calling
RAND_DRBG_bytes(<public>, ...) and RAND_DRBG_bytes(<private>, ...),
respectively. The method L<RAND_DRBG_bytes(3)> is a convenience method
wrapping the L<RAND_DRBG_generate(3)> function, which serves the actual
request for random data.
=head1 RESEEDING
A DRBG instance seeds itself automatically, pulling random input from
its entropy source. The entropy source can be either a trusted operating
system entropy source, or another DRBG with access to such a source.
Automatic reseeding occurs after a predefined number of generate requests.
The selection of the trusted entropy sources is configured at build
time using the --with-rand-seed option. The following sections explain
the reseeding process in more detail.
=head2 Automatic Reseeding
Before satisfying a generate request (L<RAND_DRBG_generate(3)>), the DRBG
reseeds itself automatically, if one of the following conditions holds:
- the DRBG was not instantiated (=seeded) yet or has been uninstantiated.
- the number of generate requests since the last reseeding exceeds a
certain threshold, the so called I<reseed_interval>.
This behaviour can be disabled by setting the I<reseed_interval> to 0.
- the time elapsed since the last reseeding exceeds a certain time
interval, the so called I<reseed_time_interval>.
This can be disabled by setting the I<reseed_time_interval> to 0.
- the DRBG is in an error state.
B<Note>: An error state is entered if the entropy source fails while
the DRBG is seeding or reseeding.
The last case ensures that the DRBG automatically recovers
from the error as soon as the entropy source is available again.
=head2 Manual Reseeding
In addition to automatic reseeding, the caller can request an immediate
reseeding of the DRBG with fresh entropy by setting the
I<prediction resistance> parameter to 1 when calling L<RAND_DRBG_generate(3)>.
-The dcoument [NIST SP 800-90C] describes prediction resistance requests
+The document [NIST SP 800-90C] describes prediction resistance requests
in detail and imposes strict conditions on the entropy sources that are
approved for providing prediction resistance.
Since the default DRBG implementation does not have access to such an approved
entropy source, a request for prediction resistance will currently always fail.
In other words, prediction resistance is currently not supported yet by the DRBG.
For the three shared DRBGs (and only for these) there is another way to
reseed them manually:
If L<RAND_add(3)> is called with a positive I<randomness> argument
(or L<RAND_seed(3)>), then this will immediately reseed the <master> DRBG.
The <public> and <private> DRBG will detect this on their next generate
call and reseed, pulling randomness from <master>.
The last feature has been added to support the common practice used with
previous OpenSSL versions to call RAND_add() before calling RAND_bytes().
=head2 Entropy Input vs. Additional Data
The DRBG distinguishes two different types of random input: I<entropy>,
which comes from a trusted source, and I<additional input>',
which can optionally be added by the user and is considered untrusted.
It is possible to add I<additional input> not only during reseeding,
but also for every generate request.
This is in fact done automatically by L<RAND_DRBG_bytes(3)>.
=head2 Configuring the Random Seed Source
In most cases OpenSSL will automatically choose a suitable seed source
for automatically seeding and reseeding its <master> DRBG. In some cases
however, it will be necessary to explicitly specify a seed source during
configuration, using the --with-rand-seed option. For more information,
see the INSTALL instructions. There are also operating systems where no
seed source is available and automatic reseeding is disabled by default.
The following two sections describe the reseeding process of the master
DRBG, depending on whether automatic reseeding is available or not.
=head2 Reseeding the master DRBG with automatic seeding enabled
Calling RAND_poll() or RAND_add() is not necessary, because the DRBG
pulls the necessary entropy from its source automatically.
However, both calls are permitted, and do reseed the RNG.
RAND_add() can be used to add both kinds of random input, depending on the
value of the B<randomness> argument:
=over 4
=item randomness == 0:
The random bytes are mixed as additional input into the current state of
the DRBG.
Mixing in additional input is not considered a full reseeding, hence the
reseed counter is not reset.
=item randomness > 0:
The random bytes are used as entropy input for a full reseeding
(resp. reinstantiation) if the DRBG is instantiated
(resp. uninstantiated or in an error state).
The number of random bits required for reseeding is determined by the
security strength of the DRBG. Currently it defaults to 256 bits (32 bytes).
It is possible to provide less randomness than required.
In this case the missing randomness will be obtained by pulling random input
from the trusted entropy sources.
=back
=head2 Reseeding the master DRBG with automatic seeding disabled
Calling RAND_poll() will always fail.
RAND_add() needs to be called for initial seeding and periodic reseeding.
At least 48 bytes (384 bits) of randomness have to be provided, otherwise
the (re-)seeding of the DRBG will fail. This corresponds to one and a half
times the security strength of the DRBG. The extra half is used for the
nonce during instantiation.
More precisely, the number of bytes needed for seeding depend on the
I<security strength> of the DRBG, which is set to 256 by default.
=head1 SEE ALSO
L<RAND_DRBG_bytes(3)>,
L<RAND_DRBG_generate(3)>,
L<RAND_DRBG_reseed(3)>,
L<RAND_DRBG_get0_master(3)>,
L<RAND_DRBG_get0_public(3)>,
L<RAND_DRBG_get0_private(3)>,
L<RAND_DRBG_set_reseed_interval(3)>,
L<RAND_DRBG_set_reseed_time_interval(3)>,
L<RAND_DRBG_set_reseed_defaults(3)>,
L<RAND(7)>,
=head1 COPYRIGHT
Copyright 2017-2018 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 5769029b7281..534059382b0a 100644
--- a/e_os.h
+++ b/e_os.h
@@ -1,324 +1,331 @@
/*
* Copyright 1995-2018 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"
# 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"
# 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
/********************************************************************
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
# define get_last_sys_error() GetLastError()
# define clear_sys_error() SetLastError(0)
# 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
- POSIXly. 'man perlvms' explains it further.
+ 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
+# 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/include/internal/cryptlib.h b/include/internal/cryptlib.h
index a608735187f8..329ef62014f6 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -1,94 +1,96 @@
/*
* Copyright 1995-2018 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_CRYPTLIB_H
# define HEADER_CRYPTLIB_H
# include <stdlib.h>
# include <string.h>
# ifdef OPENSSL_USE_APPLINK
# undef BIO_FLAGS_UPLINK
# define BIO_FLAGS_UPLINK 0x8000
# include "ms/uplink.h"
# endif
# include <openssl/crypto.h>
# include <openssl/buffer.h>
# include <openssl/bio.h>
# include <openssl/err.h>
# include "internal/nelem.h"
#ifdef NDEBUG
# define ossl_assert(x) ((x) != 0)
#else
__owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr,
const char *file, int line)
{
if (!expr)
OPENSSL_die(exprstr, file, line);
return expr;
}
# define ossl_assert(x) ossl_assert_int((x) != 0, "Assertion failed: "#x, \
__FILE__, __LINE__)
#endif
typedef struct ex_callback_st EX_CALLBACK;
DEFINE_STACK_OF(EX_CALLBACK)
typedef struct app_mem_info_st APP_INFO;
typedef struct mem_st MEM;
DEFINE_LHASH_OF(MEM);
# define OPENSSL_CONF "openssl.cnf"
# ifndef OPENSSL_SYS_VMS
# define X509_CERT_AREA OPENSSLDIR
# define X509_CERT_DIR OPENSSLDIR "/certs"
# define X509_CERT_FILE OPENSSLDIR "/cert.pem"
# define X509_PRIVATE_DIR OPENSSLDIR "/private"
# define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf"
# else
# define X509_CERT_AREA "OSSL$DATAROOT:[000000]"
# define X509_CERT_DIR "OSSL$DATAROOT:[CERTS]"
# define X509_CERT_FILE "OSSL$DATAROOT:[000000]cert.pem"
# define X509_PRIVATE_DIR "OSSL$DATAROOT:[PRIVATE]"
# define CTLOG_FILE "OSSL$DATAROOT:[000000]ct_log_list.cnf"
# endif
# define X509_CERT_DIR_EVP "SSL_CERT_DIR"
# define X509_CERT_FILE_EVP "SSL_CERT_FILE"
# define CTLOG_FILE_EVP "CTLOG_FILE"
/* size of string representations */
# define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1)
# define HEX_SIZE(type) (sizeof(type)*2)
void OPENSSL_cpuid_setup(void);
extern unsigned int OPENSSL_ia32cap_P[];
void OPENSSL_showfatal(const char *fmta, ...);
void crypto_cleanup_all_ex_data_int(void);
int openssl_init_fork_handlers(void);
+char *ossl_safe_getenv(const char *name);
+
extern CRYPTO_RWLOCK *memdbg_lock;
int openssl_strerror_r(int errnum, char *buf, size_t buflen);
# if !defined(OPENSSL_NO_STDIO)
FILE *openssl_fopen(const char *filename, const char *mode);
# else
void *openssl_fopen(const char *filename, const char *mode);
# endif
uint32_t OPENSSL_rdtsc(void);
#endif
diff --git a/include/internal/tsan_assist.h b/include/internal/tsan_assist.h
index 2c7638344a00..f30ffe398ac7 100644
--- a/include/internal/tsan_assist.h
+++ b/include/internal/tsan_assist.h
@@ -1,138 +1,144 @@
/*
* Copyright 2018 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))
/*
* 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/cryptoerr.h b/include/openssl/cryptoerr.h
index e127ff602c4b..10723d0454b3 100644
--- a/include/openssl/cryptoerr.h
+++ b/include/openssl/cryptoerr.h
@@ -1,53 +1,56 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 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_CRYPTOERR_H
# define HEADER_CRYPTOERR_H
# ifdef __cplusplus
extern "C"
# endif
+
+# include <openssl/symhacks.h>
+
int ERR_load_CRYPTO_strings(void);
/*
* CRYPTO function codes.
*/
# define CRYPTO_F_CMAC_CTX_NEW 120
# define CRYPTO_F_CRYPTO_DUP_EX_DATA 110
# define CRYPTO_F_CRYPTO_FREE_EX_DATA 111
# define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100
# define CRYPTO_F_CRYPTO_MEMDUP 115
# define CRYPTO_F_CRYPTO_NEW_EX_DATA 112
# define CRYPTO_F_CRYPTO_OCB128_COPY_CTX 121
# define CRYPTO_F_CRYPTO_OCB128_INIT 122
# define CRYPTO_F_CRYPTO_SET_EX_DATA 102
# define CRYPTO_F_FIPS_MODE_SET 109
# define CRYPTO_F_GET_AND_LOCK 113
# define CRYPTO_F_OPENSSL_ATEXIT 114
# define CRYPTO_F_OPENSSL_BUF2HEXSTR 117
# define CRYPTO_F_OPENSSL_FOPEN 119
# define CRYPTO_F_OPENSSL_HEXSTR2BUF 118
# define CRYPTO_F_OPENSSL_INIT_CRYPTO 116
# define CRYPTO_F_OPENSSL_LH_NEW 126
# define CRYPTO_F_OPENSSL_SK_DEEP_COPY 127
# define CRYPTO_F_OPENSSL_SK_DUP 128
# define CRYPTO_F_PKEY_HMAC_INIT 123
# define CRYPTO_F_PKEY_POLY1305_INIT 124
# define CRYPTO_F_PKEY_SIPHASH_INIT 125
# define CRYPTO_F_SK_RESERVE 129
/*
* CRYPTO reason codes.
*/
# define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101
# define CRYPTO_R_ILLEGAL_HEX_DIGIT 102
# define CRYPTO_R_ODD_NUMBER_OF_DIGITS 103
#endif
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index 4d70da70a614..347cfb6d097b 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -1,1467 +1,1478 @@
/*
* Copyright 2002-2018 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
*/
#ifndef HEADER_EC_H
# define HEADER_EC_H
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_EC
# include <openssl/asn1.h>
# include <openssl/symhacks.h>
# if OPENSSL_API_COMPAT < 0x10100000L
# include <openssl/bn.h>
# endif
# include <openssl/ecerr.h>
# ifdef __cplusplus
extern "C" {
# endif
# ifndef OPENSSL_ECC_MAX_FIELD_BITS
# define OPENSSL_ECC_MAX_FIELD_BITS 661
# endif
/** Enum for the point conversion form as defined in X9.62 (ECDSA)
* for the encoding of a elliptic curve point (x,y) */
typedef enum {
/** the point is encoded as z||x, where the octet z specifies
* which solution of the quadratic equation y is */
POINT_CONVERSION_COMPRESSED = 2,
/** the point is encoded as z||x||y, where z is the octet 0x04 */
POINT_CONVERSION_UNCOMPRESSED = 4,
/** the point is encoded as z||x||y, where the octet z specifies
* which solution of the quadratic equation y is */
POINT_CONVERSION_HYBRID = 6
} point_conversion_form_t;
typedef struct ec_method_st EC_METHOD;
typedef struct ec_group_st EC_GROUP;
typedef struct ec_point_st EC_POINT;
typedef struct ecpk_parameters_st ECPKPARAMETERS;
typedef struct ec_parameters_st ECPARAMETERS;
/********************************************************************/
/* EC_METHODs for curves over GF(p) */
/********************************************************************/
/** Returns the basic GFp ec methods which provides the basis for the
* optimized methods.
* \return EC_METHOD object
*/
const EC_METHOD *EC_GFp_simple_method(void);
/** Returns GFp methods using montgomery multiplication.
* \return EC_METHOD object
*/
const EC_METHOD *EC_GFp_mont_method(void);
/** Returns GFp methods using optimized methods for NIST recommended curves
* \return EC_METHOD object
*/
const EC_METHOD *EC_GFp_nist_method(void);
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
/** Returns 64-bit optimized methods for nistp224
* \return EC_METHOD object
*/
const EC_METHOD *EC_GFp_nistp224_method(void);
/** Returns 64-bit optimized methods for nistp256
* \return EC_METHOD object
*/
const EC_METHOD *EC_GFp_nistp256_method(void);
/** Returns 64-bit optimized methods for nistp521
* \return EC_METHOD object
*/
const EC_METHOD *EC_GFp_nistp521_method(void);
# endif
# ifndef OPENSSL_NO_EC2M
/********************************************************************/
/* EC_METHOD for curves over GF(2^m) */
/********************************************************************/
/** Returns the basic GF2m ec method
* \return EC_METHOD object
*/
const EC_METHOD *EC_GF2m_simple_method(void);
# endif
/********************************************************************/
/* EC_GROUP functions */
/********************************************************************/
/** Creates a new EC_GROUP object
* \param meth EC_METHOD to use
* \return newly created EC_GROUP object or NULL in case of an error.
*/
EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
/** Frees a EC_GROUP object
* \param group EC_GROUP object to be freed.
*/
void EC_GROUP_free(EC_GROUP *group);
/** Clears and frees a EC_GROUP object
* \param group EC_GROUP object to be cleared and freed.
*/
void EC_GROUP_clear_free(EC_GROUP *group);
/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD.
* \param dst destination EC_GROUP object
* \param src source EC_GROUP object
* \return 1 on success and 0 if an error occurred.
*/
int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src);
/** Creates a new EC_GROUP object and copies the copies the content
* form src to the newly created EC_KEY object
* \param src source EC_GROUP object
* \return newly created EC_GROUP object or NULL in case of an error.
*/
EC_GROUP *EC_GROUP_dup(const EC_GROUP *src);
/** Returns the EC_METHOD of the EC_GROUP object.
* \param group EC_GROUP object
* \return EC_METHOD used in this EC_GROUP object.
*/
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
/** Returns the field type of the EC_METHOD.
* \param meth EC_METHOD object
* \return NID of the underlying field type OID.
*/
int EC_METHOD_get_field_type(const EC_METHOD *meth);
/** Sets the generator and it's order/cofactor of a EC_GROUP object.
* \param group EC_GROUP object
* \param generator EC_POINT object with the generator.
* \param order the order of the group generated by the generator.
* \param cofactor the index of the sub-group generated by the generator
* in the group of all points on the elliptic curve.
* \return 1 on success and 0 if an error occurred
*/
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor);
/** Returns the generator of a EC_GROUP object.
* \param group EC_GROUP object
* \return the currently used generator (possibly NULL).
*/
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);
/** Returns the montgomery data for order(Generator)
* \param group EC_GROUP object
* \return the currently used montgomery data (possibly NULL).
*/
BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group);
/** Gets the order of a EC_GROUP
* \param group EC_GROUP object
* \param order BIGNUM to which the order is copied
* \param ctx unused
* \return 1 on success and 0 if an error occurred
*/
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx);
/** Gets the order of an EC_GROUP
* \param group EC_GROUP object
* \return the group order
*/
const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group);
/** Gets the number of bits of the order of an EC_GROUP
* \param group EC_GROUP object
* \return number of bits of group order.
*/
int EC_GROUP_order_bits(const EC_GROUP *group);
/** Gets the cofactor of a EC_GROUP
* \param group EC_GROUP object
* \param cofactor BIGNUM to which the cofactor is copied
* \param ctx unused
* \return 1 on success and 0 if an error occurred
*/
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
BN_CTX *ctx);
/** Gets the cofactor of an EC_GROUP
* \param group EC_GROUP object
* \return the group cofactor
*/
const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group);
/** Sets the name of a EC_GROUP object
* \param group EC_GROUP object
* \param nid NID of the curve name OID
*/
void EC_GROUP_set_curve_name(EC_GROUP *group, int nid);
/** Returns the curve name of a EC_GROUP object
* \param group EC_GROUP object
* \return NID of the curve name OID or 0 if not set.
*/
int EC_GROUP_get_curve_name(const EC_GROUP *group);
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);
int EC_GROUP_get_asn1_flag(const EC_GROUP *group);
void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
point_conversion_form_t form);
point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);
unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x);
size_t EC_GROUP_get_seed_len(const EC_GROUP *);
size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
/** Sets the parameters of a ec curve defined by y^2 = x^3 + a*x + b (for GFp)
* or y^2 + x*y = x^3 + a*x^2 + b (for GF2m)
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
* defining the underlying field (GF2m)
* \param a BIGNUM with parameter a of the equation
* \param b BIGNUM with parameter b of the equation
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx);
/** Gets the parameters of the ec curve defined by y^2 = x^3 + a*x + b (for GFp)
* or y^2 + x*y = x^3 + a*x^2 + b (for GF2m)
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
* defining the underlying field (GF2m)
* \param a BIGNUM for parameter a of the equation
* \param b BIGNUM for parameter b of the equation
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
BN_CTX *ctx);
/** Sets the parameters of an ec curve. Synonym for EC_GROUP_set_curve
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
* defining the underlying field (GF2m)
* \param a BIGNUM with parameter a of the equation
* \param b BIGNUM with parameter b of the equation
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b,
BN_CTX *ctx))
/** Gets the parameters of an ec curve. Synonym for EC_GROUP_get_curve
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
* defining the underlying field (GF2m)
* \param a BIGNUM for parameter a of the equation
* \param b BIGNUM for parameter b of the equation
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p,
BIGNUM *a, BIGNUM *b,
BN_CTX *ctx))
# ifndef OPENSSL_NO_EC2M
/** Sets the parameter of an ec curve. Synonym for EC_GROUP_set_curve
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
* defining the underlying field (GF2m)
* \param a BIGNUM with parameter a of the equation
* \param b BIGNUM with parameter b of the equation
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b,
BN_CTX *ctx))
/** Gets the parameters of an ec curve. Synonym for EC_GROUP_get_curve
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
* defining the underlying field (GF2m)
* \param a BIGNUM for parameter a of the equation
* \param b BIGNUM for parameter b of the equation
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p,
BIGNUM *a, BIGNUM *b,
BN_CTX *ctx))
# endif
/** Returns the number of bits needed to represent a field element
* \param group EC_GROUP object
* \return number of bits needed to represent a field element
*/
int EC_GROUP_get_degree(const EC_GROUP *group);
/** Checks whether the parameter in the EC_GROUP define a valid ec group
* \param group EC_GROUP object
* \param ctx BN_CTX object (optional)
* \return 1 if group is a valid ec group and 0 otherwise
*/
int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
/** Checks whether the discriminant of the elliptic curve is zero or not
* \param group EC_GROUP object
* \param ctx BN_CTX object (optional)
* \return 1 if the discriminant is not zero and 0 otherwise
*/
int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx);
/** Compares two EC_GROUP objects
* \param a first EC_GROUP object
* \param b second EC_GROUP object
* \param ctx BN_CTX object (optional)
* \return 0 if the groups are equal, 1 if not, or -1 on error
*/
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
/*
* EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*() after
* choosing an appropriate EC_METHOD
*/
/** Creates a new EC_GROUP object with the specified parameters defined
* over GFp (defined by the equation y^2 = x^3 + a*x + b)
* \param p BIGNUM with the prime number
* \param a BIGNUM with the parameter a of the equation
* \param b BIGNUM with the parameter b of the equation
* \param ctx BN_CTX object (optional)
* \return newly created EC_GROUP object with the specified parameters
*/
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx);
# ifndef OPENSSL_NO_EC2M
/** Creates a new EC_GROUP object with the specified parameters defined
* over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b)
* \param p BIGNUM with the polynomial defining the underlying field
* \param a BIGNUM with the parameter a of the equation
* \param b BIGNUM with the parameter b of the equation
* \param ctx BN_CTX object (optional)
* \return newly created EC_GROUP object with the specified parameters
*/
EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx);
# endif
/** Creates a EC_GROUP object with a curve specified by a NID
* \param nid NID of the OID of the curve name
* \return newly created EC_GROUP object with specified curve or NULL
* if an error occurred
*/
EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
/** Creates a new EC_GROUP object from an ECPARAMETERS object
* \param params pointer to the ECPARAMETERS object
* \return newly created EC_GROUP object with specified curve or NULL
* if an error occurred
*/
EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params);
/** Creates an ECPARAMETERS object for the given EC_GROUP object.
* \param group pointer to the EC_GROUP object
* \param params pointer to an existing ECPARAMETERS object or NULL
* \return pointer to the new ECPARAMETERS object or NULL
* if an error occurred.
*/
ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
ECPARAMETERS *params);
/** Creates a new EC_GROUP object from an ECPKPARAMETERS object
* \param params pointer to an existing ECPKPARAMETERS object, or NULL
* \return newly created EC_GROUP object with specified curve, or NULL
* if an error occurred
*/
EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params);
/** Creates an ECPKPARAMETERS object for the given EC_GROUP object.
* \param group pointer to the EC_GROUP object
* \param params pointer to an existing ECPKPARAMETERS object or NULL
* \return pointer to the new ECPKPARAMETERS object or NULL
* if an error occurred.
*/
ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group,
ECPKPARAMETERS *params);
/********************************************************************/
/* handling of internal curves */
/********************************************************************/
typedef struct {
int nid;
const char *comment;
} EC_builtin_curve;
/*
* EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number of all
* available curves or zero if a error occurred. In case r is not zero,
* nitems EC_builtin_curve structures are filled with the data of the first
* nitems internal groups
*/
size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
const char *EC_curve_nid2nist(int nid);
int EC_curve_nist2nid(const char *name);
/********************************************************************/
/* EC_POINT functions */
/********************************************************************/
/** Creates a new EC_POINT object for the specified EC_GROUP
* \param group EC_GROUP the underlying EC_GROUP object
* \return newly created EC_POINT object or NULL if an error occurred
*/
EC_POINT *EC_POINT_new(const EC_GROUP *group);
/** Frees a EC_POINT object
* \param point EC_POINT object to be freed
*/
void EC_POINT_free(EC_POINT *point);
/** Clears and frees a EC_POINT object
* \param point EC_POINT object to be cleared and freed
*/
void EC_POINT_clear_free(EC_POINT *point);
/** Copies EC_POINT object
* \param dst destination EC_POINT object
* \param src source EC_POINT object
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src);
/** Creates a new EC_POINT object and copies the content of the supplied
* EC_POINT
* \param src source EC_POINT object
* \param group underlying the EC_GROUP object
* \return newly created EC_POINT object or NULL if an error occurred
*/
EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group);
/** Returns the EC_METHOD used in EC_POINT object
* \param point EC_POINT object
* \return the EC_METHOD used
*/
const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
/** Sets a point to infinity (neutral element)
* \param group underlying EC_GROUP object
* \param point EC_POINT to set to infinity
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);
/** Sets the jacobian projective coordinates of a EC_POINT over GFp
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM with the x-coordinate
* \param y BIGNUM with the y-coordinate
* \param z BIGNUM with the z-coordinate
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
EC_POINT *p, const BIGNUM *x,
const BIGNUM *y, const BIGNUM *z,
BN_CTX *ctx);
/** Gets the jacobian projective coordinates of a EC_POINT over GFp
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM for the x-coordinate
* \param y BIGNUM for the y-coordinate
* \param z BIGNUM for the z-coordinate
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *p, BIGNUM *x,
BIGNUM *y, BIGNUM *z,
BN_CTX *ctx);
/** Sets the affine coordinates of an EC_POINT
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM with the x-coordinate
* \param y BIGNUM with the y-coordinate
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx);
/** Gets the affine coordinates of an EC_POINT.
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM for the x-coordinate
* \param y BIGNUM for the y-coordinate
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
/** Sets the affine coordinates of an EC_POINT. A synonym of
* EC_POINT_set_affine_coordinates
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM with the x-coordinate
* \param y BIGNUM with the y-coordinate
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
EC_POINT *p,
const BIGNUM *x,
const BIGNUM *y,
BN_CTX *ctx))
/** Gets the affine coordinates of an EC_POINT. A synonym of
* EC_POINT_get_affine_coordinates
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM for the x-coordinate
* \param y BIGNUM for the y-coordinate
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *p,
BIGNUM *x,
BIGNUM *y,
BN_CTX *ctx))
/** Sets the x9.62 compressed coordinates of a EC_POINT
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM with x-coordinate
* \param y_bit integer with the y-Bit (either 0 or 1)
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, int y_bit,
BN_CTX *ctx);
/** Sets the x9.62 compressed coordinates of a EC_POINT. A synonym of
* EC_POINT_set_compressed_coordinates
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM with x-coordinate
* \param y_bit integer with the y-Bit (either 0 or 1)
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
EC_POINT *p,
const BIGNUM *x,
int y_bit,
BN_CTX *ctx))
# ifndef OPENSSL_NO_EC2M
/** Sets the affine coordinates of an EC_POINT. A synonym of
* EC_POINT_set_affine_coordinates
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM with the x-coordinate
* \param y BIGNUM with the y-coordinate
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
EC_POINT *p,
const BIGNUM *x,
const BIGNUM *y,
BN_CTX *ctx))
/** Gets the affine coordinates of an EC_POINT. A synonym of
* EC_POINT_get_affine_coordinates
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM for the x-coordinate
* \param y BIGNUM for the y-coordinate
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
const EC_POINT *p,
BIGNUM *x,
BIGNUM *y,
BN_CTX *ctx))
/** Sets the x9.62 compressed coordinates of a EC_POINT. A synonym of
* EC_POINT_set_compressed_coordinates
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param x BIGNUM with x-coordinate
* \param y_bit integer with the y-Bit (either 0 or 1)
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
EC_POINT *p,
const BIGNUM *x,
int y_bit,
BN_CTX *ctx))
# endif
/** Encodes a EC_POINT object to a octet string
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param form point conversion form
* \param buf memory buffer for the result. If NULL the function returns
* required buffer size.
* \param len length of the memory buffer
* \param ctx BN_CTX object (optional)
* \return the length of the encoded octet string or 0 if an error occurred
*/
size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p,
point_conversion_form_t form,
unsigned char *buf, size_t len, BN_CTX *ctx);
/** Decodes a EC_POINT from a octet string
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param buf memory buffer with the encoded ec point
* \param len length of the encoded ec point
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p,
const unsigned char *buf, size_t len, BN_CTX *ctx);
/** Encodes an EC_POINT object to an allocated octet string
* \param group underlying EC_GROUP object
* \param point EC_POINT object
* \param form point conversion form
* \param pbuf returns pointer to allocated buffer
* \param ctx BN_CTX object (optional)
* \return the length of the encoded octet string or 0 if an error occurred
*/
size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form,
unsigned char **pbuf, BN_CTX *ctx);
/* other interfaces to point2oct/oct2point: */
BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
point_conversion_form_t form, BIGNUM *, BN_CTX *);
EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
EC_POINT *, BN_CTX *);
char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
point_conversion_form_t form, BN_CTX *);
EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
EC_POINT *, BN_CTX *);
/********************************************************************/
/* functions for doing EC_POINT arithmetic */
/********************************************************************/
/** Computes the sum of two EC_POINT
* \param group underlying EC_GROUP object
* \param r EC_POINT object for the result (r = a + b)
* \param a EC_POINT object with the first summand
* \param b EC_POINT object with the second summand
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx);
/** Computes the double of a EC_POINT
* \param group underlying EC_GROUP object
* \param r EC_POINT object for the result (r = 2 * a)
* \param a EC_POINT object
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
BN_CTX *ctx);
/** Computes the inverse of a EC_POINT
* \param group underlying EC_GROUP object
* \param a EC_POINT object to be inverted (it's used for the result as well)
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx);
/** Checks whether the point is the neutral element of the group
* \param group the underlying EC_GROUP object
* \param p EC_POINT object
* \return 1 if the point is the neutral element and 0 otherwise
*/
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p);
/** Checks whether the point is on the curve
* \param group underlying EC_GROUP object
* \param point EC_POINT object to check
* \param ctx BN_CTX object (optional)
* \return 1 if the point is on the curve, 0 if not, or -1 on error
*/
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BN_CTX *ctx);
/** Compares two EC_POINTs
* \param group underlying EC_GROUP object
* \param a first EC_POINT object
* \param b second EC_POINT object
* \param ctx BN_CTX object (optional)
* \return 1 if the points are not equal, 0 if they are, or -1 on error
*/
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
BN_CTX *ctx);
int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx);
int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
EC_POINT *points[], BN_CTX *ctx);
/** Computes r = generator * n + sum_{i=0}^{num-1} p[i] * m[i]
* \param group underlying EC_GROUP object
* \param r EC_POINT object for the result
* \param n BIGNUM with the multiplier for the group generator (optional)
* \param num number further summands
* \param p array of size num of EC_POINT objects
* \param m array of size num of BIGNUM objects
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
size_t num, const EC_POINT *p[], const BIGNUM *m[],
BN_CTX *ctx);
/** Computes r = generator * n + q * m
* \param group underlying EC_GROUP object
* \param r EC_POINT object for the result
* \param n BIGNUM with the multiplier for the group generator (optional)
* \param q EC_POINT object with the first factor of the second summand
* \param m BIGNUM with the second factor of the second summand
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
/** Stores multiples of generator for faster point multiplication
* \param group EC_GROUP object
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
/** Reports whether a precomputation has been done
* \param group EC_GROUP object
* \return 1 if a pre-computation has been done and 0 otherwise
*/
int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
/********************************************************************/
/* ASN1 stuff */
/********************************************************************/
DECLARE_ASN1_ITEM(ECPKPARAMETERS)
DECLARE_ASN1_ALLOC_FUNCTIONS(ECPKPARAMETERS)
DECLARE_ASN1_ITEM(ECPARAMETERS)
DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
/*
* EC_GROUP_get_basis_type() returns the NID of the basis type used to
* represent the field elements
*/
int EC_GROUP_get_basis_type(const EC_GROUP *);
# ifndef OPENSSL_NO_EC2M
int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
unsigned int *k2, unsigned int *k3);
# endif
# define OPENSSL_EC_EXPLICIT_CURVE 0x000
# define OPENSSL_EC_NAMED_CURVE 0x001
EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
# define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
# define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
# define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
(char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
# define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
(unsigned char *)(x))
int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
# ifndef OPENSSL_NO_STDIO
int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
# endif
/********************************************************************/
/* EC_KEY functions */
/********************************************************************/
/* some values for the encoding_flag */
# define EC_PKEY_NO_PARAMETERS 0x001
# define EC_PKEY_NO_PUBKEY 0x002
/* some values for the flags field */
# define EC_FLAG_NON_FIPS_ALLOW 0x1
# define EC_FLAG_FIPS_CHECKED 0x2
# define EC_FLAG_COFACTOR_ECDH 0x1000
/** Creates a new EC_KEY object.
* \return EC_KEY object or NULL if an error occurred.
*/
EC_KEY *EC_KEY_new(void);
int EC_KEY_get_flags(const EC_KEY *key);
void EC_KEY_set_flags(EC_KEY *key, int flags);
void EC_KEY_clear_flags(EC_KEY *key, int flags);
/** Creates a new EC_KEY object using a named curve as underlying
* EC_GROUP object.
* \param nid NID of the named curve.
* \return EC_KEY object or NULL if an error occurred.
*/
EC_KEY *EC_KEY_new_by_curve_name(int nid);
/** Frees a EC_KEY object.
* \param key EC_KEY object to be freed.
*/
void EC_KEY_free(EC_KEY *key);
/** Copies a EC_KEY object.
* \param dst destination EC_KEY object
* \param src src EC_KEY object
* \return dst or NULL if an error occurred.
*/
EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
/** Creates a new EC_KEY object and copies the content from src to it.
* \param src the source EC_KEY object
* \return newly created EC_KEY object or NULL if an error occurred.
*/
EC_KEY *EC_KEY_dup(const EC_KEY *src);
/** Increases the internal reference count of a EC_KEY object.
* \param key EC_KEY object
* \return 1 on success and 0 if an error occurred.
*/
int EC_KEY_up_ref(EC_KEY *key);
/** Returns the ENGINE object of a EC_KEY object
* \param eckey EC_KEY object
* \return the ENGINE object (possibly NULL).
*/
ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey);
/** Returns the EC_GROUP object of a EC_KEY object
* \param key EC_KEY object
* \return the EC_GROUP object (possibly NULL).
*/
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
/** Sets the EC_GROUP of a EC_KEY object.
* \param key EC_KEY object
* \param group EC_GROUP to use in the EC_KEY object (note: the EC_KEY
* object will use an own copy of the EC_GROUP).
* \return 1 on success and 0 if an error occurred.
*/
int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);
/** Returns the private key of a EC_KEY object.
* \param key EC_KEY object
* \return a BIGNUM with the private key (possibly NULL).
*/
const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
/** Sets the private key of a EC_KEY object.
* \param key EC_KEY object
* \param prv BIGNUM with the private key (note: the EC_KEY object
* will use an own copy of the BIGNUM).
* \return 1 on success and 0 if an error occurred.
*/
int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv);
/** Returns the public key of a EC_KEY object.
* \param key the EC_KEY object
* \return a EC_POINT object with the public key (possibly NULL)
*/
const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
/** Sets the public key of a EC_KEY object.
* \param key EC_KEY object
* \param pub EC_POINT object with the public key (note: the EC_KEY object
* will use an own copy of the EC_POINT object).
* \return 1 on success and 0 if an error occurred.
*/
int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
unsigned EC_KEY_get_enc_flags(const EC_KEY *key);
void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags);
point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key);
void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform);
#define EC_KEY_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, l, p, newf, dupf, freef)
int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg);
void *EC_KEY_get_ex_data(const EC_KEY *key, int idx);
/* wrapper functions for the underlying EC_GROUP object */
void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
/** Creates a table of pre-computed multiples of the generator to
* accelerate further EC_KEY operations.
* \param key EC_KEY object
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred.
*/
int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
/** Creates a new ec private (and optional a new public) key.
* \param key EC_KEY object
* \return 1 on success and 0 if an error occurred.
*/
int EC_KEY_generate_key(EC_KEY *key);
/** Verifies that a private and/or public key is valid.
* \param key the EC_KEY object
* \return 1 on success and 0 otherwise.
*/
int EC_KEY_check_key(const EC_KEY *key);
/** Indicates if an EC_KEY can be used for signing.
* \param eckey the EC_KEY object
* \return 1 if can can sign and 0 otherwise.
*/
int EC_KEY_can_sign(const EC_KEY *eckey);
/** Sets a public key from affine coordinates performing
* necessary NIST PKV tests.
* \param key the EC_KEY object
* \param x public key x coordinate
* \param y public key y coordinate
* \return 1 on success and 0 otherwise.
*/
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
BIGNUM *y);
/** Encodes an EC_KEY public key to an allocated octet string
* \param key key to encode
* \param form point conversion form
* \param pbuf returns pointer to allocated buffer
* \param ctx BN_CTX object (optional)
* \return the length of the encoded octet string or 0 if an error occurred
*/
size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
unsigned char **pbuf, BN_CTX *ctx);
/** Decodes a EC_KEY public key from a octet string
* \param key key to decode
* \param buf memory buffer with the encoded ec point
* \param len length of the encoded ec point
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len,
BN_CTX *ctx);
/** Decodes an EC_KEY private key from an octet string
* \param key key to decode
* \param buf memory buffer with the encoded private key
* \param len length of the encoded key
* \return 1 on success and 0 if an error occurred
*/
int EC_KEY_oct2priv(EC_KEY *key, const unsigned char *buf, size_t len);
/** Encodes a EC_KEY private key to an octet string
* \param key key to encode
* \param buf memory buffer for the result. If NULL the function returns
* required buffer size.
* \param len length of the memory buffer
* \return the length of the encoded octet string or 0 if an error occurred
*/
size_t EC_KEY_priv2oct(const EC_KEY *key, unsigned char *buf, size_t len);
/** Encodes an EC_KEY private key to an allocated octet string
* \param eckey key to encode
* \param pbuf returns pointer to allocated buffer
* \return the length of the encoded octet string or 0 if an error occurred
*/
size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf);
/********************************************************************/
/* de- and encoding functions for SEC1 ECPrivateKey */
/********************************************************************/
/** Decodes a private key from a memory buffer.
* \param key a pointer to a EC_KEY object which should be used (or NULL)
* \param in pointer to memory with the DER encoded private key
* \param len length of the DER encoded private key
* \return the decoded private key or NULL if an error occurred.
*/
EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len);
/** Encodes a private key object and stores the result in a buffer.
* \param key the EC_KEY object to encode
* \param out the buffer for the result (if NULL the function returns number
* of bytes needed).
* \return 1 on success and 0 if an error occurred.
*/
int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out);
/********************************************************************/
/* de- and encoding functions for EC parameters */
/********************************************************************/
/** Decodes ec parameter from a memory buffer.
* \param key a pointer to a EC_KEY object which should be used (or NULL)
* \param in pointer to memory with the DER encoded ec parameters
* \param len length of the DER encoded ec parameters
* \return a EC_KEY object with the decoded parameters or NULL if an error
* occurred.
*/
EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len);
/** Encodes ec parameter and stores the result in a buffer.
* \param key the EC_KEY object with ec parameters to encode
* \param out the buffer for the result (if NULL the function returns number
* of bytes needed).
* \return 1 on success and 0 if an error occurred.
*/
int i2d_ECParameters(EC_KEY *key, unsigned char **out);
/********************************************************************/
/* de- and encoding functions for EC public key */
/* (octet string, not DER -- hence 'o2i' and 'i2o') */
/********************************************************************/
/** Decodes a ec public key from a octet string.
* \param key a pointer to a EC_KEY object which should be used
* \param in memory buffer with the encoded public key
* \param len length of the encoded public key
* \return EC_KEY object with decoded public key or NULL if an error
* occurred.
*/
EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len);
/** Encodes a ec public key in an octet string.
* \param key the EC_KEY object with the public key
* \param out the buffer for the result (if NULL the function returns number
* of bytes needed).
* \return 1 on success and 0 if an error occurred
*/
int i2o_ECPublicKey(const EC_KEY *key, unsigned char **out);
/** Prints out the ec parameters on human readable form.
* \param bp BIO object to which the information is printed
* \param key EC_KEY object
* \return 1 on success and 0 if an error occurred
*/
int ECParameters_print(BIO *bp, const EC_KEY *key);
/** Prints out the contents of a EC_KEY object
* \param bp BIO object to which the information is printed
* \param key EC_KEY object
* \param off line offset
* \return 1 on success and 0 if an error occurred
*/
int EC_KEY_print(BIO *bp, const EC_KEY *key, int off);
# ifndef OPENSSL_NO_STDIO
/** Prints out the ec parameters on human readable form.
* \param fp file descriptor to which the information is printed
* \param key EC_KEY object
* \return 1 on success and 0 if an error occurred
*/
int ECParameters_print_fp(FILE *fp, const EC_KEY *key);
/** Prints out the contents of a EC_KEY object
* \param fp file descriptor to which the information is printed
* \param key EC_KEY object
* \param off line offset
* \return 1 on success and 0 if an error occurred
*/
int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);
# endif
const EC_KEY_METHOD *EC_KEY_OpenSSL(void);
const EC_KEY_METHOD *EC_KEY_get_default_method(void);
void EC_KEY_set_default_method(const EC_KEY_METHOD *meth);
const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key);
int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth);
EC_KEY *EC_KEY_new_method(ENGINE *engine);
+/** The old name for ecdh_KDF_X9_63
+ * The ECDH KDF specification has been mistakingly attributed to ANSI X9.62,
+ * it is actually specified in ANSI X9.63.
+ * This identifier is retained for backwards compatibility
+ */
int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
const unsigned char *Z, size_t Zlen,
const unsigned char *sinfo, size_t sinfolen,
const EVP_MD *md);
int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
const EC_KEY *ecdh,
void *(*KDF) (const void *in, size_t inlen,
void *out, size_t *outlen));
typedef struct ECDSA_SIG_st ECDSA_SIG;
/** Allocates and initialize a ECDSA_SIG structure
* \return pointer to a ECDSA_SIG structure or NULL if an error occurred
*/
ECDSA_SIG *ECDSA_SIG_new(void);
/** frees a ECDSA_SIG structure
* \param sig pointer to the ECDSA_SIG structure
*/
void ECDSA_SIG_free(ECDSA_SIG *sig);
/** DER encode content of ECDSA_SIG object (note: this function modifies *pp
* (*pp += length of the DER encoded signature)).
* \param sig pointer to the ECDSA_SIG object
* \param pp pointer to a unsigned char pointer for the output or NULL
* \return the length of the DER encoded ECDSA_SIG object or 0
*/
int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp);
/** Decodes a DER encoded ECDSA signature (note: this function changes *pp
* (*pp += len)).
* \param sig pointer to ECDSA_SIG pointer (may be NULL)
* \param pp memory buffer with the DER encoded signature
* \param len length of the buffer
* \return pointer to the decoded ECDSA_SIG structure (or NULL)
*/
ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len);
/** Accessor for r and s fields of ECDSA_SIG
* \param sig pointer to ECDSA_SIG structure
* \param pr pointer to BIGNUM pointer for r (may be NULL)
* \param ps pointer to BIGNUM pointer for s (may be NULL)
*/
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
/** Accessor for r field of ECDSA_SIG
* \param sig pointer to ECDSA_SIG structure
*/
const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig);
/** Accessor for s field of ECDSA_SIG
* \param sig pointer to ECDSA_SIG structure
*/
const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig);
/** Setter for r and s fields of ECDSA_SIG
* \param sig pointer to ECDSA_SIG structure
* \param r pointer to BIGNUM for r (may be NULL)
* \param s pointer to BIGNUM for s (may be NULL)
*/
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
/** Computes the ECDSA signature of the given hash value using
* the supplied private key and returns the created signature.
* \param dgst pointer to the hash value
* \param dgst_len length of the hash value
* \param eckey EC_KEY object containing a private EC key
* \return pointer to a ECDSA_SIG structure or NULL if an error occurred
*/
ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len,
EC_KEY *eckey);
/** Computes ECDSA signature of a given hash value using the supplied
* private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
* \param dgst pointer to the hash value to sign
* \param dgstlen length of the hash value
* \param kinv BIGNUM with a pre-computed inverse k (optional)
* \param rp BIGNUM with a pre-computed rp value (optional),
* see ECDSA_sign_setup
* \param eckey EC_KEY object containing a private EC key
* \return pointer to a ECDSA_SIG structure or NULL if an error occurred
*/
ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
const BIGNUM *kinv, const BIGNUM *rp,
EC_KEY *eckey);
/** Verifies that the supplied signature is a valid ECDSA
* signature of the supplied hash value using the supplied public key.
* \param dgst pointer to the hash value
* \param dgst_len length of the hash value
* \param sig ECDSA_SIG structure
* \param eckey EC_KEY object containing a public EC key
* \return 1 if the signature is valid, 0 if the signature is invalid
* and -1 on error
*/
int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
/** Precompute parts of the signing operation
* \param eckey EC_KEY object containing a private EC key
* \param ctx BN_CTX object (optional)
* \param kinv BIGNUM pointer for the inverse of k
* \param rp BIGNUM pointer for x coordinate of k * generator
* \return 1 on success and 0 otherwise
*/
int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp);
/** Computes ECDSA signature of a given hash value using the supplied
* private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
* \param type this parameter is ignored
* \param dgst pointer to the hash value to sign
* \param dgstlen length of the hash value
* \param sig memory for the DER encoded created signature
* \param siglen pointer to the length of the returned signature
* \param eckey EC_KEY object containing a private EC key
* \return 1 on success and 0 otherwise
*/
int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
/** Computes ECDSA signature of a given hash value using the supplied
* private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
* \param type this parameter is ignored
* \param dgst pointer to the hash value to sign
* \param dgstlen length of the hash value
* \param sig buffer to hold the DER encoded signature
* \param siglen pointer to the length of the returned signature
* \param kinv BIGNUM with a pre-computed inverse k (optional)
* \param rp BIGNUM with a pre-computed rp value (optional),
* see ECDSA_sign_setup
* \param eckey EC_KEY object containing a private EC key
* \return 1 on success and 0 otherwise
*/
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);
/** Verifies that the given signature is valid ECDSA signature
* of the supplied hash value using the specified public key.
* \param type this parameter is ignored
* \param dgst pointer to the hash value
* \param dgstlen length of the hash value
* \param sig pointer to the DER encoded signature
* \param siglen length of the DER encoded signature
* \param eckey EC_KEY object containing a public EC key
* \return 1 if the signature is valid, 0 if the signature is invalid
* and -1 on error
*/
int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
const unsigned char *sig, int siglen, EC_KEY *eckey);
/** Returns the maximum length of the DER encoded signature
* \param eckey EC_KEY object
* \return numbers of bytes required for the DER encoded signature
*/
int ECDSA_size(const EC_KEY *eckey);
/********************************************************************/
/* EC_KEY_METHOD constructors, destructors, writers and accessors */
/********************************************************************/
EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth);
void EC_KEY_METHOD_free(EC_KEY_METHOD *meth);
void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
int (*init)(EC_KEY *key),
void (*finish)(EC_KEY *key),
int (*copy)(EC_KEY *dest, const EC_KEY *src),
int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
int (*set_private)(EC_KEY *key,
const BIGNUM *priv_key),
int (*set_public)(EC_KEY *key,
const EC_POINT *pub_key));
void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth,
int (*keygen)(EC_KEY *key));
void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth,
int (*ckey)(unsigned char **psec,
size_t *pseclen,
const EC_POINT *pub_key,
const EC_KEY *ecdh));
void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth,
int (*sign)(int type, const unsigned char *dgst,
int dlen, unsigned char *sig,
unsigned int *siglen,
const BIGNUM *kinv, const BIGNUM *r,
EC_KEY *eckey),
int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp),
ECDSA_SIG *(*sign_sig)(const unsigned char *dgst,
int dgst_len,
const BIGNUM *in_kinv,
const BIGNUM *in_r,
EC_KEY *eckey));
void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth,
int (*verify)(int type, const unsigned
char *dgst, int dgst_len,
const unsigned char *sigbuf,
int sig_len, EC_KEY *eckey),
int (*verify_sig)(const unsigned char *dgst,
int dgst_len,
const ECDSA_SIG *sig,
EC_KEY *eckey));
void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth,
int (**pinit)(EC_KEY *key),
void (**pfinish)(EC_KEY *key),
int (**pcopy)(EC_KEY *dest, const EC_KEY *src),
int (**pset_group)(EC_KEY *key,
const EC_GROUP *grp),
int (**pset_private)(EC_KEY *key,
const BIGNUM *priv_key),
int (**pset_public)(EC_KEY *key,
const EC_POINT *pub_key));
void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth,
int (**pkeygen)(EC_KEY *key));
void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth,
int (**pck)(unsigned char **psec,
size_t *pseclen,
const EC_POINT *pub_key,
const EC_KEY *ecdh));
void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth,
int (**psign)(int type, const unsigned char *dgst,
int dlen, unsigned char *sig,
unsigned int *siglen,
const BIGNUM *kinv, const BIGNUM *r,
EC_KEY *eckey),
int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp),
ECDSA_SIG *(**psign_sig)(const unsigned char *dgst,
int dgst_len,
const BIGNUM *in_kinv,
const BIGNUM *in_r,
EC_KEY *eckey));
void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth,
int (**pverify)(int type, const unsigned
char *dgst, int dgst_len,
const unsigned char *sigbuf,
int sig_len, EC_KEY *eckey),
int (**pverify_sig)(const unsigned char *dgst,
int dgst_len,
const ECDSA_SIG *sig,
EC_KEY *eckey));
# define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
# ifndef __cplusplus
# if defined(__SUNPRO_C)
# if __SUNPRO_C >= 0x520
# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
# endif
# endif
# endif
# define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
# define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL)
# define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL)
# define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL)
# define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL)
# define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL)
# define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md))
# define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd))
# define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL)
# define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, \
(void *)(plen))
# define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)(p))
# define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
EVP_PKEY_OP_DERIVE, \
EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)(p))
/* SM2 will skip the operation check so no need to pass operation here */
# define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \
EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id))
# define EVP_PKEY_CTX_get1_id(ctx, id) \
EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id))
# define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \
EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len))
# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
# define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2)
# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3)
# define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4)
# define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5)
# define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6)
# define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7)
# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8)
# define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9)
# define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10)
# define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11)
# define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12)
# define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13)
/* KDF types */
# define EVP_PKEY_ECDH_KDF_NONE 1
-# define EVP_PKEY_ECDH_KDF_X9_62 2
+# define EVP_PKEY_ECDH_KDF_X9_63 2
+/** The old name for EVP_PKEY_ECDH_KDF_X9_63
+ * The ECDH KDF specification has been mistakingly attributed to ANSI X9.62,
+ * it is actually specified in ANSI X9.63.
+ * This identifier is retained for backwards compatibility
+ */
+# define EVP_PKEY_ECDH_KDF_X9_62 EVP_PKEY_ECDH_KDF_X9_63
# ifdef __cplusplus
}
# endif
# endif
#endif
diff --git a/include/openssl/ocsp.h b/include/openssl/ocsp.h
index 937b32271b21..0a17166b5bf6 100644
--- a/include/openssl/ocsp.h
+++ b/include/openssl/ocsp.h
@@ -1,355 +1,352 @@
/*
* Copyright 2000-2018 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)
-DECLARE_ASN1_FUNCTIONS(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_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it,
- ASN1_VALUE *val);
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_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 9e66fc13faab..af7a3b564e9d 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.
*
* 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 0x1010100fL
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1 11 Sep 2018"
+# define OPENSSL_VERSION_NUMBER 0x1010101fL
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1a 20 Nov 2018"
/*-
* 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/rand_drbg.h b/include/openssl/rand_drbg.h
index 282356e16176..45b731b73c26 100644
--- a/include/openssl/rand_drbg.h
+++ b/include/openssl/rand_drbg.h
@@ -1,120 +1,130 @@
/*
* Copyright 2017-2018 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_DRBG_RAND_H
# define HEADER_DRBG_RAND_H
# include <time.h>
# include <openssl/ossl_typ.h>
+# include <openssl/obj_mac.h>
+/*
+ * RAND_DRBG flags
+ *
+ * Note: if new flags are added, the constant `rand_drbg_used_flags`
+ * in drbg_lib.c needs to be updated accordingly.
+ */
/* In CTR mode, disable derivation function ctr_df */
# define RAND_DRBG_FLAG_CTR_NO_DF 0x1
-/* A logical OR of all used flag bits (currently there is only one) */
-# define RAND_DRBG_USED_FLAGS ( \
- RAND_DRBG_FLAG_CTR_NO_DF \
- )
+
+# if OPENSSL_API_COMPAT < 0x10200000L
+/* This #define was replaced by an internal constant and should not be used. */
+# define RAND_DRBG_USED_FLAGS (RAND_DRBG_FLAG_CTR_NO_DF)
+# endif
/*
* Default security strength (in the sense of [NIST SP 800-90Ar1])
*
* NIST SP 800-90Ar1 supports the strength of the DRBG being smaller than that
- * of the cipher by collecting less entropy. The current DRBG implemantion does
- * not take RAND_DRBG_STRENGTH into account and sets the strength of the DRBG
- * to that of the cipher.
+ * of the cipher by collecting less entropy. The current DRBG implementation
+ * does not take RAND_DRBG_STRENGTH into account and sets the strength of the
+ * DRBG to that of the cipher.
*
* RAND_DRBG_STRENGTH is currently only used for the legacy RAND
* implementation.
*
* Currently supported ciphers are: NID_aes_128_ctr, NID_aes_192_ctr and
* NID_aes_256_ctr
*/
# define RAND_DRBG_STRENGTH 256
+/* Default drbg type */
# define RAND_DRBG_TYPE NID_aes_256_ctr
+/* Default drbg flags */
# define RAND_DRBG_FLAGS 0
# ifdef __cplusplus
extern "C" {
# endif
/*
* Object lifetime functions.
*/
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);
/*
* Object "use" functions.
*/
int RAND_DRBG_reseed(RAND_DRBG *drbg,
const unsigned char *adin, size_t adinlen,
int prediction_resistance);
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);
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
);
RAND_DRBG *RAND_DRBG_get0_master(void);
RAND_DRBG *RAND_DRBG_get0_public(void);
RAND_DRBG *RAND_DRBG_get0_private(void);
/*
* EXDATA
*/
# define RAND_DRBG_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DRBG, l, p, newf, dupf, freef)
int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg);
void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx);
/*
* Callback function typedefs
*/
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 *ctx,
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);
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);
# ifdef __cplusplus
}
# endif
#endif
diff --git a/include/openssl/randerr.h b/include/openssl/randerr.h
index 128f4dea751c..599a2a18d41f 100644
--- a/include/openssl/randerr.h
+++ b/include/openssl/randerr.h
@@ -1,88 +1,89 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 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_RANDERR_H
# define HEADER_RANDERR_H
# ifdef __cplusplus
extern "C"
# endif
int ERR_load_RAND_strings(void);
/*
* RAND function codes.
*/
# define RAND_F_DRBG_BYTES 101
# define RAND_F_DRBG_GET_ENTROPY 105
# define RAND_F_DRBG_SETUP 117
# define RAND_F_GET_ENTROPY 106
# define RAND_F_RAND_BYTES 100
# define RAND_F_RAND_DRBG_ENABLE_LOCKING 119
# define RAND_F_RAND_DRBG_GENERATE 107
# define RAND_F_RAND_DRBG_GET_ENTROPY 120
# define RAND_F_RAND_DRBG_GET_NONCE 123
# define RAND_F_RAND_DRBG_INSTANTIATE 108
# define RAND_F_RAND_DRBG_NEW 109
# define RAND_F_RAND_DRBG_RESEED 110
# define RAND_F_RAND_DRBG_RESTART 102
# define RAND_F_RAND_DRBG_SET 104
# define RAND_F_RAND_DRBG_SET_DEFAULTS 121
# define RAND_F_RAND_DRBG_UNINSTANTIATE 118
# define RAND_F_RAND_LOAD_FILE 111
# define RAND_F_RAND_POOL_ACQUIRE_ENTROPY 122
# define RAND_F_RAND_POOL_ADD 103
# define RAND_F_RAND_POOL_ADD_BEGIN 113
# define RAND_F_RAND_POOL_ADD_END 114
+# define RAND_F_RAND_POOL_ATTACH 124
# define RAND_F_RAND_POOL_BYTES_NEEDED 115
# define RAND_F_RAND_POOL_NEW 116
# define RAND_F_RAND_WRITE_FILE 112
/*
* RAND reason codes.
*/
# define RAND_R_ADDITIONAL_INPUT_TOO_LONG 102
# define RAND_R_ALREADY_INSTANTIATED 103
# define RAND_R_ARGUMENT_OUT_OF_RANGE 105
# define RAND_R_CANNOT_OPEN_FILE 121
# define RAND_R_DRBG_ALREADY_INITIALIZED 129
# define RAND_R_DRBG_NOT_INITIALISED 104
# define RAND_R_ENTROPY_INPUT_TOO_LONG 106
# define RAND_R_ENTROPY_OUT_OF_RANGE 124
# define RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED 127
# define RAND_R_ERROR_INITIALISING_DRBG 107
# define RAND_R_ERROR_INSTANTIATING_DRBG 108
# define RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT 109
# define RAND_R_ERROR_RETRIEVING_ENTROPY 110
# define RAND_R_ERROR_RETRIEVING_NONCE 111
# define RAND_R_FAILED_TO_CREATE_LOCK 126
# define RAND_R_FUNC_NOT_IMPLEMENTED 101
# define RAND_R_FWRITE_ERROR 123
# define RAND_R_GENERATE_ERROR 112
# define RAND_R_INTERNAL_ERROR 113
# define RAND_R_IN_ERROR_STATE 114
# define RAND_R_NOT_A_REGULAR_FILE 122
# define RAND_R_NOT_INSTANTIATED 115
# define RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED 128
# define RAND_R_PARENT_LOCKING_NOT_ENABLED 130
# define RAND_R_PARENT_STRENGTH_TOO_WEAK 131
# define RAND_R_PERSONALISATION_STRING_TOO_LONG 116
# define RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED 133
# define RAND_R_PRNG_NOT_SEEDED 100
# define RAND_R_RANDOM_POOL_OVERFLOW 125
# define RAND_R_RANDOM_POOL_UNDERFLOW 134
# define RAND_R_REQUEST_TOO_LARGE_FOR_DRBG 117
# define RAND_R_RESEED_ERROR 118
# define RAND_R_SELFTEST_FAILURE 119
# define RAND_R_TOO_LITTLE_NONCE_REQUESTED 135
# define RAND_R_TOO_MUCH_NONCE_REQUESTED 136
# define RAND_R_UNSUPPORTED_DRBG_FLAGS 132
# define RAND_R_UNSUPPORTED_DRBG_TYPE 120
#endif
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index a611b6a0be92..cdce1264eb5c 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -1,512 +1,512 @@
/*
* Copyright 1995-2018 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_RSA_H
# define HEADER_RSA_H
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_RSA
# include <openssl/asn1.h>
# include <openssl/bio.h>
# include <openssl/crypto.h>
# include <openssl/ossl_typ.h>
# if OPENSSL_API_COMPAT < 0x10100000L
# include <openssl/bn.h>
# endif
# include <openssl/rsaerr.h>
# ifdef __cplusplus
extern "C" {
# endif
/* The types RSA and RSA_METHOD are defined in ossl_typ.h */
# ifndef OPENSSL_RSA_MAX_MODULUS_BITS
# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
# endif
# define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 1024
# ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
# endif
# ifndef OPENSSL_RSA_MAX_PUBEXP_BITS
/* exponent limit enforced for "large" modulus only */
# define OPENSSL_RSA_MAX_PUBEXP_BITS 64
# endif
# define RSA_3 0x3L
# define RSA_F4 0x10001L
/* based on RFC 8017 appendix A.1.2 */
# define RSA_ASN1_VERSION_DEFAULT 0
# define RSA_ASN1_VERSION_MULTI 1
# define RSA_DEFAULT_PRIME_NUM 2
# define RSA_METHOD_FLAG_NO_CHECK 0x0001/* don't check pub/private
* match */
# define RSA_FLAG_CACHE_PUBLIC 0x0002
# define RSA_FLAG_CACHE_PRIVATE 0x0004
# define RSA_FLAG_BLINDING 0x0008
# define RSA_FLAG_THREAD_SAFE 0x0010
/*
* This flag means the private key operations will be handled by rsa_mod_exp
* and that they do not depend on the private key components being present:
* for example a key stored in external hardware. Without this flag
* bn_mod_exp gets called when private key components are absent.
*/
# define RSA_FLAG_EXT_PKEY 0x0020
/*
* new with 0.9.6j and 0.9.7b; the built-in
* RSA implementation now uses blinding by
* default (ignoring RSA_FLAG_BLINDING),
* but other engines might not need it
*/
# define RSA_FLAG_NO_BLINDING 0x0080
# if OPENSSL_API_COMPAT < 0x10100000L
/*
* Does nothing. Previously this switched off constant time behaviour.
*/
# define RSA_FLAG_NO_CONSTTIME 0x0000
# endif
# if OPENSSL_API_COMPAT < 0x00908000L
/* deprecated name for the flag*/
/*
* new with 0.9.7h; the built-in RSA
* implementation now uses constant time
* modular exponentiation for secret exponents
* by default. This flag causes the
* faster variable sliding window method to
* be used for all exponents.
*/
# define RSA_FLAG_NO_EXP_CONSTTIME RSA_FLAG_NO_CONSTTIME
# endif
# define EVP_PKEY_CTX_set_rsa_padding(ctx, pad) \
RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL)
# define EVP_PKEY_CTX_get_rsa_padding(ctx, ppad) \
RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad)
# define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \
RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
/* Salt length matches digest */
# define RSA_PSS_SALTLEN_DIGEST -1
/* Verify only: auto detect salt length */
# define RSA_PSS_SALTLEN_AUTO -2
/* Set salt length to maximum possible */
# define RSA_PSS_SALTLEN_MAX -3
/* Old compatible max salt length for sign only */
# define RSA_PSS_SALTLEN_MAX_SIGN -2
# define EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, len) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
# define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \
RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, plen)
# define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
# define EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp) \
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp)
# define EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) \
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes, NULL)
# define EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) \
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md))
# define EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx, md) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md))
# define EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \
EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)(md))
# define EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, pmd) \
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)(pmd))
# define EVP_PKEY_CTX_get_rsa_oaep_md(ctx, pmd) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \
EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)(pmd))
# define EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, l, llen) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \
EVP_PKEY_CTRL_RSA_OAEP_LABEL, llen, (void *)(l))
# define EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, l) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \
EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *)(l))
# define EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, \
- EVP_PKEY_OP_TYPE_KEYGEN, EVP_PKEY_CTRL_MD, \
+ EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD, \
0, (void *)(md))
# define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1)
# define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 2)
# define EVP_PKEY_CTRL_RSA_KEYGEN_BITS (EVP_PKEY_ALG_CTRL + 3)
# define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP (EVP_PKEY_ALG_CTRL + 4)
# define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 5)
# define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 6)
# define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 7)
# define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 8)
# define EVP_PKEY_CTRL_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 9)
# define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 10)
# define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 11)
# define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
# define EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES (EVP_PKEY_ALG_CTRL + 13)
# define RSA_PKCS1_PADDING 1
# define RSA_SSLV23_PADDING 2
# define RSA_NO_PADDING 3
# define RSA_PKCS1_OAEP_PADDING 4
# define RSA_X931_PADDING 5
/* EVP_PKEY_ only */
# define RSA_PKCS1_PSS_PADDING 6
# define RSA_PKCS1_PADDING_SIZE 11
# define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg)
# define RSA_get_app_data(s) RSA_get_ex_data(s,0)
RSA *RSA_new(void);
RSA *RSA_new_method(ENGINE *engine);
int RSA_bits(const RSA *rsa);
int RSA_size(const RSA *rsa);
int RSA_security_bits(const RSA *rsa);
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
int RSA_set0_crt_params(RSA *r,BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
BIGNUM *coeffs[], int pnum);
void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
int RSA_get_multi_prime_extra_count(const RSA *r);
int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[]);
void RSA_get0_crt_params(const RSA *r,
const BIGNUM **dmp1, const BIGNUM **dmq1,
const BIGNUM **iqmp);
int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
const BIGNUM *coeffs[]);
const BIGNUM *RSA_get0_n(const RSA *d);
const BIGNUM *RSA_get0_e(const RSA *d);
const BIGNUM *RSA_get0_d(const RSA *d);
const BIGNUM *RSA_get0_p(const RSA *d);
const BIGNUM *RSA_get0_q(const RSA *d);
const BIGNUM *RSA_get0_dmp1(const RSA *r);
const BIGNUM *RSA_get0_dmq1(const RSA *r);
const BIGNUM *RSA_get0_iqmp(const RSA *r);
void RSA_clear_flags(RSA *r, int flags);
int RSA_test_flags(const RSA *r, int flags);
void RSA_set_flags(RSA *r, int flags);
int RSA_get_version(RSA *r);
ENGINE *RSA_get0_engine(const RSA *r);
/* Deprecated version */
DEPRECATEDIN_0_9_8(RSA *RSA_generate_key(int bits, unsigned long e, void
(*callback) (int, int, void *),
void *cb_arg))
/* New version */
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
/* Multi-prime version */
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
BIGNUM *e, BN_GENCB *cb);
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);
int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
BN_GENCB *cb);
int RSA_check_key(const RSA *);
int RSA_check_key_ex(const RSA *, BN_GENCB *cb);
/* next 4 return -1 on error */
int RSA_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_public_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
void RSA_free(RSA *r);
/* "up" the RSA object's reference count */
int RSA_up_ref(RSA *r);
int RSA_flags(const RSA *r);
void RSA_set_default_method(const RSA_METHOD *meth);
const RSA_METHOD *RSA_get_default_method(void);
const RSA_METHOD *RSA_null_method(void);
const RSA_METHOD *RSA_get_method(const RSA *rsa);
int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
/* these are the actual RSA functions */
const RSA_METHOD *RSA_PKCS1_OpenSSL(void);
int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2);
DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey)
DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey)
typedef struct rsa_pss_params_st {
X509_ALGOR *hashAlgorithm;
X509_ALGOR *maskGenAlgorithm;
ASN1_INTEGER *saltLength;
ASN1_INTEGER *trailerField;
/* Decoded hash algorithm from maskGenAlgorithm */
X509_ALGOR *maskHash;
} RSA_PSS_PARAMS;
DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
typedef struct rsa_oaep_params_st {
X509_ALGOR *hashFunc;
X509_ALGOR *maskGenFunc;
X509_ALGOR *pSourceFunc;
/* Decoded hash algorithm from maskGenFunc */
X509_ALGOR *maskHash;
} RSA_OAEP_PARAMS;
DECLARE_ASN1_FUNCTIONS(RSA_OAEP_PARAMS)
# ifndef OPENSSL_NO_STDIO
int RSA_print_fp(FILE *fp, const RSA *r, int offset);
# endif
int RSA_print(BIO *bp, const RSA *r, int offset);
/*
* The following 2 functions sign and verify a X509_SIG ASN1 object inside
* PKCS#1 padded RSA encryption
*/
int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen, RSA *rsa);
int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
const unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
/*
* The following 2 function sign and verify a ASN1_OCTET_STRING object inside
* PKCS#1 padded RSA encryption
*/
int RSA_sign_ASN1_OCTET_STRING(int type,
const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,
RSA *rsa);
int RSA_verify_ASN1_OCTET_STRING(int type, const unsigned char *m,
unsigned int m_length, unsigned char *sigbuf,
unsigned int siglen, RSA *rsa);
int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
void RSA_blinding_off(RSA *rsa);
BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *f, int fl);
int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *f, int fl,
int rsa_len);
int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
const unsigned char *f, int fl);
int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
const unsigned char *f, int fl,
int rsa_len);
int PKCS1_MGF1(unsigned char *mask, long len, const unsigned char *seed,
long seedlen, const EVP_MD *dgst);
int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *f, int fl,
const unsigned char *p, int pl);
int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
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 *from, int flen,
const unsigned char *param, int plen,
const EVP_MD *md, const EVP_MD *mgf1md);
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 RSA_padding_add_SSLv23(unsigned char *to, int tlen,
const unsigned char *f, int fl);
int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
const unsigned char *f, int fl, int rsa_len);
int RSA_padding_add_none(unsigned char *to, int tlen, const unsigned char *f,
int fl);
int RSA_padding_check_none(unsigned char *to, int tlen,
const unsigned char *f, int fl, int rsa_len);
int RSA_padding_add_X931(unsigned char *to, int tlen, const unsigned char *f,
int fl);
int RSA_padding_check_X931(unsigned char *to, int tlen,
const unsigned char *f, int fl, int rsa_len);
int RSA_X931_hash_id(int nid);
int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
const EVP_MD *Hash, const unsigned char *EM,
int sLen);
int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
const unsigned char *mHash, const EVP_MD *Hash,
int sLen);
int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
const unsigned char *EM, int sLen);
int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
const unsigned char *mHash,
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
int sLen);
#define RSA_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, l, p, newf, dupf, freef)
int RSA_set_ex_data(RSA *r, int idx, void *arg);
void *RSA_get_ex_data(const RSA *r, int idx);
RSA *RSAPublicKey_dup(RSA *rsa);
RSA *RSAPrivateKey_dup(RSA *rsa);
/*
* If this flag is set the RSA method is FIPS compliant and can be used in
* FIPS mode. This is set in the validated module method. If an application
* sets this flag in its own methods it is its responsibility to ensure the
* result is compliant.
*/
# define RSA_FLAG_FIPS_METHOD 0x0400
/*
* If this flag is set the operations normally disabled in FIPS mode are
* permitted it is then the applications responsibility to ensure that the
* usage is compliant.
*/
# define RSA_FLAG_NON_FIPS_ALLOW 0x0400
/*
* Application has decided PRNG is good enough to generate a key: don't
* check.
*/
# define RSA_FLAG_CHECKED 0x0800
RSA_METHOD *RSA_meth_new(const char *name, int flags);
void RSA_meth_free(RSA_METHOD *meth);
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
const char *RSA_meth_get0_name(const RSA_METHOD *meth);
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
int RSA_meth_get_flags(const RSA_METHOD *meth);
int RSA_meth_set_flags(RSA_METHOD *meth, int flags);
void *RSA_meth_get0_app_data(const RSA_METHOD *meth);
int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data);
int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_meth_set_pub_enc(RSA_METHOD *rsa,
int (*pub_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_meth_set_pub_dec(RSA_METHOD *rsa,
int (*pub_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_meth_set_priv_enc(RSA_METHOD *rsa,
int (*priv_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth))
(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_meth_set_priv_dec(RSA_METHOD *rsa,
int (*priv_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth))
- (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+ (BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx);
int RSA_meth_set_mod_exp(RSA_METHOD *rsa,
- int (*mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+ int (*mod_exp) (BIGNUM *r0, const BIGNUM *i, RSA *rsa,
BN_CTX *ctx));
int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth))
(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int RSA_meth_set_bn_mod_exp(RSA_METHOD *rsa,
int (*bn_mod_exp) (BIGNUM *r,
const BIGNUM *a,
const BIGNUM *p,
const BIGNUM *m,
BN_CTX *ctx,
BN_MONT_CTX *m_ctx));
int (*RSA_meth_get_init(const RSA_METHOD *meth)) (RSA *rsa);
int RSA_meth_set_init(RSA_METHOD *rsa, int (*init) (RSA *rsa));
int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa);
int RSA_meth_set_finish(RSA_METHOD *rsa, int (*finish) (RSA *rsa));
int (*RSA_meth_get_sign(const RSA_METHOD *meth))
(int type,
const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,
const RSA *rsa);
int RSA_meth_set_sign(RSA_METHOD *rsa,
int (*sign) (int type, const unsigned char *m,
unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,
const RSA *rsa));
int (*RSA_meth_get_verify(const RSA_METHOD *meth))
(int dtype, const unsigned char *m,
unsigned int m_length, const unsigned char *sigbuf,
unsigned int siglen, const RSA *rsa);
int RSA_meth_set_verify(RSA_METHOD *rsa,
int (*verify) (int dtype, const unsigned char *m,
unsigned int m_length,
const unsigned char *sigbuf,
unsigned int siglen, const RSA *rsa));
int (*RSA_meth_get_keygen(const RSA_METHOD *meth))
(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
int RSA_meth_set_keygen(RSA_METHOD *rsa,
int (*keygen) (RSA *rsa, int bits, BIGNUM *e,
BN_GENCB *cb));
int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth))
(RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb);
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb));
# ifdef __cplusplus
}
# endif
# endif
#endif
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 0a18a43544cb..d6b1b4e6a670 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1,2413 +1,2425 @@
/*
* Copyright 1995-2018 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
/* 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_SERVER_TMP_KEY 109
+# 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_server_tmp_key(s, pk) \
- SSL_ctrl(s,SSL_CTRL_GET_SERVER_TMP_KEY,0,pk)
+# 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(SSL *s);
int SSL_renegotiate(SSL *s);
int SSL_renegotiate_abbreviated(SSL *s);
__owur int SSL_renegotiate_pending(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(SSL_CTX *ctx);
__owur const SSL_METHOD *SSL_get_ssl_method(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(SSL *s);
__owur const COMP_METHOD *SSL_get_current_expansion(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(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(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(SSL *s);
int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
size_t SSL_CTX_get_num_tickets(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_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/symhacks.h b/include/openssl/symhacks.h
index caf1f1a75d02..156ea6e4ee95 100644
--- a/include/openssl/symhacks.h
+++ b/include/openssl/symhacks.h
@@ -1,52 +1,37 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2018 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_SYMHACKS_H
# define HEADER_SYMHACKS_H
# include <openssl/e_os2.h>
/* Case insensitive linking causes problems.... */
# if defined(OPENSSL_SYS_VMS)
# undef ERR_load_CRYPTO_strings
# define ERR_load_CRYPTO_strings ERR_load_CRYPTOlib_strings
# undef OCSP_crlID_new
# define OCSP_crlID_new OCSP_crlID2_new
# undef d2i_ECPARAMETERS
# define d2i_ECPARAMETERS d2i_UC_ECPARAMETERS
# undef i2d_ECPARAMETERS
# define i2d_ECPARAMETERS i2d_UC_ECPARAMETERS
# undef d2i_ECPKPARAMETERS
# define d2i_ECPKPARAMETERS d2i_UC_ECPKPARAMETERS
# undef i2d_ECPKPARAMETERS
# define i2d_ECPKPARAMETERS i2d_UC_ECPKPARAMETERS
-/*
- * These functions do not seem to exist! However, I'm paranoid... Original
- * command in x509v3.h: These functions are being redefined in another
- * directory, and clash when the linker is case-insensitive, so let's hide
- * them a little, by giving them an extra 'o' at the beginning of the name...
- */
-# undef X509v3_cleanup_extensions
-# define X509v3_cleanup_extensions oX509v3_cleanup_extensions
-# undef X509v3_add_extension
-# define X509v3_add_extension oX509v3_add_extension
-# undef X509v3_add_netscape_extensions
-# define X509v3_add_netscape_extensions oX509v3_add_netscape_extensions
-# undef X509v3_add_standard_extensions
-# define X509v3_add_standard_extensions oX509v3_add_standard_extensions
-
/* This one clashes with CMS_data_create */
# undef cms_Data_create
# define cms_Data_create priv_cms_Data_create
# endif
#endif /* ! defined HEADER_VMS_IDHACKS_H */
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 2e46cf80d342..e13b5dd4bc65 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -1,1236 +1,1237 @@
/*
* Copyright 1995-2018 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_TLS1_H
# define HEADER_TLS1_H
# include <openssl/buffer.h>
# include <openssl/x509.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Default security level if not overridden at config time */
# ifndef OPENSSL_TLS_SECURITY_LEVEL
# define OPENSSL_TLS_SECURITY_LEVEL 1
# endif
# define TLS1_VERSION 0x0301
# define TLS1_1_VERSION 0x0302
# define TLS1_2_VERSION 0x0303
# define TLS1_3_VERSION 0x0304
# define TLS_MAX_VERSION TLS1_3_VERSION
/* Special value for method supporting multiple versions */
# define TLS_ANY_VERSION 0x10000
# define TLS1_VERSION_MAJOR 0x03
# define TLS1_VERSION_MINOR 0x01
# define TLS1_1_VERSION_MAJOR 0x03
# define TLS1_1_VERSION_MINOR 0x02
# define TLS1_2_VERSION_MAJOR 0x03
# define TLS1_2_VERSION_MINOR 0x03
# define TLS1_get_version(s) \
((SSL_version(s) >> 8) == TLS1_VERSION_MAJOR ? SSL_version(s) : 0)
# define TLS1_get_client_version(s) \
((SSL_client_version(s) >> 8) == TLS1_VERSION_MAJOR ? SSL_client_version(s) : 0)
# define TLS1_AD_DECRYPTION_FAILED 21
# define TLS1_AD_RECORD_OVERFLOW 22
# define TLS1_AD_UNKNOWN_CA 48/* fatal */
# define TLS1_AD_ACCESS_DENIED 49/* fatal */
# define TLS1_AD_DECODE_ERROR 50/* fatal */
# define TLS1_AD_DECRYPT_ERROR 51
# define TLS1_AD_EXPORT_RESTRICTION 60/* fatal */
# define TLS1_AD_PROTOCOL_VERSION 70/* fatal */
# define TLS1_AD_INSUFFICIENT_SECURITY 71/* fatal */
# define TLS1_AD_INTERNAL_ERROR 80/* fatal */
# define TLS1_AD_INAPPROPRIATE_FALLBACK 86/* fatal */
# define TLS1_AD_USER_CANCELLED 90
# define TLS1_AD_NO_RENEGOTIATION 100
/* TLSv1.3 alerts */
# define TLS13_AD_MISSING_EXTENSION 109 /* fatal */
# define TLS13_AD_CERTIFICATE_REQUIRED 116 /* fatal */
/* codes 110-114 are from RFC3546 */
# define TLS1_AD_UNSUPPORTED_EXTENSION 110
# define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
# define TLS1_AD_UNRECOGNIZED_NAME 112
# define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
# define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
# define TLS1_AD_UNKNOWN_PSK_IDENTITY 115/* fatal */
# define TLS1_AD_NO_APPLICATION_PROTOCOL 120 /* fatal */
/* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */
# define TLSEXT_TYPE_server_name 0
# define TLSEXT_TYPE_max_fragment_length 1
# define TLSEXT_TYPE_client_certificate_url 2
# define TLSEXT_TYPE_trusted_ca_keys 3
# define TLSEXT_TYPE_truncated_hmac 4
# define TLSEXT_TYPE_status_request 5
/* ExtensionType values from RFC4681 */
# define TLSEXT_TYPE_user_mapping 6
/* ExtensionType values from RFC5878 */
# define TLSEXT_TYPE_client_authz 7
# define TLSEXT_TYPE_server_authz 8
/* ExtensionType values from RFC6091 */
# define TLSEXT_TYPE_cert_type 9
/* ExtensionType values from RFC4492 */
/*
* Prior to TLSv1.3 the supported_groups extension was known as
* elliptic_curves
*/
# define TLSEXT_TYPE_supported_groups 10
# define TLSEXT_TYPE_elliptic_curves TLSEXT_TYPE_supported_groups
# define TLSEXT_TYPE_ec_point_formats 11
/* ExtensionType value from RFC5054 */
# define TLSEXT_TYPE_srp 12
/* ExtensionType values from RFC5246 */
# define TLSEXT_TYPE_signature_algorithms 13
/* ExtensionType value from RFC5764 */
# define TLSEXT_TYPE_use_srtp 14
/* ExtensionType value from RFC5620 */
# define TLSEXT_TYPE_heartbeat 15
/* ExtensionType value from RFC7301 */
# define TLSEXT_TYPE_application_layer_protocol_negotiation 16
/*
* Extension type for Certificate Transparency
* https://tools.ietf.org/html/rfc6962#section-3.3.1
*/
# define TLSEXT_TYPE_signed_certificate_timestamp 18
/*
* ExtensionType value for TLS padding extension.
* http://tools.ietf.org/html/draft-agl-tls-padding
*/
# define TLSEXT_TYPE_padding 21
/* ExtensionType value from RFC7366 */
# define TLSEXT_TYPE_encrypt_then_mac 22
/* ExtensionType value from RFC7627 */
# define TLSEXT_TYPE_extended_master_secret 23
/* ExtensionType value from RFC4507 */
# define TLSEXT_TYPE_session_ticket 35
/* As defined for TLS1.3 */
# define TLSEXT_TYPE_psk 41
# define TLSEXT_TYPE_early_data 42
# define TLSEXT_TYPE_supported_versions 43
# define TLSEXT_TYPE_cookie 44
# define TLSEXT_TYPE_psk_kex_modes 45
# define TLSEXT_TYPE_certificate_authorities 47
# define TLSEXT_TYPE_post_handshake_auth 49
# define TLSEXT_TYPE_signature_algorithms_cert 50
# define TLSEXT_TYPE_key_share 51
/* Temporary extension type */
# define TLSEXT_TYPE_renegotiate 0xff01
# ifndef OPENSSL_NO_NEXTPROTONEG
/* This is not an IANA defined extension number */
# define TLSEXT_TYPE_next_proto_neg 13172
# endif
/* NameType value from RFC3546 */
# define TLSEXT_NAMETYPE_host_name 0
/* status request value from RFC3546 */
# define TLSEXT_STATUSTYPE_ocsp 1
/* ECPointFormat values from RFC4492 */
# define TLSEXT_ECPOINTFORMAT_first 0
# define TLSEXT_ECPOINTFORMAT_uncompressed 0
# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1
# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2
# define TLSEXT_ECPOINTFORMAT_last 2
/* Signature and hash algorithms from RFC5246 */
# define TLSEXT_signature_anonymous 0
# define TLSEXT_signature_rsa 1
# define TLSEXT_signature_dsa 2
# define TLSEXT_signature_ecdsa 3
# define TLSEXT_signature_gostr34102001 237
# define TLSEXT_signature_gostr34102012_256 238
# define TLSEXT_signature_gostr34102012_512 239
/* Total number of different signature algorithms */
# define TLSEXT_signature_num 7
# define TLSEXT_hash_none 0
# define TLSEXT_hash_md5 1
# define TLSEXT_hash_sha1 2
# define TLSEXT_hash_sha224 3
# define TLSEXT_hash_sha256 4
# define TLSEXT_hash_sha384 5
# define TLSEXT_hash_sha512 6
# define TLSEXT_hash_gostr3411 237
# define TLSEXT_hash_gostr34112012_256 238
# define TLSEXT_hash_gostr34112012_512 239
/* Total number of different digest algorithms */
# define TLSEXT_hash_num 10
/* Flag set for unrecognised algorithms */
# define TLSEXT_nid_unknown 0x1000000
/* ECC curves */
# define TLSEXT_curve_P_256 23
# define TLSEXT_curve_P_384 24
/* OpenSSL value to disable maximum fragment length extension */
# define TLSEXT_max_fragment_length_DISABLED 0
/* Allowed values for max fragment length extension */
# define TLSEXT_max_fragment_length_512 1
# define TLSEXT_max_fragment_length_1024 2
# define TLSEXT_max_fragment_length_2048 3
# define TLSEXT_max_fragment_length_4096 4
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);
# define TLSEXT_MAXLEN_host_name 255
__owur const char *SSL_get_servername(const SSL *s, const int type);
__owur int SSL_get_servername_type(const SSL *s);
/*
* SSL_export_keying_material exports a value derived from the master secret,
* as specified in RFC 5705. It writes |olen| bytes to |out| given a label and
* optional context. (Since a zero length context is allowed, the |use_context|
* flag controls whether a context is included.) It returns 1 on success and
* 0 or -1 otherwise.
*/
__owur 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);
/*
* SSL_export_keying_material_early exports a value derived from the
* early exporter master secret, as specified in
* https://tools.ietf.org/html/draft-ietf-tls-tls13-23. It writes
* |olen| bytes to |out| given a label and optional context. It
* returns 1 on success and 0 otherwise.
*/
__owur 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);
int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid);
+int SSL_get_signature_type_nid(const SSL *s, int *pnid);
int SSL_get_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignandhash,
unsigned char *rsig, unsigned char *rhash);
int SSL_get_shared_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignandhash,
unsigned char *rsig, unsigned char *rhash);
__owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain);
# define SSL_set_tlsext_host_name(s,name) \
SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,\
(void *)name)
# define SSL_set_tlsext_debug_callback(ssl, cb) \
SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,\
(void (*)(void))cb)
# define SSL_set_tlsext_debug_arg(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0,arg)
# define SSL_get_tlsext_status_type(ssl) \
SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE,0,NULL)
# define SSL_set_tlsext_status_type(ssl, type) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type,NULL)
# define SSL_get_tlsext_status_exts(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0,arg)
# define SSL_set_tlsext_status_exts(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0,arg)
# define SSL_get_tlsext_status_ids(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0,arg)
# define SSL_set_tlsext_status_ids(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0,arg)
# define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0,arg)
# define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen,arg)
# define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,\
(void (*)(void))cb)
# define SSL_TLSEXT_ERR_OK 0
# define SSL_TLSEXT_ERR_ALERT_WARNING 1
# define SSL_TLSEXT_ERR_ALERT_FATAL 2
# define SSL_TLSEXT_ERR_NOACK 3
# define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0,arg)
# define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_TLSEXT_TICKET_KEYS,keylen,keys)
# define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_TICKET_KEYS,keylen,keys)
# define SSL_CTX_get_tlsext_status_cb(ssl, cb) \
SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB,0,(void *)cb)
# define SSL_CTX_set_tlsext_status_cb(ssl, cb) \
SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,\
(void (*)(void))cb)
# define SSL_CTX_get_tlsext_status_arg(ssl, arg) \
SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG,0,arg)
# define SSL_CTX_set_tlsext_status_arg(ssl, arg) \
SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0,arg)
# define SSL_CTX_set_tlsext_status_type(ssl, type) \
SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type,NULL)
# define SSL_CTX_get_tlsext_status_type(ssl) \
SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE,0,NULL)
# define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \
SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,\
(void (*)(void))cb)
# ifndef OPENSSL_NO_HEARTBEATS
# define SSL_DTLSEXT_HB_ENABLED 0x01
# define SSL_DTLSEXT_HB_DONT_SEND_REQUESTS 0x02
# define SSL_DTLSEXT_HB_DONT_RECV_REQUESTS 0x04
# define SSL_get_dtlsext_heartbeat_pending(ssl) \
SSL_ctrl(ssl,SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING,0,NULL)
# define SSL_set_dtlsext_heartbeat_no_requests(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS,arg,NULL)
# if OPENSSL_API_COMPAT < 0x10100000L
# define SSL_CTRL_TLS_EXT_SEND_HEARTBEAT \
SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT
# define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING \
SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING
# define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS \
SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS
# define SSL_TLSEXT_HB_ENABLED \
SSL_DTLSEXT_HB_ENABLED
# define SSL_TLSEXT_HB_DONT_SEND_REQUESTS \
SSL_DTLSEXT_HB_DONT_SEND_REQUESTS
# define SSL_TLSEXT_HB_DONT_RECV_REQUESTS \
SSL_DTLSEXT_HB_DONT_RECV_REQUESTS
# define SSL_get_tlsext_heartbeat_pending(ssl) \
SSL_get_dtlsext_heartbeat_pending(ssl)
# define SSL_set_tlsext_heartbeat_no_requests(ssl, arg) \
SSL_set_dtlsext_heartbeat_no_requests(ssl,arg)
# endif
# endif
/* PSK ciphersuites from 4279 */
# define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A
# define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008B
# define TLS1_CK_PSK_WITH_AES_128_CBC_SHA 0x0300008C
# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA 0x0300008D
# define TLS1_CK_DHE_PSK_WITH_RC4_128_SHA 0x0300008E
# define TLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008F
# define TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA 0x03000090
# define TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA 0x03000091
# define TLS1_CK_RSA_PSK_WITH_RC4_128_SHA 0x03000092
# define TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x03000093
# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA 0x03000094
# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA 0x03000095
/* PSK ciphersuites from 5487 */
# define TLS1_CK_PSK_WITH_AES_128_GCM_SHA256 0x030000A8
# define TLS1_CK_PSK_WITH_AES_256_GCM_SHA384 0x030000A9
# define TLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256 0x030000AA
# define TLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384 0x030000AB
# define TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256 0x030000AC
# define TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384 0x030000AD
# define TLS1_CK_PSK_WITH_AES_128_CBC_SHA256 0x030000AE
# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA384 0x030000AF
# define TLS1_CK_PSK_WITH_NULL_SHA256 0x030000B0
# define TLS1_CK_PSK_WITH_NULL_SHA384 0x030000B1
# define TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256 0x030000B2
# define TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384 0x030000B3
# define TLS1_CK_DHE_PSK_WITH_NULL_SHA256 0x030000B4
# define TLS1_CK_DHE_PSK_WITH_NULL_SHA384 0x030000B5
# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256 0x030000B6
# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384 0x030000B7
# define TLS1_CK_RSA_PSK_WITH_NULL_SHA256 0x030000B8
# define TLS1_CK_RSA_PSK_WITH_NULL_SHA384 0x030000B9
/* NULL PSK ciphersuites from RFC4785 */
# define TLS1_CK_PSK_WITH_NULL_SHA 0x0300002C
# define TLS1_CK_DHE_PSK_WITH_NULL_SHA 0x0300002D
# define TLS1_CK_RSA_PSK_WITH_NULL_SHA 0x0300002E
/* AES ciphersuites from RFC3268 */
# define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F
# define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030
# define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031
# define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032
# define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033
# define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034
# define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035
# define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036
# define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037
# define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038
# define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039
# define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A
/* TLS v1.2 ciphersuites */
# define TLS1_CK_RSA_WITH_NULL_SHA256 0x0300003B
# define TLS1_CK_RSA_WITH_AES_128_SHA256 0x0300003C
# define TLS1_CK_RSA_WITH_AES_256_SHA256 0x0300003D
# define TLS1_CK_DH_DSS_WITH_AES_128_SHA256 0x0300003E
# define TLS1_CK_DH_RSA_WITH_AES_128_SHA256 0x0300003F
# define TLS1_CK_DHE_DSS_WITH_AES_128_SHA256 0x03000040
/* Camellia ciphersuites from RFC4132 */
# define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041
# define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042
# define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043
# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044
# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045
# define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046
/* TLS v1.2 ciphersuites */
# define TLS1_CK_DHE_RSA_WITH_AES_128_SHA256 0x03000067
# define TLS1_CK_DH_DSS_WITH_AES_256_SHA256 0x03000068
# define TLS1_CK_DH_RSA_WITH_AES_256_SHA256 0x03000069
# define TLS1_CK_DHE_DSS_WITH_AES_256_SHA256 0x0300006A
# define TLS1_CK_DHE_RSA_WITH_AES_256_SHA256 0x0300006B
# define TLS1_CK_ADH_WITH_AES_128_SHA256 0x0300006C
# define TLS1_CK_ADH_WITH_AES_256_SHA256 0x0300006D
/* Camellia ciphersuites from RFC4132 */
# define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084
# define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085
# define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086
# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087
# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088
# define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089
/* SEED ciphersuites from RFC4162 */
# define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096
# define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097
# define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098
# define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099
# define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A
# define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B
/* TLS v1.2 GCM ciphersuites from RFC5288 */
# define TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 0x0300009C
# define TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 0x0300009D
# define TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256 0x0300009E
# define TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384 0x0300009F
# define TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256 0x030000A0
# define TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384 0x030000A1
# define TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256 0x030000A2
# define TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384 0x030000A3
# define TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256 0x030000A4
# define TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384 0x030000A5
# define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256 0x030000A6
# define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384 0x030000A7
/* CCM ciphersuites from RFC6655 */
# define TLS1_CK_RSA_WITH_AES_128_CCM 0x0300C09C
# define TLS1_CK_RSA_WITH_AES_256_CCM 0x0300C09D
# define TLS1_CK_DHE_RSA_WITH_AES_128_CCM 0x0300C09E
# define TLS1_CK_DHE_RSA_WITH_AES_256_CCM 0x0300C09F
# define TLS1_CK_RSA_WITH_AES_128_CCM_8 0x0300C0A0
# define TLS1_CK_RSA_WITH_AES_256_CCM_8 0x0300C0A1
# define TLS1_CK_DHE_RSA_WITH_AES_128_CCM_8 0x0300C0A2
# define TLS1_CK_DHE_RSA_WITH_AES_256_CCM_8 0x0300C0A3
# define TLS1_CK_PSK_WITH_AES_128_CCM 0x0300C0A4
# define TLS1_CK_PSK_WITH_AES_256_CCM 0x0300C0A5
# define TLS1_CK_DHE_PSK_WITH_AES_128_CCM 0x0300C0A6
# define TLS1_CK_DHE_PSK_WITH_AES_256_CCM 0x0300C0A7
# define TLS1_CK_PSK_WITH_AES_128_CCM_8 0x0300C0A8
# define TLS1_CK_PSK_WITH_AES_256_CCM_8 0x0300C0A9
# define TLS1_CK_DHE_PSK_WITH_AES_128_CCM_8 0x0300C0AA
# define TLS1_CK_DHE_PSK_WITH_AES_256_CCM_8 0x0300C0AB
/* CCM ciphersuites from RFC7251 */
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM 0x0300C0AC
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM 0x0300C0AD
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM_8 0x0300C0AE
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM_8 0x0300C0AF
/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */
# define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BA
# define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 0x030000BB
# define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BC
# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 0x030000BD
# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BE
# define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256 0x030000BF
# define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C0
# define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 0x030000C1
# define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C2
# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 0x030000C3
# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C4
# define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256 0x030000C5
/* ECC ciphersuites from RFC4492 */
# define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001
# define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002
# define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003
# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004
# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005
# define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006
# define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007
# define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A
# define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B
# define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C
# define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D
# define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E
# define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F
# define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010
# define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011
# define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012
# define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013
# define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014
# define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015
# define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016
# define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017
# define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018
# define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019
/* SRP ciphersuites from RFC 5054 */
# define TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0x0300C01A
# define TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0x0300C01B
# define TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0x0300C01C
# define TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA 0x0300C01D
# define TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0x0300C01E
# define TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0x0300C01F
# define TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA 0x0300C020
# define TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0x0300C021
# define TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0x0300C022
/* ECDH HMAC based ciphersuites from RFC5289 */
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256 0x0300C023
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384 0x0300C024
# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256 0x0300C025
# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384 0x0300C026
# define TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 0x0300C027
# define TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384 0x0300C028
# define TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256 0x0300C029
# define TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384 0x0300C02A
/* ECDH GCM based ciphersuites from RFC5289 */
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02B
# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02C
# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02D
# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02E
# define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0x0300C02F
# define TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0x0300C030
# define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031
# define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032
/* ECDHE PSK ciphersuites from RFC5489 */
# define TLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA 0x0300C033
# define TLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0x0300C034
# define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA 0x0300C035
# define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA 0x0300C036
# define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0x0300C037
# define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0x0300C038
/* NULL PSK ciphersuites from RFC4785 */
# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA 0x0300C039
# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA256 0x0300C03A
# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA384 0x0300C03B
/* Camellia-CBC ciphersuites from RFC6367 */
# define TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C072
# define TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C073
# define TLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C074
# define TLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C075
# define TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C076
# define TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C077
# define TLS1_CK_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C078
# define TLS1_CK_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C079
# define TLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C094
# define TLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C095
# define TLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C096
# define TLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C097
# define TLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C098
# define TLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C099
# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C09A
# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C09B
/* draft-ietf-tls-chacha20-poly1305-03 */
# define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305 0x0300CCA8
# define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 0x0300CCA9
# define TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305 0x0300CCAA
# define TLS1_CK_PSK_WITH_CHACHA20_POLY1305 0x0300CCAB
# define TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305 0x0300CCAC
# define TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305 0x0300CCAD
# define TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305 0x0300CCAE
/* TLS v1.3 ciphersuites */
# define TLS1_3_CK_AES_128_GCM_SHA256 0x03001301
# define TLS1_3_CK_AES_256_GCM_SHA384 0x03001302
# define TLS1_3_CK_CHACHA20_POLY1305_SHA256 0x03001303
# define TLS1_3_CK_AES_128_CCM_SHA256 0x03001304
# define TLS1_3_CK_AES_128_CCM_8_SHA256 0x03001305
/* Aria ciphersuites from RFC6209 */
# define TLS1_CK_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C050
# define TLS1_CK_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C051
# define TLS1_CK_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C052
# define TLS1_CK_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C053
# define TLS1_CK_DH_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C054
# define TLS1_CK_DH_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C055
# define TLS1_CK_DHE_DSS_WITH_ARIA_128_GCM_SHA256 0x0300C056
# define TLS1_CK_DHE_DSS_WITH_ARIA_256_GCM_SHA384 0x0300C057
# define TLS1_CK_DH_DSS_WITH_ARIA_128_GCM_SHA256 0x0300C058
# define TLS1_CK_DH_DSS_WITH_ARIA_256_GCM_SHA384 0x0300C059
# define TLS1_CK_DH_anon_WITH_ARIA_128_GCM_SHA256 0x0300C05A
# define TLS1_CK_DH_anon_WITH_ARIA_256_GCM_SHA384 0x0300C05B
# define TLS1_CK_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0x0300C05C
# define TLS1_CK_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0x0300C05D
# define TLS1_CK_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0x0300C05E
# define TLS1_CK_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0x0300C05F
# define TLS1_CK_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C060
# define TLS1_CK_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C061
# define TLS1_CK_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C062
# define TLS1_CK_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C063
# define TLS1_CK_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06A
# define TLS1_CK_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06B
# define TLS1_CK_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06C
# define TLS1_CK_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06D
# define TLS1_CK_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06E
# define TLS1_CK_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06F
/* a bundle of RFC standard cipher names, generated from ssl3_ciphers[] */
# define TLS1_RFC_RSA_WITH_AES_128_SHA "TLS_RSA_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_DHE_DSS_WITH_AES_128_SHA "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_DHE_RSA_WITH_AES_128_SHA "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_ADH_WITH_AES_128_SHA "TLS_DH_anon_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_RSA_WITH_AES_256_SHA "TLS_RSA_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_DHE_DSS_WITH_AES_256_SHA "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_DHE_RSA_WITH_AES_256_SHA "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_ADH_WITH_AES_256_SHA "TLS_DH_anon_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_RSA_WITH_NULL_SHA256 "TLS_RSA_WITH_NULL_SHA256"
# define TLS1_RFC_RSA_WITH_AES_128_SHA256 "TLS_RSA_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_RSA_WITH_AES_256_SHA256 "TLS_RSA_WITH_AES_256_CBC_SHA256"
# define TLS1_RFC_DHE_DSS_WITH_AES_128_SHA256 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_DHE_RSA_WITH_AES_128_SHA256 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_DHE_DSS_WITH_AES_256_SHA256 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"
# define TLS1_RFC_DHE_RSA_WITH_AES_256_SHA256 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"
# define TLS1_RFC_ADH_WITH_AES_128_SHA256 "TLS_DH_anon_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_ADH_WITH_AES_256_SHA256 "TLS_DH_anon_WITH_AES_256_CBC_SHA256"
# define TLS1_RFC_RSA_WITH_AES_128_GCM_SHA256 "TLS_RSA_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_RSA_WITH_AES_256_GCM_SHA384 "TLS_RSA_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_DHE_RSA_WITH_AES_128_GCM_SHA256 "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_DHE_RSA_WITH_AES_256_GCM_SHA384 "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_DHE_DSS_WITH_AES_128_GCM_SHA256 "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_DHE_DSS_WITH_AES_256_GCM_SHA384 "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_ADH_WITH_AES_128_GCM_SHA256 "TLS_DH_anon_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_ADH_WITH_AES_256_GCM_SHA384 "TLS_DH_anon_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_RSA_WITH_AES_128_CCM "TLS_RSA_WITH_AES_128_CCM"
# define TLS1_RFC_RSA_WITH_AES_256_CCM "TLS_RSA_WITH_AES_256_CCM"
# define TLS1_RFC_DHE_RSA_WITH_AES_128_CCM "TLS_DHE_RSA_WITH_AES_128_CCM"
# define TLS1_RFC_DHE_RSA_WITH_AES_256_CCM "TLS_DHE_RSA_WITH_AES_256_CCM"
# define TLS1_RFC_RSA_WITH_AES_128_CCM_8 "TLS_RSA_WITH_AES_128_CCM_8"
# define TLS1_RFC_RSA_WITH_AES_256_CCM_8 "TLS_RSA_WITH_AES_256_CCM_8"
# define TLS1_RFC_DHE_RSA_WITH_AES_128_CCM_8 "TLS_DHE_RSA_WITH_AES_128_CCM_8"
# define TLS1_RFC_DHE_RSA_WITH_AES_256_CCM_8 "TLS_DHE_RSA_WITH_AES_256_CCM_8"
# define TLS1_RFC_PSK_WITH_AES_128_CCM "TLS_PSK_WITH_AES_128_CCM"
# define TLS1_RFC_PSK_WITH_AES_256_CCM "TLS_PSK_WITH_AES_256_CCM"
# define TLS1_RFC_DHE_PSK_WITH_AES_128_CCM "TLS_DHE_PSK_WITH_AES_128_CCM"
# define TLS1_RFC_DHE_PSK_WITH_AES_256_CCM "TLS_DHE_PSK_WITH_AES_256_CCM"
# define TLS1_RFC_PSK_WITH_AES_128_CCM_8 "TLS_PSK_WITH_AES_128_CCM_8"
# define TLS1_RFC_PSK_WITH_AES_256_CCM_8 "TLS_PSK_WITH_AES_256_CCM_8"
# define TLS1_RFC_DHE_PSK_WITH_AES_128_CCM_8 "TLS_PSK_DHE_WITH_AES_128_CCM_8"
# define TLS1_RFC_DHE_PSK_WITH_AES_256_CCM_8 "TLS_PSK_DHE_WITH_AES_256_CCM_8"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM_8 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM_8 "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"
# define TLS1_3_RFC_AES_128_GCM_SHA256 "TLS_AES_128_GCM_SHA256"
# define TLS1_3_RFC_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384"
# define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256"
# define TLS1_3_RFC_AES_128_CCM_SHA256 "TLS_AES_128_CCM_SHA256"
# define TLS1_3_RFC_AES_128_CCM_8_SHA256 "TLS_AES_128_CCM_8_SHA256"
# define TLS1_RFC_ECDHE_ECDSA_WITH_NULL_SHA "TLS_ECDHE_ECDSA_WITH_NULL_SHA"
# define TLS1_RFC_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_ECDHE_RSA_WITH_NULL_SHA "TLS_ECDHE_RSA_WITH_NULL_SHA"
# define TLS1_RFC_ECDHE_RSA_WITH_DES_192_CBC3_SHA "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_CBC_SHA "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_CBC_SHA "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_ECDH_anon_WITH_NULL_SHA "TLS_ECDH_anon_WITH_NULL_SHA"
# define TLS1_RFC_ECDH_anon_WITH_DES_192_CBC3_SHA "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_ECDH_anon_WITH_AES_128_CBC_SHA "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_ECDH_anon_WITH_AES_256_CBC_SHA "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_SHA256 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_SHA384 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"
# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_SHA256 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_SHA384 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_PSK_WITH_NULL_SHA "TLS_PSK_WITH_NULL_SHA"
# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA "TLS_DHE_PSK_WITH_NULL_SHA"
# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA "TLS_RSA_PSK_WITH_NULL_SHA"
# define TLS1_RFC_PSK_WITH_3DES_EDE_CBC_SHA "TLS_PSK_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_PSK_WITH_AES_128_CBC_SHA "TLS_PSK_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_PSK_WITH_AES_256_CBC_SHA "TLS_PSK_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_DHE_PSK_WITH_3DES_EDE_CBC_SHA "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_RSA_PSK_WITH_3DES_EDE_CBC_SHA "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_PSK_WITH_AES_128_GCM_SHA256 "TLS_PSK_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_PSK_WITH_AES_256_GCM_SHA384 "TLS_PSK_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_DHE_PSK_WITH_AES_128_GCM_SHA256 "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_DHE_PSK_WITH_AES_256_GCM_SHA384 "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_RSA_PSK_WITH_AES_128_GCM_SHA256 "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"
# define TLS1_RFC_RSA_PSK_WITH_AES_256_GCM_SHA384 "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"
# define TLS1_RFC_PSK_WITH_AES_128_CBC_SHA256 "TLS_PSK_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_PSK_WITH_AES_256_CBC_SHA384 "TLS_PSK_WITH_AES_256_CBC_SHA384"
# define TLS1_RFC_PSK_WITH_NULL_SHA256 "TLS_PSK_WITH_NULL_SHA256"
# define TLS1_RFC_PSK_WITH_NULL_SHA384 "TLS_PSK_WITH_NULL_SHA384"
# define TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA256 "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA384 "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"
# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA256 "TLS_DHE_PSK_WITH_NULL_SHA256"
# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA384 "TLS_DHE_PSK_WITH_NULL_SHA384"
# define TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA256 "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA384 "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"
# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA256 "TLS_RSA_PSK_WITH_NULL_SHA256"
# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA384 "TLS_RSA_PSK_WITH_NULL_SHA384"
# define TLS1_RFC_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"
# define TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"
# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA "TLS_ECDHE_PSK_WITH_NULL_SHA"
# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA256 "TLS_ECDHE_PSK_WITH_NULL_SHA256"
# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA384 "TLS_ECDHE_PSK_WITH_NULL_SHA384"
# define TLS1_RFC_SRP_SHA_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_SRP_SHA_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"
# define TLS1_RFC_SRP_SHA_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"
# define TLS1_RFC_DHE_RSA_WITH_CHACHA20_POLY1305 "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
# define TLS1_RFC_ECDHE_RSA_WITH_CHACHA20_POLY1305 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
# define TLS1_RFC_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
# define TLS1_RFC_PSK_WITH_CHACHA20_POLY1305 "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256"
# define TLS1_RFC_ECDHE_PSK_WITH_CHACHA20_POLY1305 "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"
# define TLS1_RFC_DHE_PSK_WITH_CHACHA20_POLY1305 "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"
# define TLS1_RFC_RSA_PSK_WITH_CHACHA20_POLY1305 "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256"
# define TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA256 "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"
# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"
# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"
# define TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"
# define TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"
# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"
# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"
# define TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"
# define TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"
# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"
# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"
# define TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"
# define TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"
# define TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"
# define TLS1_RFC_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"
# define TLS1_RFC_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"
# define TLS1_RFC_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"
# define TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"
# define TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"
# define TLS1_RFC_RSA_WITH_SEED_SHA "TLS_RSA_WITH_SEED_CBC_SHA"
# define TLS1_RFC_DHE_DSS_WITH_SEED_SHA "TLS_DHE_DSS_WITH_SEED_CBC_SHA"
# define TLS1_RFC_DHE_RSA_WITH_SEED_SHA "TLS_DHE_RSA_WITH_SEED_CBC_SHA"
# define TLS1_RFC_ADH_WITH_SEED_SHA "TLS_DH_anon_WITH_SEED_CBC_SHA"
# define TLS1_RFC_ECDHE_PSK_WITH_RC4_128_SHA "TLS_ECDHE_PSK_WITH_RC4_128_SHA"
# define TLS1_RFC_ECDH_anon_WITH_RC4_128_SHA "TLS_ECDH_anon_WITH_RC4_128_SHA"
# define TLS1_RFC_ECDHE_ECDSA_WITH_RC4_128_SHA "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"
# define TLS1_RFC_ECDHE_RSA_WITH_RC4_128_SHA "TLS_ECDHE_RSA_WITH_RC4_128_SHA"
# define TLS1_RFC_PSK_WITH_RC4_128_SHA "TLS_PSK_WITH_RC4_128_SHA"
# define TLS1_RFC_RSA_PSK_WITH_RC4_128_SHA "TLS_RSA_PSK_WITH_RC4_128_SHA"
# define TLS1_RFC_DHE_PSK_WITH_RC4_128_SHA "TLS_DHE_PSK_WITH_RC4_128_SHA"
# define TLS1_RFC_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_RSA_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_RSA_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_DHE_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_DHE_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_DH_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_DH_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_DHE_DSS_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_DHE_DSS_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_DH_DSS_WITH_ARIA_128_GCM_SHA256 "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_DH_DSS_WITH_ARIA_256_GCM_SHA384 "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_DH_anon_WITH_ARIA_128_GCM_SHA256 "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_DH_anon_WITH_ARIA_256_GCM_SHA384 "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_PSK_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_PSK_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_DHE_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_DHE_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"
# define TLS1_RFC_RSA_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"
# define TLS1_RFC_RSA_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"
/*
* XXX Backward compatibility alert: Older versions of OpenSSL gave some DHE
* ciphers names with "EDH" instead of "DHE". Going forward, we should be
* using DHE everywhere, though we may indefinitely maintain aliases for
* users or configurations that used "EDH"
*/
# define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA"
# define TLS1_TXT_PSK_WITH_NULL_SHA "PSK-NULL-SHA"
# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA "DHE-PSK-NULL-SHA"
# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA "RSA-PSK-NULL-SHA"
/* AES ciphersuites from RFC3268 */
# define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA"
# define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA"
# define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA"
# define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA"
# define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA"
# define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA"
# define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA"
# define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA"
# define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA"
# define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA"
# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA"
# define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA"
/* ECC ciphersuites from RFC4492 */
# define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA"
# define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA"
# define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA"
# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA"
# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA"
# define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA"
# define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA"
# define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA"
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA"
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA"
# define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA"
# define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA"
# define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA"
# define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA"
# define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA"
# define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA"
# define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA"
# define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA"
# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA"
# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA"
# define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA"
# define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA"
# define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA"
# define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA"
# define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA"
/* PSK ciphersuites from RFC 4279 */
# define TLS1_TXT_PSK_WITH_RC4_128_SHA "PSK-RC4-SHA"
# define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA "PSK-3DES-EDE-CBC-SHA"
# define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA "PSK-AES128-CBC-SHA"
# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA "PSK-AES256-CBC-SHA"
# define TLS1_TXT_DHE_PSK_WITH_RC4_128_SHA "DHE-PSK-RC4-SHA"
# define TLS1_TXT_DHE_PSK_WITH_3DES_EDE_CBC_SHA "DHE-PSK-3DES-EDE-CBC-SHA"
# define TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA "DHE-PSK-AES128-CBC-SHA"
# define TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA "DHE-PSK-AES256-CBC-SHA"
# define TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA "RSA-PSK-RC4-SHA"
# define TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA "RSA-PSK-3DES-EDE-CBC-SHA"
# define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA "RSA-PSK-AES128-CBC-SHA"
# define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA "RSA-PSK-AES256-CBC-SHA"
/* PSK ciphersuites from RFC 5487 */
# define TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256 "PSK-AES128-GCM-SHA256"
# define TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384 "PSK-AES256-GCM-SHA384"
# define TLS1_TXT_DHE_PSK_WITH_AES_128_GCM_SHA256 "DHE-PSK-AES128-GCM-SHA256"
# define TLS1_TXT_DHE_PSK_WITH_AES_256_GCM_SHA384 "DHE-PSK-AES256-GCM-SHA384"
# define TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256 "RSA-PSK-AES128-GCM-SHA256"
# define TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384 "RSA-PSK-AES256-GCM-SHA384"
# define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256 "PSK-AES128-CBC-SHA256"
# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384 "PSK-AES256-CBC-SHA384"
# define TLS1_TXT_PSK_WITH_NULL_SHA256 "PSK-NULL-SHA256"
# define TLS1_TXT_PSK_WITH_NULL_SHA384 "PSK-NULL-SHA384"
# define TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256 "DHE-PSK-AES128-CBC-SHA256"
# define TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA384 "DHE-PSK-AES256-CBC-SHA384"
# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA256 "DHE-PSK-NULL-SHA256"
# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA384 "DHE-PSK-NULL-SHA384"
# define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256 "RSA-PSK-AES128-CBC-SHA256"
# define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384 "RSA-PSK-AES256-CBC-SHA384"
# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA256 "RSA-PSK-NULL-SHA256"
# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA384 "RSA-PSK-NULL-SHA384"
/* SRP ciphersuite from RFC 5054 */
# define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA "SRP-3DES-EDE-CBC-SHA"
# define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "SRP-RSA-3DES-EDE-CBC-SHA"
# define TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "SRP-DSS-3DES-EDE-CBC-SHA"
# define TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA "SRP-AES-128-CBC-SHA"
# define TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "SRP-RSA-AES-128-CBC-SHA"
# define TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "SRP-DSS-AES-128-CBC-SHA"
# define TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA "SRP-AES-256-CBC-SHA"
# define TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "SRP-RSA-AES-256-CBC-SHA"
# define TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "SRP-DSS-AES-256-CBC-SHA"
/* Camellia ciphersuites from RFC4132 */
# define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA"
# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA"
# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA"
# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA"
# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA"
# define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA"
# define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA"
# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA"
# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA"
# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA"
# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA"
# define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA"
/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */
# define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256 "CAMELLIA128-SHA256"
# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 "DH-DSS-CAMELLIA128-SHA256"
# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 "DH-RSA-CAMELLIA128-SHA256"
# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 "DHE-DSS-CAMELLIA128-SHA256"
# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "DHE-RSA-CAMELLIA128-SHA256"
# define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA256 "ADH-CAMELLIA128-SHA256"
# define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256 "CAMELLIA256-SHA256"
# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 "DH-DSS-CAMELLIA256-SHA256"
# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 "DH-RSA-CAMELLIA256-SHA256"
# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 "DHE-DSS-CAMELLIA256-SHA256"
# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 "DHE-RSA-CAMELLIA256-SHA256"
# define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256 "ADH-CAMELLIA256-SHA256"
# define TLS1_TXT_PSK_WITH_CAMELLIA_128_CBC_SHA256 "PSK-CAMELLIA128-SHA256"
# define TLS1_TXT_PSK_WITH_CAMELLIA_256_CBC_SHA384 "PSK-CAMELLIA256-SHA384"
# define TLS1_TXT_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "DHE-PSK-CAMELLIA128-SHA256"
# define TLS1_TXT_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "DHE-PSK-CAMELLIA256-SHA384"
# define TLS1_TXT_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 "RSA-PSK-CAMELLIA128-SHA256"
# define TLS1_TXT_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 "RSA-PSK-CAMELLIA256-SHA384"
# define TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-PSK-CAMELLIA128-SHA256"
# define TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-PSK-CAMELLIA256-SHA384"
/* SEED ciphersuites from RFC4162 */
# define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA"
# define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA"
# define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA"
# define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA"
# define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA"
# define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA"
/* TLS v1.2 ciphersuites */
# define TLS1_TXT_RSA_WITH_NULL_SHA256 "NULL-SHA256"
# define TLS1_TXT_RSA_WITH_AES_128_SHA256 "AES128-SHA256"
# define TLS1_TXT_RSA_WITH_AES_256_SHA256 "AES256-SHA256"
# define TLS1_TXT_DH_DSS_WITH_AES_128_SHA256 "DH-DSS-AES128-SHA256"
# define TLS1_TXT_DH_RSA_WITH_AES_128_SHA256 "DH-RSA-AES128-SHA256"
# define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256 "DHE-DSS-AES128-SHA256"
# define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 "DHE-RSA-AES128-SHA256"
# define TLS1_TXT_DH_DSS_WITH_AES_256_SHA256 "DH-DSS-AES256-SHA256"
# define TLS1_TXT_DH_RSA_WITH_AES_256_SHA256 "DH-RSA-AES256-SHA256"
# define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256 "DHE-DSS-AES256-SHA256"
# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 "DHE-RSA-AES256-SHA256"
# define TLS1_TXT_ADH_WITH_AES_128_SHA256 "ADH-AES128-SHA256"
# define TLS1_TXT_ADH_WITH_AES_256_SHA256 "ADH-AES256-SHA256"
/* TLS v1.2 GCM ciphersuites from RFC5288 */
# define TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256 "AES128-GCM-SHA256"
# define TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384 "AES256-GCM-SHA384"
# define TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 "DHE-RSA-AES128-GCM-SHA256"
# define TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 "DHE-RSA-AES256-GCM-SHA384"
# define TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256 "DH-RSA-AES128-GCM-SHA256"
# define TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384 "DH-RSA-AES256-GCM-SHA384"
# define TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256 "DHE-DSS-AES128-GCM-SHA256"
# define TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384 "DHE-DSS-AES256-GCM-SHA384"
# define TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256 "DH-DSS-AES128-GCM-SHA256"
# define TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384 "DH-DSS-AES256-GCM-SHA384"
# define TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256 "ADH-AES128-GCM-SHA256"
# define TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384 "ADH-AES256-GCM-SHA384"
/* CCM ciphersuites from RFC6655 */
# define TLS1_TXT_RSA_WITH_AES_128_CCM "AES128-CCM"
# define TLS1_TXT_RSA_WITH_AES_256_CCM "AES256-CCM"
# define TLS1_TXT_DHE_RSA_WITH_AES_128_CCM "DHE-RSA-AES128-CCM"
# define TLS1_TXT_DHE_RSA_WITH_AES_256_CCM "DHE-RSA-AES256-CCM"
# define TLS1_TXT_RSA_WITH_AES_128_CCM_8 "AES128-CCM8"
# define TLS1_TXT_RSA_WITH_AES_256_CCM_8 "AES256-CCM8"
# define TLS1_TXT_DHE_RSA_WITH_AES_128_CCM_8 "DHE-RSA-AES128-CCM8"
# define TLS1_TXT_DHE_RSA_WITH_AES_256_CCM_8 "DHE-RSA-AES256-CCM8"
# define TLS1_TXT_PSK_WITH_AES_128_CCM "PSK-AES128-CCM"
# define TLS1_TXT_PSK_WITH_AES_256_CCM "PSK-AES256-CCM"
# define TLS1_TXT_DHE_PSK_WITH_AES_128_CCM "DHE-PSK-AES128-CCM"
# define TLS1_TXT_DHE_PSK_WITH_AES_256_CCM "DHE-PSK-AES256-CCM"
# define TLS1_TXT_PSK_WITH_AES_128_CCM_8 "PSK-AES128-CCM8"
# define TLS1_TXT_PSK_WITH_AES_256_CCM_8 "PSK-AES256-CCM8"
# define TLS1_TXT_DHE_PSK_WITH_AES_128_CCM_8 "DHE-PSK-AES128-CCM8"
# define TLS1_TXT_DHE_PSK_WITH_AES_256_CCM_8 "DHE-PSK-AES256-CCM8"
/* CCM ciphersuites from RFC7251 */
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM "ECDHE-ECDSA-AES128-CCM"
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM "ECDHE-ECDSA-AES256-CCM"
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM_8 "ECDHE-ECDSA-AES128-CCM8"
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM_8 "ECDHE-ECDSA-AES256-CCM8"
/* ECDH HMAC based ciphersuites from RFC5289 */
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256 "ECDHE-ECDSA-AES128-SHA256"
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384 "ECDHE-ECDSA-AES256-SHA384"
# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_SHA256 "ECDH-ECDSA-AES128-SHA256"
# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_SHA384 "ECDH-ECDSA-AES256-SHA384"
# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 "ECDHE-RSA-AES128-SHA256"
# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 "ECDHE-RSA-AES256-SHA384"
# define TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256 "ECDH-RSA-AES128-SHA256"
# define TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384 "ECDH-RSA-AES256-SHA384"
/* ECDH GCM based ciphersuites from RFC5289 */
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "ECDHE-ECDSA-AES128-GCM-SHA256"
# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "ECDHE-ECDSA-AES256-GCM-SHA384"
# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 "ECDH-ECDSA-AES128-GCM-SHA256"
# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 "ECDH-ECDSA-AES256-GCM-SHA384"
# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "ECDHE-RSA-AES128-GCM-SHA256"
# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "ECDHE-RSA-AES256-GCM-SHA384"
# define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256"
# define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384"
/* TLS v1.2 PSK GCM ciphersuites from RFC5487 */
# define TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256 "PSK-AES128-GCM-SHA256"
# define TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384 "PSK-AES256-GCM-SHA384"
/* ECDHE PSK ciphersuites from RFC 5489 */
# define TLS1_TXT_ECDHE_PSK_WITH_RC4_128_SHA "ECDHE-PSK-RC4-SHA"
# define TLS1_TXT_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA "ECDHE-PSK-3DES-EDE-CBC-SHA"
# define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA "ECDHE-PSK-AES128-CBC-SHA"
# define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA "ECDHE-PSK-AES256-CBC-SHA"
# define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "ECDHE-PSK-AES128-CBC-SHA256"
# define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "ECDHE-PSK-AES256-CBC-SHA384"
# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA "ECDHE-PSK-NULL-SHA"
# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA256 "ECDHE-PSK-NULL-SHA256"
# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA384 "ECDHE-PSK-NULL-SHA384"
/* Camellia-CBC ciphersuites from RFC6367 */
# define TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-ECDSA-CAMELLIA128-SHA256"
# define TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-ECDSA-CAMELLIA256-SHA384"
# define TLS1_TXT_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDH-ECDSA-CAMELLIA128-SHA256"
# define TLS1_TXT_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDH-ECDSA-CAMELLIA256-SHA384"
# define TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-RSA-CAMELLIA128-SHA256"
# define TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-RSA-CAMELLIA256-SHA384"
# define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDH-RSA-CAMELLIA128-SHA256"
# define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDH-RSA-CAMELLIA256-SHA384"
/* draft-ietf-tls-chacha20-poly1305-03 */
# define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 "ECDHE-RSA-CHACHA20-POLY1305"
# define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305"
# define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305"
# define TLS1_TXT_PSK_WITH_CHACHA20_POLY1305 "PSK-CHACHA20-POLY1305"
# define TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305 "ECDHE-PSK-CHACHA20-POLY1305"
# define TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305 "DHE-PSK-CHACHA20-POLY1305"
# define TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305 "RSA-PSK-CHACHA20-POLY1305"
/* Aria ciphersuites from RFC6209 */
# define TLS1_TXT_RSA_WITH_ARIA_128_GCM_SHA256 "ARIA128-GCM-SHA256"
# define TLS1_TXT_RSA_WITH_ARIA_256_GCM_SHA384 "ARIA256-GCM-SHA384"
# define TLS1_TXT_DHE_RSA_WITH_ARIA_128_GCM_SHA256 "DHE-RSA-ARIA128-GCM-SHA256"
# define TLS1_TXT_DHE_RSA_WITH_ARIA_256_GCM_SHA384 "DHE-RSA-ARIA256-GCM-SHA384"
# define TLS1_TXT_DH_RSA_WITH_ARIA_128_GCM_SHA256 "DH-RSA-ARIA128-GCM-SHA256"
# define TLS1_TXT_DH_RSA_WITH_ARIA_256_GCM_SHA384 "DH-RSA-ARIA256-GCM-SHA384"
# define TLS1_TXT_DHE_DSS_WITH_ARIA_128_GCM_SHA256 "DHE-DSS-ARIA128-GCM-SHA256"
# define TLS1_TXT_DHE_DSS_WITH_ARIA_256_GCM_SHA384 "DHE-DSS-ARIA256-GCM-SHA384"
# define TLS1_TXT_DH_DSS_WITH_ARIA_128_GCM_SHA256 "DH-DSS-ARIA128-GCM-SHA256"
# define TLS1_TXT_DH_DSS_WITH_ARIA_256_GCM_SHA384 "DH-DSS-ARIA256-GCM-SHA384"
# define TLS1_TXT_DH_anon_WITH_ARIA_128_GCM_SHA256 "ADH-ARIA128-GCM-SHA256"
# define TLS1_TXT_DH_anon_WITH_ARIA_256_GCM_SHA384 "ADH-ARIA256-GCM-SHA384"
# define TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 "ECDHE-ECDSA-ARIA128-GCM-SHA256"
# define TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 "ECDHE-ECDSA-ARIA256-GCM-SHA384"
# define TLS1_TXT_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 "ECDH-ECDSA-ARIA128-GCM-SHA256"
# define TLS1_TXT_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 "ECDH-ECDSA-ARIA256-GCM-SHA384"
# define TLS1_TXT_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 "ECDHE-ARIA128-GCM-SHA256"
# define TLS1_TXT_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 "ECDHE-ARIA256-GCM-SHA384"
# define TLS1_TXT_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 "ECDH-ARIA128-GCM-SHA256"
# define TLS1_TXT_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 "ECDH-ARIA256-GCM-SHA384"
# define TLS1_TXT_PSK_WITH_ARIA_128_GCM_SHA256 "PSK-ARIA128-GCM-SHA256"
# define TLS1_TXT_PSK_WITH_ARIA_256_GCM_SHA384 "PSK-ARIA256-GCM-SHA384"
# define TLS1_TXT_DHE_PSK_WITH_ARIA_128_GCM_SHA256 "DHE-PSK-ARIA128-GCM-SHA256"
# define TLS1_TXT_DHE_PSK_WITH_ARIA_256_GCM_SHA384 "DHE-PSK-ARIA256-GCM-SHA384"
# define TLS1_TXT_RSA_PSK_WITH_ARIA_128_GCM_SHA256 "RSA-PSK-ARIA128-GCM-SHA256"
# define TLS1_TXT_RSA_PSK_WITH_ARIA_256_GCM_SHA384 "RSA-PSK-ARIA256-GCM-SHA384"
# define TLS_CT_RSA_SIGN 1
# define TLS_CT_DSS_SIGN 2
# define TLS_CT_RSA_FIXED_DH 3
# define TLS_CT_DSS_FIXED_DH 4
# define TLS_CT_ECDSA_SIGN 64
# define TLS_CT_RSA_FIXED_ECDH 65
# define TLS_CT_ECDSA_FIXED_ECDH 66
# define TLS_CT_GOST01_SIGN 22
# define TLS_CT_GOST12_SIGN 238
# define TLS_CT_GOST12_512_SIGN 239
/*
* when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see
* comment there)
*/
# define TLS_CT_NUMBER 10
# if defined(SSL3_CT_NUMBER)
# if TLS_CT_NUMBER != SSL3_CT_NUMBER
# error "SSL/TLS CT_NUMBER values do not match"
# endif
# endif
# define TLS1_FINISH_MAC_LENGTH 12
# define TLS_MD_MAX_CONST_SIZE 22
# define TLS_MD_CLIENT_FINISH_CONST "client finished"
# define TLS_MD_CLIENT_FINISH_CONST_SIZE 15
# define TLS_MD_SERVER_FINISH_CONST "server finished"
# define TLS_MD_SERVER_FINISH_CONST_SIZE 15
# define TLS_MD_KEY_EXPANSION_CONST "key expansion"
# define TLS_MD_KEY_EXPANSION_CONST_SIZE 13
# define TLS_MD_CLIENT_WRITE_KEY_CONST "client write key"
# define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE 16
# define TLS_MD_SERVER_WRITE_KEY_CONST "server write key"
# define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16
# define TLS_MD_IV_BLOCK_CONST "IV block"
# define TLS_MD_IV_BLOCK_CONST_SIZE 8
# define TLS_MD_MASTER_SECRET_CONST "master secret"
# define TLS_MD_MASTER_SECRET_CONST_SIZE 13
# define TLS_MD_EXTENDED_MASTER_SECRET_CONST "extended master secret"
# define TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE 22
# ifdef CHARSET_EBCDIC
# undef TLS_MD_CLIENT_FINISH_CONST
/*
* client finished
*/
# define TLS_MD_CLIENT_FINISH_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64"
# undef TLS_MD_SERVER_FINISH_CONST
/*
* server finished
*/
# define TLS_MD_SERVER_FINISH_CONST "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64"
# undef TLS_MD_SERVER_WRITE_KEY_CONST
/*
* server write key
*/
# define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"
# undef TLS_MD_KEY_EXPANSION_CONST
/*
* key expansion
*/
# define TLS_MD_KEY_EXPANSION_CONST "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e"
# undef TLS_MD_CLIENT_WRITE_KEY_CONST
/*
* client write key
*/
# define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"
# undef TLS_MD_SERVER_WRITE_KEY_CONST
/*
* server write key
*/
# define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"
# undef TLS_MD_IV_BLOCK_CONST
/*
* IV block
*/
# define TLS_MD_IV_BLOCK_CONST "\x49\x56\x20\x62\x6c\x6f\x63\x6b"
# undef TLS_MD_MASTER_SECRET_CONST
/*
* master secret
*/
# define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
# undef TLS_MD_EXTENDED_MASTER_SECRET_CONST
/*
* extended master secret
*/
# define TLS_MD_EXTENDED_MASTER_SECRET_CONST "\x65\x78\x74\x65\x63\x64\x65\x64\x20\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
# endif
/* TLS Session Ticket extension struct */
struct tls_session_ticket_ext_st {
unsigned short length;
void *data;
};
#ifdef __cplusplus
}
#endif
#endif
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index f80851251fe2..fcda32754735 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -1,991 +1,972 @@
/*
- * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2018 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 <stdio.h>
#include <openssl/objects.h>
#include <openssl/rand.h>
#include "ssl_locl.h"
static void get_current_time(struct timeval *t);
static int dtls1_handshake_write(SSL *s);
static size_t dtls1_link_min_mtu(void);
/* XDTLS: figure out the right values */
static const size_t g_probable_mtu[] = { 1500, 512, 256 };
const SSL3_ENC_METHOD DTLSv1_enc_data = {
tls1_enc,
tls1_mac,
tls1_setup_key_block,
tls1_generate_master_secret,
tls1_change_cipher_state,
tls1_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV,
dtls1_set_handshake_header,
dtls1_close_construct_packet,
dtls1_handshake_write
};
const SSL3_ENC_METHOD DTLSv1_2_enc_data = {
tls1_enc,
tls1_mac,
tls1_setup_key_block,
tls1_generate_master_secret,
tls1_change_cipher_state,
tls1_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS
| SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS,
dtls1_set_handshake_header,
dtls1_close_construct_packet,
dtls1_handshake_write
};
long dtls1_default_timeout(void)
{
/*
* 2 hours, the 24 hours mentioned in the DTLSv1 spec is way too long for
* http, the cache would over fill
*/
return (60 * 60 * 2);
}
int dtls1_new(SSL *s)
{
DTLS1_STATE *d1;
if (!DTLS_RECORD_LAYER_new(&s->rlayer)) {
return 0;
}
if (!ssl3_new(s))
return 0;
if ((d1 = OPENSSL_zalloc(sizeof(*d1))) == NULL) {
ssl3_free(s);
return 0;
}
d1->buffered_messages = pqueue_new();
d1->sent_messages = pqueue_new();
if (s->server) {
d1->cookie_len = sizeof(s->d1->cookie);
}
d1->link_mtu = 0;
d1->mtu = 0;
if (d1->buffered_messages == NULL || d1->sent_messages == NULL) {
pqueue_free(d1->buffered_messages);
pqueue_free(d1->sent_messages);
OPENSSL_free(d1);
ssl3_free(s);
return 0;
}
s->d1 = d1;
if (!s->method->ssl_clear(s))
return 0;
return 1;
}
static void dtls1_clear_queues(SSL *s)
{
dtls1_clear_received_buffer(s);
dtls1_clear_sent_buffer(s);
}
void dtls1_clear_received_buffer(SSL *s)
{
pitem *item = NULL;
hm_fragment *frag = NULL;
while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
}
}
void dtls1_clear_sent_buffer(SSL *s)
{
pitem *item = NULL;
hm_fragment *frag = NULL;
while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
}
}
void dtls1_free(SSL *s)
{
DTLS_RECORD_LAYER_free(&s->rlayer);
ssl3_free(s);
dtls1_clear_queues(s);
pqueue_free(s->d1->buffered_messages);
pqueue_free(s->d1->sent_messages);
OPENSSL_free(s->d1);
s->d1 = NULL;
}
int dtls1_clear(SSL *s)
{
pqueue *buffered_messages;
pqueue *sent_messages;
size_t mtu;
size_t link_mtu;
DTLS_RECORD_LAYER_clear(&s->rlayer);
if (s->d1) {
DTLS_timer_cb timer_cb = s->d1->timer_cb;
buffered_messages = s->d1->buffered_messages;
sent_messages = s->d1->sent_messages;
mtu = s->d1->mtu;
link_mtu = s->d1->link_mtu;
dtls1_clear_queues(s);
memset(s->d1, 0, sizeof(*s->d1));
/* Restore the timer callback from previous state */
s->d1->timer_cb = timer_cb;
if (s->server) {
s->d1->cookie_len = sizeof(s->d1->cookie);
}
if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
s->d1->mtu = mtu;
s->d1->link_mtu = link_mtu;
}
s->d1->buffered_messages = buffered_messages;
s->d1->sent_messages = sent_messages;
}
if (!ssl3_clear(s))
return 0;
if (s->method->version == DTLS_ANY_VERSION)
s->version = DTLS_MAX_VERSION;
#ifndef OPENSSL_NO_DTLS1_METHOD
else if (s->options & SSL_OP_CISCO_ANYCONNECT)
s->client_version = s->version = DTLS1_BAD_VER;
#endif
else
s->version = s->method->version;
return 1;
}
long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
{
int ret = 0;
switch (cmd) {
case DTLS_CTRL_GET_TIMEOUT:
if (dtls1_get_timeout(s, (struct timeval *)parg) != NULL) {
ret = 1;
}
break;
case DTLS_CTRL_HANDLE_TIMEOUT:
ret = dtls1_handle_timeout(s);
break;
case DTLS_CTRL_SET_LINK_MTU:
if (larg < (long)dtls1_link_min_mtu())
return 0;
s->d1->link_mtu = larg;
return 1;
case DTLS_CTRL_GET_LINK_MIN_MTU:
return (long)dtls1_link_min_mtu();
case SSL_CTRL_SET_MTU:
/*
* We may not have a BIO set yet so can't call dtls1_min_mtu()
* We'll have to make do with dtls1_link_min_mtu() and max overhead
*/
if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
return 0;
s->d1->mtu = larg;
return larg;
default:
ret = ssl3_ctrl(s, cmd, larg, parg);
break;
}
return ret;
}
void dtls1_start_timer(SSL *s)
{
unsigned int sec, usec;
#ifndef OPENSSL_NO_SCTP
/* Disable timer for SCTP */
if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
return;
}
#endif
/*
* If timer is not set, initialize duration with 1 second or
* a user-specified value if the timer callback is installed.
*/
if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
if (s->d1->timer_cb != NULL)
s->d1->timeout_duration_us = s->d1->timer_cb(s, 0);
else
s->d1->timeout_duration_us = 1000000;
}
/* Set timeout to current time */
get_current_time(&(s->d1->next_timeout));
/* Add duration to current time */
sec = s->d1->timeout_duration_us / 1000000;
usec = s->d1->timeout_duration_us - (sec * 1000000);
s->d1->next_timeout.tv_sec += sec;
s->d1->next_timeout.tv_usec += usec;
if (s->d1->next_timeout.tv_usec >= 1000000) {
s->d1->next_timeout.tv_sec++;
s->d1->next_timeout.tv_usec -= 1000000;
}
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&(s->d1->next_timeout));
}
struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft)
{
struct timeval timenow;
/* If no timeout is set, just return NULL */
if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
return NULL;
}
/* Get current time */
get_current_time(&timenow);
/* If timer already expired, set remaining time to 0 */
if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
(s->d1->next_timeout.tv_sec == timenow.tv_sec &&
s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
memset(timeleft, 0, sizeof(*timeleft));
return timeleft;
}
/* Calculate time left until timer expires */
memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
timeleft->tv_sec -= timenow.tv_sec;
timeleft->tv_usec -= timenow.tv_usec;
if (timeleft->tv_usec < 0) {
timeleft->tv_sec--;
timeleft->tv_usec += 1000000;
}
/*
* If remaining time is less than 15 ms, set it to 0 to prevent issues
* because of small divergences with socket timeouts.
*/
if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
memset(timeleft, 0, sizeof(*timeleft));
}
return timeleft;
}
int dtls1_is_timer_expired(SSL *s)
{
struct timeval timeleft;
/* Get time left until timeout, return false if no timer running */
if (dtls1_get_timeout(s, &timeleft) == NULL) {
return 0;
}
/* Return false if timer is not expired yet */
if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
return 0;
}
/* Timer expired, so return true */
return 1;
}
void dtls1_double_timeout(SSL *s)
{
s->d1->timeout_duration_us *= 2;
if (s->d1->timeout_duration_us > 60000000)
s->d1->timeout_duration_us = 60000000;
dtls1_start_timer(s);
}
void dtls1_stop_timer(SSL *s)
{
/* Reset everything */
memset(&s->d1->timeout, 0, sizeof(s->d1->timeout));
memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
s->d1->timeout_duration_us = 1000000;
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&(s->d1->next_timeout));
/* Clear retransmission buffer */
dtls1_clear_sent_buffer(s);
}
int dtls1_check_timeout_num(SSL *s)
{
size_t mtu;
s->d1->timeout.num_alerts++;
/* Reduce MTU after 2 unsuccessful retransmissions */
if (s->d1->timeout.num_alerts > 2
&& !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
mtu =
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
if (mtu < s->d1->mtu)
s->d1->mtu = mtu;
}
if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
/* fail the connection, enough alerts have been sent */
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS1_CHECK_TIMEOUT_NUM,
SSL_R_READ_TIMEOUT_EXPIRED);
return -1;
}
return 0;
}
int dtls1_handle_timeout(SSL *s)
{
/* if no timer is expired, don't do anything */
if (!dtls1_is_timer_expired(s)) {
return 0;
}
if (s->d1->timer_cb != NULL)
s->d1->timeout_duration_us = s->d1->timer_cb(s, s->d1->timeout_duration_us);
else
dtls1_double_timeout(s);
if (dtls1_check_timeout_num(s) < 0) {
/* SSLfatal() already called */
return -1;
}
s->d1->timeout.read_timeouts++;
if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
s->d1->timeout.read_timeouts = 1;
}
dtls1_start_timer(s);
/* Calls SSLfatal() if required */
return dtls1_retransmit_buffered_messages(s);
}
static void get_current_time(struct timeval *t)
{
#if defined(_WIN32)
SYSTEMTIME st;
union {
unsigned __int64 ul;
FILETIME ft;
} now;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &now.ft);
/* re-bias to 1/1/1970 */
# ifdef __MINGW32__
now.ul -= 116444736000000000ULL;
# else
/* *INDENT-OFF* */
now.ul -= 116444736000000000UI64;
/* *INDENT-ON* */
# endif
t->tv_sec = (long)(now.ul / 10000000);
t->tv_usec = ((int)(now.ul % 10000000)) / 10;
#else
gettimeofday(t, NULL);
#endif
}
#define LISTEN_SUCCESS 2
#define LISTEN_SEND_VERIFY_REQUEST 1
#ifndef OPENSSL_NO_SOCK
int DTLSv1_listen(SSL *s, BIO_ADDR *client)
{
- int next, n, ret = 0, clearpkt = 0;
+ int next, n, ret = 0;
unsigned char cookie[DTLS1_COOKIE_LENGTH];
unsigned char seq[SEQ_NUM_SIZE];
const unsigned char *data;
- unsigned char *buf;
- size_t fragoff, fraglen, msglen;
+ unsigned char *buf, *wbuf;
+ size_t fragoff, fraglen, msglen, reclen, align = 0;
unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen;
BIO *rbio, *wbio;
- BUF_MEM *bufm;
BIO_ADDR *tmpclient = NULL;
PACKET pkt, msgpkt, msgpayload, session, cookiepkt;
if (s->handshake_func == NULL) {
/* Not properly initialized yet */
SSL_set_accept_state(s);
}
/* Ensure there is no state left over from a previous invocation */
if (!SSL_clear(s))
return -1;
ERR_clear_error();
rbio = SSL_get_rbio(s);
wbio = SSL_get_wbio(s);
if (!rbio || !wbio) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET);
return -1;
}
- /*
- * We only peek at incoming ClientHello's until we're sure we are going to
- * to respond with a HelloVerifyRequest. If its a ClientHello with a valid
- * cookie then we leave it in the BIO for accept to handle.
- */
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL);
-
/*
* Note: This check deliberately excludes DTLS1_BAD_VER because that version
* requires the MAC to be calculated *including* the first ClientHello
* (without the cookie). Since DTLSv1_listen is stateless that cannot be
* supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via
* SSL_accept)
*/
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION);
return -1;
}
- if (s->init_buf == NULL) {
- if ((bufm = BUF_MEM_new()) == NULL) {
- SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
- return -1;
- }
-
- if (!BUF_MEM_grow(bufm, SSL3_RT_MAX_PLAIN_LENGTH)) {
- BUF_MEM_free(bufm);
- SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
- return -1;
- }
- s->init_buf = bufm;
+ if (!ssl3_setup_buffers(s)) {
+ /* SSLerr already called */
+ return -1;
}
- buf = (unsigned char *)s->init_buf->data;
+ buf = RECORD_LAYER_get_rbuf(&s->rlayer)->buf;
+ wbuf = RECORD_LAYER_get_wbuf(&s->rlayer)[0].buf;
+#if defined(SSL3_ALIGN_PAYLOAD)
+# if SSL3_ALIGN_PAYLOAD != 0
+ /*
+ * Using SSL3_RT_HEADER_LENGTH here instead of DTLS1_RT_HEADER_LENGTH for
+ * consistency with ssl3_read_n. In practice it should make no difference
+ * for sensible values of SSL3_ALIGN_PAYLOAD because the difference between
+ * SSL3_RT_HEADER_LENGTH and DTLS1_RT_HEADER_LENGTH is exactly 8
+ */
+ align = (size_t)buf + SSL3_RT_HEADER_LENGTH;
+ align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
+# endif
+#endif
+ buf += align;
do {
/* Get a packet */
clear_sys_error();
- /*
- * Technically a ClientHello could be SSL3_RT_MAX_PLAIN_LENGTH
- * + DTLS1_RT_HEADER_LENGTH bytes long. Normally init_buf does not store
- * the record header as well, but we do here. We've set up init_buf to
- * be the standard size for simplicity. In practice we shouldn't ever
- * receive a ClientHello as long as this. If we do it will get dropped
- * in the record length check below.
- */
- n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
-
+ n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH
+ + DTLS1_RT_HEADER_LENGTH);
if (n <= 0) {
if (BIO_should_retry(rbio)) {
/* Non-blocking IO */
goto end;
}
return -1;
}
- /* If we hit any problems we need to clear this packet from the BIO */
- clearpkt = 1;
-
if (!PACKET_buf_init(&pkt, buf, n)) {
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
return -1;
}
/*
* Parse the received record. If there are any problems with it we just
* dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is
* resilient in the face of invalid records (e.g., invalid formatting,
* length, MAC, etc.). In general, invalid records SHOULD be silently
* discarded, thus preserving the association; however, an error MAY be
* logged for diagnostic purposes."
*/
/* this packet contained a partial record, dump it */
if (n < DTLS1_RT_HEADER_LENGTH) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL);
goto end;
}
if (s->msg_callback)
s->msg_callback(0, 0, SSL3_RT_HEADER, buf,
DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
/* Get the record header */
if (!PACKET_get_1(&pkt, &rectype)
|| !PACKET_get_1(&pkt, &versmajor)) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
if (rectype != SSL3_RT_HANDSHAKE) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
/*
* Check record version number. We only check that the major version is
* the same.
*/
if (versmajor != DTLS1_VERSION_MAJOR) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
goto end;
}
if (!PACKET_forward(&pkt, 1)
/* Save the sequence number: 64 bits, with top 2 bytes = epoch */
|| !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE)
|| !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
+ reclen = PACKET_remaining(&msgpkt);
/*
* We allow data remaining at the end of the packet because there could
* be a second record (but we ignore it)
*/
/* This is an initial ClientHello so the epoch has to be 0 */
if (seq[0] != 0 || seq[1] != 0) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
/* Get a pointer to the raw message for the later callback */
data = PACKET_data(&msgpkt);
/* Finished processing the record header, now process the message */
if (!PACKET_get_1(&msgpkt, &msgtype)
|| !PACKET_get_net_3_len(&msgpkt, &msglen)
|| !PACKET_get_net_2(&msgpkt, &msgseq)
|| !PACKET_get_net_3_len(&msgpkt, &fragoff)
|| !PACKET_get_net_3_len(&msgpkt, &fraglen)
|| !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen)
|| PACKET_remaining(&msgpkt) != 0) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
if (msgtype != SSL3_MT_CLIENT_HELLO) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
/* Message sequence number can only be 0 or 1 */
if (msgseq > 2) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER);
goto end;
}
/*
* We don't support fragment reassembly for ClientHellos whilst
* listening because that would require server side state (which is
* against the whole point of the ClientHello/HelloVerifyRequest
* mechanism). Instead we only look at the first ClientHello fragment
* and require that the cookie must be contained within it.
*/
if (fragoff != 0 || fraglen > msglen) {
/* Non initial ClientHello fragment (or bad fragment) */
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
goto end;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data,
fraglen + DTLS1_HM_HEADER_LENGTH, s,
s->msg_callback_arg);
if (!PACKET_get_net_2(&msgpayload, &clientvers)) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
/*
* Verify client version is supported
*/
if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) &&
s->method->version != DTLS_ANY_VERSION) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
goto end;
}
if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE)
|| !PACKET_get_length_prefixed_1(&msgpayload, &session)
|| !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) {
/*
* Could be malformed or the cookie does not fit within the initial
* ClientHello fragment. Either way we can't handle it.
*/
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
/*
* Check if we have a cookie or not. If not we need to send a
* HelloVerifyRequest.
*/
if (PACKET_remaining(&cookiepkt) == 0) {
next = LISTEN_SEND_VERIFY_REQUEST;
} else {
/*
* We have a cookie, so lets check it.
*/
if (s->ctx->app_verify_cookie_cb == NULL) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
/* This is fatal */
return -1;
}
if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookiepkt),
(unsigned int)PACKET_remaining(&cookiepkt)) == 0) {
/*
* We treat invalid cookies in the same was as no cookie as
* per RFC6347
*/
next = LISTEN_SEND_VERIFY_REQUEST;
} else {
/* Cookie verification succeeded */
next = LISTEN_SUCCESS;
}
}
if (next == LISTEN_SEND_VERIFY_REQUEST) {
WPACKET wpkt;
unsigned int version;
size_t wreclen;
/*
* There was no cookie in the ClientHello so we need to send a
* HelloVerifyRequest. If this fails we do not worry about trying
* to resend, we just drop it.
*/
- /*
- * Dump the read packet, we don't need it any more. Ignore return
- * value
- */
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
- BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL);
-
/* Generate the cookie */
if (s->ctx->app_gen_cookie_cb == NULL ||
s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 ||
cookielen > 255) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
/* This is fatal */
return -1;
}
/*
* Special case: for hello verify request, client version 1.0 and we
* haven't decided which version to use yet send back using version
* 1.0 header: otherwise some clients will ignore it.
*/
version = (s->method->version == DTLS_ANY_VERSION) ? DTLS1_VERSION
: s->version;
/* Construct the record and message headers */
- if (!WPACKET_init(&wpkt, s->init_buf)
+ if (!WPACKET_init_static_len(&wpkt,
+ wbuf,
+ ssl_get_max_send_fragment(s)
+ + DTLS1_RT_HEADER_LENGTH,
+ 0)
|| !WPACKET_put_bytes_u8(&wpkt, SSL3_RT_HANDSHAKE)
|| !WPACKET_put_bytes_u16(&wpkt, version)
/*
* Record sequence number is always the same as in the
* received ClientHello
*/
|| !WPACKET_memcpy(&wpkt, seq, SEQ_NUM_SIZE)
/* End of record, start sub packet for message */
|| !WPACKET_start_sub_packet_u16(&wpkt)
/* Message type */
|| !WPACKET_put_bytes_u8(&wpkt,
DTLS1_MT_HELLO_VERIFY_REQUEST)
/*
* Message length - doesn't follow normal TLS convention:
* the length isn't the last thing in the message header.
* We'll need to fill this in later when we know the
* length. Set it to zero for now
*/
|| !WPACKET_put_bytes_u24(&wpkt, 0)
/*
* Message sequence number is always 0 for a
* HelloVerifyRequest
*/
|| !WPACKET_put_bytes_u16(&wpkt, 0)
/*
* We never fragment a HelloVerifyRequest, so fragment
* offset is 0
*/
|| !WPACKET_put_bytes_u24(&wpkt, 0)
/*
* Fragment length is the same as message length, but
* this *is* the last thing in the message header so we
* can just start a sub-packet. No need to come back
* later for this one.
*/
|| !WPACKET_start_sub_packet_u24(&wpkt)
/* Create the actual HelloVerifyRequest body */
|| !dtls_raw_hello_verify_request(&wpkt, cookie, cookielen)
/* Close message body */
|| !WPACKET_close(&wpkt)
/* Close record body */
|| !WPACKET_close(&wpkt)
|| !WPACKET_get_total_written(&wpkt, &wreclen)
|| !WPACKET_finish(&wpkt)) {
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
WPACKET_cleanup(&wpkt);
/* This is fatal */
return -1;
}
/*
* Fix up the message len in the message header. Its the same as the
* fragment len which has been filled in by WPACKET, so just copy
* that. Destination for the message len is after the record header
* plus one byte for the message content type. The source is the
* last 3 bytes of the message header
*/
- memcpy(&buf[DTLS1_RT_HEADER_LENGTH + 1],
- &buf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3],
+ memcpy(&wbuf[DTLS1_RT_HEADER_LENGTH + 1],
+ &wbuf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3],
3);
if (s->msg_callback)
s->msg_callback(1, 0, SSL3_RT_HEADER, buf,
DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
if ((tmpclient = BIO_ADDR_new()) == NULL) {
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
goto end;
}
/*
* This is unnecessary if rbio and wbio are one and the same - but
* maybe they're not. We ignore errors here - some BIOs do not
* support this.
*/
if (BIO_dgram_get_peer(rbio, tmpclient) > 0) {
(void)BIO_dgram_set_peer(wbio, tmpclient);
}
BIO_ADDR_free(tmpclient);
tmpclient = NULL;
/* TODO(size_t): convert this call */
- if (BIO_write(wbio, buf, wreclen) < (int)wreclen) {
+ if (BIO_write(wbio, wbuf, wreclen) < (int)wreclen) {
if (BIO_should_retry(wbio)) {
/*
* Non-blocking IO...but we're stateless, so we're just
* going to drop this packet.
*/
goto end;
}
return -1;
}
if (BIO_flush(wbio) <= 0) {
if (BIO_should_retry(wbio)) {
/*
* Non-blocking IO...but we're stateless, so we're just
* going to drop this packet.
*/
goto end;
}
return -1;
}
}
} while (next != LISTEN_SUCCESS);
/*
* Set expected sequence numbers to continue the handshake.
*/
s->d1->handshake_read_seq = 1;
s->d1->handshake_write_seq = 1;
s->d1->next_handshake_write_seq = 1;
DTLS_RECORD_LAYER_set_write_sequence(&s->rlayer, seq);
/*
* We are doing cookie exchange, so make sure we set that option in the
* SSL object
*/
SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
/*
* Tell the state machine that we've done the initial hello verify
* exchange
*/
ossl_statem_set_hello_verify_done(s);
/*
* Some BIOs may not support this. If we fail we clear the client address
*/
if (BIO_dgram_get_peer(rbio, client) <= 0)
BIO_ADDR_clear(client);
+ /* Buffer the record in the processed_rcds queue */
+ if (!dtls_buffer_listen_record(s, reclen, seq, align))
+ return -1;
+
ret = 1;
- clearpkt = 0;
end:
BIO_ADDR_free(tmpclient);
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
- if (clearpkt) {
- /* Dump this packet. Ignore return value */
- BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
- }
return ret;
}
#endif
static int dtls1_handshake_write(SSL *s)
{
return dtls1_do_write(s, SSL3_RT_HANDSHAKE);
}
int dtls1_shutdown(SSL *s)
{
int ret;
#ifndef OPENSSL_NO_SCTP
BIO *wbio;
wbio = SSL_get_wbio(s);
if (wbio != NULL && BIO_dgram_is_sctp(wbio) &&
!(s->shutdown & SSL_SENT_SHUTDOWN)) {
ret = BIO_dgram_sctp_wait_for_dry(wbio);
if (ret < 0)
return -1;
if (ret == 0)
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1,
NULL);
}
#endif
ret = ssl3_shutdown(s);
#ifndef OPENSSL_NO_SCTP
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
#endif
return ret;
}
int dtls1_query_mtu(SSL *s)
{
if (s->d1->link_mtu) {
s->d1->mtu =
s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
s->d1->link_mtu = 0;
}
/* AHA! Figure out the MTU, and stick to the right size */
if (s->d1->mtu < dtls1_min_mtu(s)) {
if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
s->d1->mtu =
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
/*
* I've seen the kernel return bogus numbers when it doesn't know
* (initial write), so just make sure we have a reasonable number
*/
if (s->d1->mtu < dtls1_min_mtu(s)) {
/* Set to min mtu */
s->d1->mtu = dtls1_min_mtu(s);
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
(long)s->d1->mtu, NULL);
}
} else
return 0;
}
return 1;
}
static size_t dtls1_link_min_mtu(void)
{
return (g_probable_mtu[(sizeof(g_probable_mtu) /
sizeof(g_probable_mtu[0])) - 1]);
}
size_t dtls1_min_mtu(SSL *s)
{
return dtls1_link_min_mtu() - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
}
size_t DTLS_get_data_mtu(const SSL *s)
{
size_t mac_overhead, int_overhead, blocksize, ext_overhead;
const SSL_CIPHER *ciph = SSL_get_current_cipher(s);
size_t mtu = s->d1->mtu;
if (ciph == NULL)
return 0;
if (!ssl_cipher_get_overhead(ciph, &mac_overhead, &int_overhead,
&blocksize, &ext_overhead))
return 0;
if (SSL_READ_ETM(s))
ext_overhead += mac_overhead;
else
int_overhead += mac_overhead;
/* Subtract external overhead (e.g. IV/nonce, separate MAC) */
if (ext_overhead + DTLS1_RT_HEADER_LENGTH >= mtu)
return 0;
mtu -= ext_overhead + DTLS1_RT_HEADER_LENGTH;
/* Round encrypted payload down to cipher block size (for CBC etc.)
* No check for overflow since 'mtu % blocksize' cannot exceed mtu. */
if (blocksize)
mtu -= (mtu % blocksize);
/* Subtract internal overhead (e.g. CBC padding len byte) */
if (int_overhead >= mtu)
return 0;
mtu -= int_overhead;
return mtu;
}
void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb)
{
s->d1->timer_cb = cb;
}
diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c
index 43e1f9895319..1f9b31969d82 100644
--- a/ssl/record/rec_layer_d1.c
+++ b/ssl/record/rec_layer_d1.c
@@ -1,1075 +1,1072 @@
/*
* Copyright 2005-2018 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 "../ssl_locl.h"
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include "record_locl.h"
#include "../packet_locl.h"
#include "internal/cryptlib.h"
int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
{
DTLS_RECORD_LAYER *d;
if ((d = OPENSSL_malloc(sizeof(*d))) == NULL) {
SSLerr(SSL_F_DTLS_RECORD_LAYER_NEW, ERR_R_MALLOC_FAILURE);
return 0;
}
rl->d = d;
d->unprocessed_rcds.q = pqueue_new();
d->processed_rcds.q = pqueue_new();
d->buffered_app_data.q = pqueue_new();
if (d->unprocessed_rcds.q == NULL || d->processed_rcds.q == NULL
|| d->buffered_app_data.q == NULL) {
pqueue_free(d->unprocessed_rcds.q);
pqueue_free(d->processed_rcds.q);
pqueue_free(d->buffered_app_data.q);
OPENSSL_free(d);
rl->d = NULL;
return 0;
}
return 1;
}
void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl)
{
DTLS_RECORD_LAYER_clear(rl);
pqueue_free(rl->d->unprocessed_rcds.q);
pqueue_free(rl->d->processed_rcds.q);
pqueue_free(rl->d->buffered_app_data.q);
OPENSSL_free(rl->d);
rl->d = NULL;
}
void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl)
{
DTLS_RECORD_LAYER *d;
pitem *item = NULL;
DTLS1_RECORD_DATA *rdata;
pqueue *unprocessed_rcds;
pqueue *processed_rcds;
pqueue *buffered_app_data;
d = rl->d;
while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) {
rdata = (DTLS1_RECORD_DATA *)item->data;
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(item->data);
pitem_free(item);
}
while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) {
rdata = (DTLS1_RECORD_DATA *)item->data;
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(item->data);
pitem_free(item);
}
while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) {
rdata = (DTLS1_RECORD_DATA *)item->data;
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(item->data);
pitem_free(item);
}
unprocessed_rcds = d->unprocessed_rcds.q;
processed_rcds = d->processed_rcds.q;
buffered_app_data = d->buffered_app_data.q;
memset(d, 0, sizeof(*d));
d->unprocessed_rcds.q = unprocessed_rcds;
d->processed_rcds.q = processed_rcds;
d->buffered_app_data.q = buffered_app_data;
}
void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e)
{
if (e == rl->d->w_epoch - 1) {
memcpy(rl->d->curr_write_sequence,
rl->write_sequence, sizeof(rl->write_sequence));
memcpy(rl->write_sequence,
rl->d->last_write_sequence, sizeof(rl->write_sequence));
} else if (e == rl->d->w_epoch + 1) {
memcpy(rl->d->last_write_sequence,
rl->write_sequence, sizeof(unsigned char[8]));
memcpy(rl->write_sequence,
rl->d->curr_write_sequence, sizeof(rl->write_sequence));
}
rl->d->w_epoch = e;
}
void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq)
{
memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE);
}
/* copy buffered record into SSL structure */
static int dtls1_copy_record(SSL *s, pitem *item)
{
DTLS1_RECORD_DATA *rdata;
rdata = (DTLS1_RECORD_DATA *)item->data;
SSL3_BUFFER_release(&s->rlayer.rbuf);
s->rlayer.packet = rdata->packet;
s->rlayer.packet_length = rdata->packet_length;
memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER));
memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD));
/* Set proper sequence number for mac calculation */
memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
return 1;
}
int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
{
DTLS1_RECORD_DATA *rdata;
pitem *item;
/* Limit the size of the queue to prevent DOS attacks */
if (pqueue_size(queue->q) >= 100)
return 0;
rdata = OPENSSL_malloc(sizeof(*rdata));
item = pitem_new(priority, rdata);
if (rdata == NULL || item == NULL) {
OPENSSL_free(rdata);
pitem_free(item);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_BUFFER_RECORD,
ERR_R_INTERNAL_ERROR);
return -1;
}
rdata->packet = s->rlayer.packet;
rdata->packet_length = s->rlayer.packet_length;
memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER));
memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD));
item->data = rdata;
#ifndef OPENSSL_NO_SCTP
/* Store bio_dgram_sctp_rcvinfo struct */
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
(SSL_get_state(s) == TLS_ST_SR_FINISHED
|| SSL_get_state(s) == TLS_ST_CR_FINISHED)) {
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO,
sizeof(rdata->recordinfo), &rdata->recordinfo);
}
#endif
s->rlayer.packet = NULL;
s->rlayer.packet_length = 0;
memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf));
memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec));
if (!ssl3_setup_buffers(s)) {
/* SSLfatal() already called */
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(rdata);
pitem_free(item);
return -1;
}
- /* insert should not fail, since duplicates are dropped */
if (pqueue_insert(queue->q, item) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_BUFFER_RECORD,
- ERR_R_INTERNAL_ERROR);
+ /* Must be a duplicate so ignore it */
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(rdata);
pitem_free(item);
- return -1;
}
return 1;
}
int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
{
pitem *item;
item = pqueue_pop(queue->q);
if (item) {
dtls1_copy_record(s, item);
OPENSSL_free(item->data);
pitem_free(item);
return 1;
}
return 0;
}
/*
* retrieve a buffered record that belongs to the new epoch, i.e., not
* processed yet
*/
#define dtls1_get_unprocessed_record(s) \
dtls1_retrieve_buffered_record((s), \
&((s)->rlayer.d->unprocessed_rcds))
int dtls1_process_buffered_records(SSL *s)
{
pitem *item;
SSL3_BUFFER *rb;
SSL3_RECORD *rr;
DTLS1_BITMAP *bitmap;
unsigned int is_next_epoch;
int replayok = 1;
item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q);
if (item) {
/* Check if epoch is current. */
if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
return 1; /* Nothing to do. */
rr = RECORD_LAYER_get_rrec(&s->rlayer);
rb = RECORD_LAYER_get_rbuf(&s->rlayer);
if (SSL3_BUFFER_get_left(rb) > 0) {
/*
* We've still got data from the current packet to read. There could
* be a record from the new epoch in it - so don't overwrite it
* with the unprocessed records yet (we'll do it when we've
* finished reading the current packet).
*/
return 1;
}
/* Process all the records. */
while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) {
dtls1_get_unprocessed_record(s);
bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
if (bitmap == NULL) {
/*
* Should not happen. This will only ever be NULL when the
* current record is from a different epoch. But that cannot
* be the case because we already checked the epoch above
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS,
ERR_R_INTERNAL_ERROR);
return 0;
}
#ifndef OPENSSL_NO_SCTP
/* Only do replay check if no SCTP bio */
if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
#endif
{
/*
* Check whether this is a repeat, or aged record. We did this
* check once already when we first received the record - but
* we might have updated the window since then due to
* records we subsequently processed.
*/
replayok = dtls1_record_replay_check(s, bitmap);
}
if (!replayok || !dtls1_process_record(s, bitmap)) {
if (ossl_statem_in_error(s)) {
/* dtls1_process_record called SSLfatal() */
return -1;
}
/* dump this record */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
continue;
}
if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) {
/* SSLfatal() already called */
return 0;
}
}
}
/*
* sync epoch numbers once all the unprocessed records have been
* processed
*/
s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch;
s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
return 1;
}
/*-
* Return up to 'len' payload bytes received in 'type' records.
* 'type' is one of the following:
*
* - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
* - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
* - 0 (during a shutdown, no data has to be returned)
*
* If we don't have stored data to work from, read a SSL/TLS record first
* (possibly multiple records if we still don't have anything to return).
*
* This function must handle any surprises the peer may have for us, such as
* Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec
* messages are treated as if they were handshake messages *if* the |recd_type|
* argument is non NULL.
* Also if record payloads contain fragments too small to process, we store
* them until there is enough for the respective protocol (the record protocol
* may use arbitrary fragmentation and even interleaving):
* Change cipher spec protocol
* just 1 byte needed, no need for keeping anything stored
* Alert protocol
* 2 bytes needed (AlertLevel, AlertDescription)
* Handshake protocol
* 4 bytes needed (HandshakeType, uint24 length) -- we just have
* to detect unexpected Client Hello and Hello Request messages
* here, anything else is handled by higher layers
* Application data protocol
* none of our business
*/
int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
size_t len, int peek, size_t *readbytes)
{
int i, j, iret;
size_t n;
SSL3_RECORD *rr;
void (*cb) (const SSL *ssl, int type2, int val) = NULL;
if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) {
/* Not initialized yet */
if (!ssl3_setup_buffers(s)) {
/* SSLfatal() already called */
return -1;
}
}
if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
(type != SSL3_RT_HANDSHAKE)) ||
(peek && (type != SSL3_RT_APPLICATION_DATA))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES,
ERR_R_INTERNAL_ERROR);
return -1;
}
if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) {
/* type == SSL3_RT_APPLICATION_DATA */
i = s->handshake_func(s);
/* SSLfatal() already called if appropriate */
if (i < 0)
return i;
if (i == 0)
return -1;
}
start:
s->rwstate = SSL_NOTHING;
/*-
* s->s3->rrec.type - is the type of record
* s->s3->rrec.data, - data
* s->s3->rrec.off, - offset into 'data' for next read
* s->s3->rrec.length, - number of bytes.
*/
rr = s->rlayer.rrec;
/*
* We are not handshaking and have no data yet, so process data buffered
* during the last handshake in advance, if any.
*/
if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) {
pitem *item;
item = pqueue_pop(s->rlayer.d->buffered_app_data.q);
if (item) {
#ifndef OPENSSL_NO_SCTP
/* Restore bio_dgram_sctp_rcvinfo struct */
if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
sizeof(rdata->recordinfo), &rdata->recordinfo);
}
#endif
dtls1_copy_record(s, item);
OPENSSL_free(item->data);
pitem_free(item);
}
}
/* Check for timeout */
if (dtls1_handle_timeout(s) > 0) {
goto start;
} else if (ossl_statem_in_error(s)) {
/* dtls1_handle_timeout() has failed with a fatal error */
return -1;
}
/* get new packet if necessary */
if ((SSL3_RECORD_get_length(rr) == 0)
|| (s->rlayer.rstate == SSL_ST_READ_BODY)) {
RECORD_LAYER_set_numrpipes(&s->rlayer, 0);
iret = dtls1_get_record(s);
if (iret <= 0) {
iret = dtls1_read_failed(s, iret);
/*
* Anything other than a timeout is an error. SSLfatal() already
* called if appropriate.
*/
if (iret <= 0)
return iret;
else
goto start;
}
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
}
/*
* Reset the count of consecutive warning alerts if we've got a non-empty
* record that isn't an alert.
*/
if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT
&& SSL3_RECORD_get_length(rr) != 0)
s->rlayer.alert_count = 0;
if (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE
&& SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC
&& !SSL_in_init(s)
&& (s->d1->next_timeout.tv_sec != 0
|| s->d1->next_timeout.tv_usec != 0)) {
/*
* The timer is still running but we've received something that isn't
* handshake data - so the peer must have finished processing our
* last handshake flight. Stop the timer.
*/
dtls1_stop_timer(s);
}
/* we now have a packet which can be read and processed */
if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
* reset by ssl3_get_finished */
&& (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
/*
* We now have application data between CCS and Finished. Most likely
* the packets were reordered on their way, so buffer the application
* data for later processing rather than dropping the connection.
*/
if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data),
SSL3_RECORD_get_seq_num(rr)) < 0) {
/* SSLfatal() already called */
return -1;
}
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
goto start;
}
/*
* If the other end has shut down, throw anything we read away (even in
* 'peek' mode)
*/
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
s->rwstate = SSL_NOTHING;
return 0;
}
if (type == SSL3_RECORD_get_type(rr)
|| (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
&& type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) {
/*
* SSL3_RT_APPLICATION_DATA or
* SSL3_RT_HANDSHAKE or
* SSL3_RT_CHANGE_CIPHER_SPEC
*/
/*
* make sure that we are not getting application data when we are
* doing a handshake for the first time
*/
if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
(s->enc_read_ctx == NULL)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
SSL_R_APP_DATA_IN_HANDSHAKE);
return -1;
}
if (recvd_type != NULL)
*recvd_type = SSL3_RECORD_get_type(rr);
if (len == 0) {
/*
* Mark a zero length record as read. This ensures multiple calls to
* SSL_read() with a zero length buffer will eventually cause
* SSL_pending() to report data as being available.
*/
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
return 0;
}
if (len > SSL3_RECORD_get_length(rr))
n = SSL3_RECORD_get_length(rr);
else
n = len;
memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
if (peek) {
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
} else {
SSL3_RECORD_sub_length(rr, n);
SSL3_RECORD_add_off(rr, n);
if (SSL3_RECORD_get_length(rr) == 0) {
s->rlayer.rstate = SSL_ST_READ_HEADER;
SSL3_RECORD_set_off(rr, 0);
SSL3_RECORD_set_read(rr);
}
}
#ifndef OPENSSL_NO_SCTP
/*
* We might had to delay a close_notify alert because of reordered
* app data. If there was an alert and there is no message to read
* anymore, finally set shutdown.
*/
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
s->d1->shutdown_received
&& !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return 0;
}
#endif
*readbytes = n;
return 1;
}
/*
* If we get here, then type != rr->type; if we have a handshake message,
* then it was unexpected (Hello Request or Client Hello).
*/
if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
unsigned int alert_level, alert_descr;
unsigned char *alert_bytes = SSL3_RECORD_get_data(rr)
+ SSL3_RECORD_get_off(rr);
PACKET alert;
if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr))
|| !PACKET_get_1(&alert, &alert_level)
|| !PACKET_get_1(&alert, &alert_descr)
|| PACKET_remaining(&alert) != 0) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
SSL_R_INVALID_ALERT);
return -1;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s,
s->msg_callback_arg);
if (s->info_callback != NULL)
cb = s->info_callback;
else if (s->ctx->info_callback != NULL)
cb = s->ctx->info_callback;
if (cb != NULL) {
j = (alert_level << 8) | alert_descr;
cb(s, SSL_CB_READ_ALERT, j);
}
if (alert_level == SSL3_AL_WARNING) {
s->s3->warn_alert = alert_descr;
SSL3_RECORD_set_read(rr);
s->rlayer.alert_count++;
if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
SSL_R_TOO_MANY_WARN_ALERTS);
return -1;
}
if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
#ifndef OPENSSL_NO_SCTP
/*
* With SCTP and streams the socket may deliver app data
* after a close_notify alert. We have to check this first so
* that nothing gets discarded.
*/
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
s->d1->shutdown_received = 1;
s->rwstate = SSL_READING;
BIO_clear_retry_flags(SSL_get_rbio(s));
BIO_set_retry_read(SSL_get_rbio(s));
return -1;
}
#endif
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return 0;
}
} else if (alert_level == SSL3_AL_FATAL) {
char tmp[16];
s->rwstate = SSL_NOTHING;
s->s3->fatal_alert = alert_descr;
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS1_READ_BYTES,
SSL_AD_REASON_OFFSET + alert_descr);
BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
ERR_add_error_data(2, "SSL alert number ", tmp);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
SSL3_RECORD_set_read(rr);
SSL_CTX_remove_session(s->session_ctx, s->session);
return 0;
} else {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_READ_BYTES,
SSL_R_UNKNOWN_ALERT_TYPE);
return -1;
}
goto start;
}
if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a
* shutdown */
s->rwstate = SSL_NOTHING;
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
return 0;
}
if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
/*
* We can't process a CCS now, because previous handshake messages
* are still missing, so just drop it.
*/
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
goto start;
}
/*
* Unexpected handshake message (Client Hello, or protocol violation)
*/
if ((SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) &&
!ossl_statem_get_in_handshake(s)) {
struct hm_header_st msg_hdr;
/*
* This may just be a stale retransmit. Also sanity check that we have
* at least enough record bytes for a message header
*/
if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch
|| SSL3_RECORD_get_length(rr) < DTLS1_HM_HEADER_LENGTH) {
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
goto start;
}
dtls1_get_message_header(rr->data, &msg_hdr);
/*
* If we are server, we may have a repeated FINISHED of the client
* here, then retransmit our CCS and FINISHED.
*/
if (msg_hdr.type == SSL3_MT_FINISHED) {
if (dtls1_check_timeout_num(s) < 0) {
/* SSLfatal) already called */
return -1;
}
if (dtls1_retransmit_buffered_messages(s) <= 0) {
/* Fail if we encountered a fatal error */
if (ossl_statem_in_error(s))
return -1;
}
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
/* no read-ahead left? */
BIO *bio;
s->rwstate = SSL_READING;
bio = SSL_get_rbio(s);
BIO_clear_retry_flags(bio);
BIO_set_retry_read(bio);
return -1;
}
}
goto start;
}
/*
* To get here we must be trying to read app data but found handshake
* data. But if we're trying to read app data, and we're not in init
* (which is tested for at the top of this function) then init must be
* finished
*/
if (!ossl_assert(SSL_is_init_finished(s))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES,
ERR_R_INTERNAL_ERROR);
return -1;
}
/* We found handshake data, so we're going back into init */
ossl_statem_set_in_init(s, 1);
i = s->handshake_func(s);
/* SSLfatal() called if appropriate */
if (i < 0)
return i;
if (i == 0)
return -1;
if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
/* no read-ahead left? */
BIO *bio;
/*
* In the case where we try to read application data, but we
* trigger an SSL handshake, we return -1 with the retry
* option set. Otherwise renegotiation may cause nasty
* problems in the blocking world
*/
s->rwstate = SSL_READING;
bio = SSL_get_rbio(s);
BIO_clear_retry_flags(bio);
BIO_set_retry_read(bio);
return -1;
}
}
goto start;
}
switch (SSL3_RECORD_get_type(rr)) {
default:
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
SSL_R_UNEXPECTED_RECORD);
return -1;
case SSL3_RT_CHANGE_CIPHER_SPEC:
case SSL3_RT_ALERT:
case SSL3_RT_HANDSHAKE:
/*
* we already handled all of these, with the possible exception of
* SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but
* that should not happen when type != rr->type
*/
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
ERR_R_INTERNAL_ERROR);
return -1;
case SSL3_RT_APPLICATION_DATA:
/*
* At this point, we were expecting handshake data, but have
* application data. If the library was running inside ssl3_read()
* (i.e. in_read_app_data is set) and it makes sense to read
* application data at this point (session renegotiation not yet
* started), we will indulge it.
*/
if (s->s3->in_read_app_data &&
(s->s3->total_renegotiations != 0) &&
ossl_statem_app_data_allowed(s)) {
s->s3->in_read_app_data = 2;
return -1;
} else {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
SSL_R_UNEXPECTED_RECORD);
return -1;
}
}
/* not reached */
}
/*
* Call this to write data in records of type 'type' It will return <= 0 if
* not all data has been sent or non-blocking IO.
*/
int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len,
size_t *written)
{
int i;
if (!ossl_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_WRITE_BYTES,
ERR_R_INTERNAL_ERROR);
return -1;
}
s->rwstate = SSL_NOTHING;
i = do_dtls1_write(s, type, buf, len, 0, written);
return i;
}
int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
size_t len, int create_empty_fragment, size_t *written)
{
unsigned char *p, *pseq;
int i, mac_size, clear = 0;
size_t prefix_len = 0;
int eivlen;
SSL3_RECORD wr;
SSL3_BUFFER *wb;
SSL_SESSION *sess;
wb = &s->rlayer.wbuf[0];
/*
* first check if there is a SSL3_BUFFER still being written out. This
* will happen with non blocking IO
*/
if (!ossl_assert(SSL3_BUFFER_get_left(wb) == 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* If we have an alert to send, lets send it */
if (s->s3->alert_dispatch) {
i = s->method->ssl_dispatch_alert(s);
if (i <= 0)
return i;
/* if it went, fall through and send more stuff */
}
if (len == 0 && !create_empty_fragment)
return 0;
if (len > ssl_get_max_send_fragment(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
return 0;
}
sess = s->session;
if ((sess == NULL) ||
(s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL))
clear = 1;
if (clear)
mac_size = 0;
else {
mac_size = EVP_MD_CTX_size(s->write_hash);
if (mac_size < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
return -1;
}
}
p = SSL3_BUFFER_get_buf(wb) + prefix_len;
/* write the header */
*(p++) = type & 0xff;
SSL3_RECORD_set_type(&wr, type);
/*
* Special case: for hello verify request, client version 1.0 and we
* haven't decided which version to use yet send back using version 1.0
* header: otherwise some clients will ignore it.
*/
if (s->method->version == DTLS_ANY_VERSION &&
s->max_proto_version != DTLS1_BAD_VER) {
*(p++) = DTLS1_VERSION >> 8;
*(p++) = DTLS1_VERSION & 0xff;
} else {
*(p++) = s->version >> 8;
*(p++) = s->version & 0xff;
}
/* field where we are to write out packet epoch, seq num and len */
pseq = p;
p += 10;
/* Explicit IV length, block ciphers appropriate version flag */
if (s->enc_write_ctx) {
int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
if (mode == EVP_CIPH_CBC_MODE) {
eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
if (eivlen <= 1)
eivlen = 0;
}
/* Need explicit part of IV for GCM mode */
else if (mode == EVP_CIPH_GCM_MODE)
eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
else if (mode == EVP_CIPH_CCM_MODE)
eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
else
eivlen = 0;
} else
eivlen = 0;
/* lets setup the record stuff. */
SSL3_RECORD_set_data(&wr, p + eivlen); /* make room for IV in case of CBC */
SSL3_RECORD_set_length(&wr, len);
SSL3_RECORD_set_input(&wr, (unsigned char *)buf);
/*
* we now 'read' from wr.input, wr.length bytes into wr.data
*/
/* first we compress */
if (s->compress != NULL) {
if (!ssl3_do_compress(s, &wr)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
SSL_R_COMPRESSION_FAILURE);
return -1;
}
} else {
memcpy(SSL3_RECORD_get_data(&wr), SSL3_RECORD_get_input(&wr),
SSL3_RECORD_get_length(&wr));
SSL3_RECORD_reset_input(&wr);
}
/*
* we should still have the output to wr.data and the input from
* wr.input. Length should be wr.length. wr.data still points in the
* wb->buf
*/
if (!SSL_WRITE_ETM(s) && mac_size != 0) {
if (!s->method->ssl3_enc->mac(s, &wr,
&(p[SSL3_RECORD_get_length(&wr) + eivlen]),
1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
ERR_R_INTERNAL_ERROR);
return -1;
}
SSL3_RECORD_add_length(&wr, mac_size);
}
/* this is true regardless of mac size */
SSL3_RECORD_set_data(&wr, p);
SSL3_RECORD_reset_input(&wr);
if (eivlen)
SSL3_RECORD_add_length(&wr, eivlen);
if (s->method->ssl3_enc->enc(s, &wr, 1, 1) < 1) {
if (!ossl_statem_in_error(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
ERR_R_INTERNAL_ERROR);
}
return -1;
}
if (SSL_WRITE_ETM(s) && mac_size != 0) {
if (!s->method->ssl3_enc->mac(s, &wr,
&(p[SSL3_RECORD_get_length(&wr)]), 1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
ERR_R_INTERNAL_ERROR);
return -1;
}
SSL3_RECORD_add_length(&wr, mac_size);
}
/* record length after mac and block padding */
/* there's only one epoch between handshake and app data */
s2n(s->rlayer.d->w_epoch, pseq);
memcpy(pseq, &(s->rlayer.write_sequence[2]), 6);
pseq += 6;
s2n(SSL3_RECORD_get_length(&wr), pseq);
if (s->msg_callback)
s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH,
DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
/*
* we should now have wr.data pointing to the encrypted data, which is
* wr->length long
*/
SSL3_RECORD_set_type(&wr, type); /* not needed but helps for debugging */
SSL3_RECORD_add_length(&wr, DTLS1_RT_HEADER_LENGTH);
ssl3_record_sequence_update(&(s->rlayer.write_sequence[0]));
if (create_empty_fragment) {
/*
* we are in a recursive call; just return the length, don't write
* out anything here
*/
*written = wr.length;
return 1;
}
/* now let's set up wb */
SSL3_BUFFER_set_left(wb, prefix_len + SSL3_RECORD_get_length(&wr));
SSL3_BUFFER_set_offset(wb, 0);
/*
* memorize arguments so that ssl3_write_pending can detect bad write
* retries later
*/
s->rlayer.wpend_tot = len;
s->rlayer.wpend_buf = buf;
s->rlayer.wpend_type = type;
s->rlayer.wpend_ret = len;
/* we now just need to write the buffer. Calls SSLfatal() as required. */
return ssl3_write_pending(s, type, buf, len, written);
}
DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
unsigned int *is_next_epoch)
{
*is_next_epoch = 0;
/* In current epoch, accept HM, CCS, DATA, & ALERT */
if (rr->epoch == s->rlayer.d->r_epoch)
return &s->rlayer.d->bitmap;
/*
* Only HM and ALERT messages can be from the next epoch and only if we
* have already processed all of the unprocessed records from the last
* epoch
*/
else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch &&
(rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
*is_next_epoch = 1;
return &s->rlayer.d->next_bitmap;
}
return NULL;
}
void dtls1_reset_seq_numbers(SSL *s, int rw)
{
unsigned char *seq;
unsigned int seq_bytes = sizeof(s->rlayer.read_sequence);
if (rw & SSL3_CC_READ) {
seq = s->rlayer.read_sequence;
s->rlayer.d->r_epoch++;
memcpy(&s->rlayer.d->bitmap, &s->rlayer.d->next_bitmap,
sizeof(s->rlayer.d->bitmap));
memset(&s->rlayer.d->next_bitmap, 0, sizeof(s->rlayer.d->next_bitmap));
/*
* We must not use any buffered messages received from the previous
* epoch
*/
dtls1_clear_received_buffer(s);
} else {
seq = s->rlayer.write_sequence;
memcpy(s->rlayer.d->last_write_sequence, seq,
sizeof(s->rlayer.write_sequence));
s->rlayer.d->w_epoch++;
}
memset(seq, 0, seq_bytes);
}
diff --git a/ssl/record/record.h b/ssl/record/record.h
index 32db8212aa14..af56206e07c9 100644
--- a/ssl/record/record.h
+++ b/ssl/record/record.h
@@ -1,232 +1,236 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 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
*/
/*****************************************************************************
* *
* These structures should be considered PRIVATE to the record layer. No *
* non-record layer code should be using these structures in any way. *
* *
*****************************************************************************/
typedef struct ssl3_buffer_st {
/* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */
unsigned char *buf;
/* default buffer size (or 0 if no default set) */
size_t default_len;
/* buffer size */
size_t len;
/* where to 'copy from' */
size_t offset;
/* how many bytes left */
size_t left;
} SSL3_BUFFER;
#define SEQ_NUM_SIZE 8
typedef struct ssl3_record_st {
/* Record layer version */
/* r */
int rec_version;
/* type of record */
/* r */
int type;
/* How many bytes available */
/* rw */
size_t length;
/*
* How many bytes were available before padding was removed? This is used
* to implement the MAC check in constant time for CBC records.
*/
/* rw */
size_t orig_len;
/* read/write offset into 'buf' */
/* r */
size_t off;
/* pointer to the record data */
/* rw */
unsigned char *data;
/* where the decode bytes are */
/* rw */
unsigned char *input;
/* only used with decompression - malloc()ed */
/* r */
unsigned char *comp;
/* Whether the data from this record has already been read or not */
/* r */
unsigned int read;
/* epoch number, needed by DTLS1 */
/* r */
unsigned long epoch;
/* sequence number, needed by DTLS1 */
/* r */
unsigned char seq_num[SEQ_NUM_SIZE];
} SSL3_RECORD;
typedef struct dtls1_bitmap_st {
/* Track 32 packets on 32-bit systems and 64 - on 64-bit systems */
unsigned long map;
/* Max record number seen so far, 64-bit value in big-endian encoding */
unsigned char max_seq_num[SEQ_NUM_SIZE];
} DTLS1_BITMAP;
typedef struct record_pqueue_st {
unsigned short epoch;
struct pqueue_st *q;
} record_pqueue;
typedef struct dtls1_record_data_st {
unsigned char *packet;
size_t packet_length;
SSL3_BUFFER rbuf;
SSL3_RECORD rrec;
#ifndef OPENSSL_NO_SCTP
struct bio_dgram_sctp_rcvinfo recordinfo;
#endif
} DTLS1_RECORD_DATA;
typedef struct dtls_record_layer_st {
/*
* The current data and handshake epoch. This is initially
* undefined, and starts at zero once the initial handshake is
* completed
*/
unsigned short r_epoch;
unsigned short w_epoch;
/* records being received in the current epoch */
DTLS1_BITMAP bitmap;
/* renegotiation starts a new set of sequence numbers */
DTLS1_BITMAP next_bitmap;
/* Received handshake records (processed and unprocessed) */
record_pqueue unprocessed_rcds;
record_pqueue processed_rcds;
/*
* Buffered application records. Only for records between CCS and
* Finished to prevent either protocol violation or unnecessary message
* loss.
*/
record_pqueue buffered_app_data;
/* save last and current sequence numbers for retransmissions */
unsigned char last_write_sequence[8];
unsigned char curr_write_sequence[8];
} DTLS_RECORD_LAYER;
/*****************************************************************************
* *
* This structure should be considered "opaque" to anything outside of the *
* record layer. No non-record layer code should be accessing the members of *
* this structure. *
* *
*****************************************************************************/
typedef struct record_layer_st {
/* The parent SSL structure */
SSL *s;
/*
* Read as many input bytes as possible (for
* non-blocking reads)
*/
int read_ahead;
/* where we are when reading */
int rstate;
/* How many pipelines can be used to read data */
size_t numrpipes;
/* How many pipelines can be used to write data */
size_t numwpipes;
/* read IO goes into here */
SSL3_BUFFER rbuf;
/* write IO goes into here */
SSL3_BUFFER wbuf[SSL_MAX_PIPELINES];
/* each decoded record goes in here */
SSL3_RECORD rrec[SSL_MAX_PIPELINES];
/* used internally to point at a raw packet */
unsigned char *packet;
size_t packet_length;
/* number of bytes sent so far */
size_t wnum;
unsigned char handshake_fragment[4];
size_t handshake_fragment_len;
/* The number of consecutive empty records we have received */
size_t empty_record_count;
/* partial write - check the numbers match */
/* number bytes written */
size_t wpend_tot;
int wpend_type;
/* number of bytes submitted */
size_t wpend_ret;
const unsigned char *wpend_buf;
unsigned char read_sequence[SEQ_NUM_SIZE];
unsigned char write_sequence[SEQ_NUM_SIZE];
/* Set to true if this is the first record in a connection */
unsigned int is_first_record;
/* Count of the number of consecutive warning alerts received */
unsigned int alert_count;
DTLS_RECORD_LAYER *d;
} RECORD_LAYER;
/*****************************************************************************
* *
* The following macros/functions represent the libssl internal API to the *
* record layer. Any libssl code may call these functions/macros *
* *
*****************************************************************************/
#define MIN_SSL2_RECORD_LEN 9
#define RECORD_LAYER_set_read_ahead(rl, ra) ((rl)->read_ahead = (ra))
#define RECORD_LAYER_get_read_ahead(rl) ((rl)->read_ahead)
#define RECORD_LAYER_get_packet(rl) ((rl)->packet)
#define RECORD_LAYER_get_packet_length(rl) ((rl)->packet_length)
#define RECORD_LAYER_add_packet_length(rl, inc) ((rl)->packet_length += (inc))
#define DTLS_RECORD_LAYER_get_w_epoch(rl) ((rl)->d->w_epoch)
#define DTLS_RECORD_LAYER_get_processed_rcds(rl) \
((rl)->d->processed_rcds)
#define DTLS_RECORD_LAYER_get_unprocessed_rcds(rl) \
((rl)->d->unprocessed_rcds)
+#define RECORD_LAYER_get_rbuf(rl) (&(rl)->rbuf)
+#define RECORD_LAYER_get_wbuf(rl) ((rl)->wbuf)
void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s);
void RECORD_LAYER_clear(RECORD_LAYER *rl);
void RECORD_LAYER_release(RECORD_LAYER *rl);
int RECORD_LAYER_read_pending(const RECORD_LAYER *rl);
int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl);
int RECORD_LAYER_write_pending(const RECORD_LAYER *rl);
void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl);
void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl);
int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl);
size_t RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl);
__owur size_t ssl3_pending(const SSL *s);
__owur int ssl3_write_bytes(SSL *s, int type, const void *buf, size_t len,
size_t *written);
int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
size_t *pipelens, size_t numpipes,
int create_empty_fragment, size_t *written);
__owur int ssl3_read_bytes(SSL *s, int type, int *recvd_type,
unsigned char *buf, size_t len, int peek,
size_t *readbytes);
__owur int ssl3_setup_buffers(SSL *s);
__owur int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int send);
__owur int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
__owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
size_t *written);
__owur int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send);
__owur int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
__owur int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send);
int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl);
void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl);
void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e);
void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq);
__owur int dtls1_read_bytes(SSL *s, int type, int *recvd_type,
unsigned char *buf, size_t len, int peek,
size_t *readbytes);
__owur int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len,
size_t *written);
int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
size_t len, int create_empty_fragment, size_t *written);
void dtls1_reset_seq_numbers(SSL *s, int rw);
+int dtls_buffer_listen_record(SSL *s, size_t len, unsigned char *seq,
+ size_t off);
diff --git a/ssl/record/record_locl.h b/ssl/record/record_locl.h
index 07fd7ab640ba..5e8dd7f70442 100644
--- a/ssl/record/record_locl.h
+++ b/ssl/record/record_locl.h
@@ -1,118 +1,116 @@
/*
* Copyright 1995-2018 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
*/
/*****************************************************************************
* *
* The following macros/functions are PRIVATE to the record layer. They *
* should NOT be used outside of the record layer. *
* *
*****************************************************************************/
#define MAX_WARN_ALERT_COUNT 5
/* Functions/macros provided by the RECORD_LAYER component */
-#define RECORD_LAYER_get_rbuf(rl) (&(rl)->rbuf)
-#define RECORD_LAYER_get_wbuf(rl) ((rl)->wbuf)
#define RECORD_LAYER_get_rrec(rl) ((rl)->rrec)
#define RECORD_LAYER_set_packet(rl, p) ((rl)->packet = (p))
#define RECORD_LAYER_reset_packet_length(rl) ((rl)->packet_length = 0)
#define RECORD_LAYER_get_rstate(rl) ((rl)->rstate)
#define RECORD_LAYER_set_rstate(rl, st) ((rl)->rstate = (st))
#define RECORD_LAYER_get_read_sequence(rl) ((rl)->read_sequence)
#define RECORD_LAYER_get_write_sequence(rl) ((rl)->write_sequence)
#define RECORD_LAYER_get_numrpipes(rl) ((rl)->numrpipes)
#define RECORD_LAYER_set_numrpipes(rl, n) ((rl)->numrpipes = (n))
#define RECORD_LAYER_inc_empty_record_count(rl) ((rl)->empty_record_count++)
#define RECORD_LAYER_reset_empty_record_count(rl) \
((rl)->empty_record_count = 0)
#define RECORD_LAYER_get_empty_record_count(rl) ((rl)->empty_record_count)
#define RECORD_LAYER_is_first_record(rl) ((rl)->is_first_record)
#define RECORD_LAYER_set_first_record(rl) ((rl)->is_first_record = 1)
#define RECORD_LAYER_clear_first_record(rl) ((rl)->is_first_record = 0)
#define DTLS_RECORD_LAYER_get_r_epoch(rl) ((rl)->d->r_epoch)
__owur int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
size_t *readbytes);
DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
unsigned int *is_next_epoch);
int dtls1_process_buffered_records(SSL *s);
int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue);
int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority);
void ssl3_record_sequence_update(unsigned char *seq);
/* Functions provided by the DTLS1_BITMAP component */
int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
/* Macros/functions provided by the SSL3_BUFFER component */
#define SSL3_BUFFER_get_buf(b) ((b)->buf)
#define SSL3_BUFFER_set_buf(b, n) ((b)->buf = (n))
#define SSL3_BUFFER_get_len(b) ((b)->len)
#define SSL3_BUFFER_set_len(b, l) ((b)->len = (l))
#define SSL3_BUFFER_get_left(b) ((b)->left)
#define SSL3_BUFFER_set_left(b, l) ((b)->left = (l))
#define SSL3_BUFFER_sub_left(b, l) ((b)->left -= (l))
#define SSL3_BUFFER_get_offset(b) ((b)->offset)
#define SSL3_BUFFER_set_offset(b, o) ((b)->offset = (o))
#define SSL3_BUFFER_add_offset(b, o) ((b)->offset += (o))
#define SSL3_BUFFER_is_initialised(b) ((b)->buf != NULL)
#define SSL3_BUFFER_set_default_len(b, l) ((b)->default_len = (l))
void SSL3_BUFFER_clear(SSL3_BUFFER *b);
void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, size_t n);
void SSL3_BUFFER_release(SSL3_BUFFER *b);
__owur int ssl3_setup_read_buffer(SSL *s);
__owur int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len);
int ssl3_release_read_buffer(SSL *s);
int ssl3_release_write_buffer(SSL *s);
/* Macros/functions provided by the SSL3_RECORD component */
#define SSL3_RECORD_get_type(r) ((r)->type)
#define SSL3_RECORD_set_type(r, t) ((r)->type = (t))
#define SSL3_RECORD_set_rec_version(r, v) ((r)->rec_version = (v))
#define SSL3_RECORD_get_length(r) ((r)->length)
#define SSL3_RECORD_set_length(r, l) ((r)->length = (l))
#define SSL3_RECORD_add_length(r, l) ((r)->length += (l))
#define SSL3_RECORD_sub_length(r, l) ((r)->length -= (l))
#define SSL3_RECORD_get_data(r) ((r)->data)
#define SSL3_RECORD_set_data(r, d) ((r)->data = (d))
#define SSL3_RECORD_get_input(r) ((r)->input)
#define SSL3_RECORD_set_input(r, i) ((r)->input = (i))
#define SSL3_RECORD_reset_input(r) ((r)->input = (r)->data)
#define SSL3_RECORD_get_seq_num(r) ((r)->seq_num)
#define SSL3_RECORD_get_off(r) ((r)->off)
#define SSL3_RECORD_set_off(r, o) ((r)->off = (o))
#define SSL3_RECORD_add_off(r, o) ((r)->off += (o))
#define SSL3_RECORD_get_epoch(r) ((r)->epoch)
#define SSL3_RECORD_is_sslv2_record(r) \
((r)->rec_version == SSL2_VERSION)
#define SSL3_RECORD_is_read(r) ((r)->read)
#define SSL3_RECORD_set_read(r) ((r)->read = 1)
void SSL3_RECORD_clear(SSL3_RECORD *r, size_t);
void SSL3_RECORD_release(SSL3_RECORD *r, size_t num_recs);
void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num);
int ssl3_get_record(SSL *s);
__owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr);
__owur int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr);
int ssl3_cbc_copy_mac(unsigned char *out,
const SSL3_RECORD *rec, size_t md_size);
__owur int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
size_t block_size, size_t mac_size);
__owur int tls1_cbc_remove_padding(const SSL *s,
SSL3_RECORD *rec,
size_t block_size, size_t mac_size);
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
__owur int dtls1_get_record(SSL *s);
int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send);
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index a616bf040932..e59ac5a67676 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -1,2032 +1,2057 @@
/*
* Copyright 1995-2018 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 "../ssl_locl.h"
#include "internal/constant_time_locl.h"
#include <openssl/rand.h>
#include "record_locl.h"
#include "internal/cryptlib.h"
static const unsigned char ssl3_pad_1[48] = {
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
};
static const unsigned char ssl3_pad_2[48] = {
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
};
/*
* Clear the contents of an SSL3_RECORD but retain any memory allocated
*/
void SSL3_RECORD_clear(SSL3_RECORD *r, size_t num_recs)
{
unsigned char *comp;
size_t i;
for (i = 0; i < num_recs; i++) {
comp = r[i].comp;
memset(&r[i], 0, sizeof(*r));
r[i].comp = comp;
}
}
void SSL3_RECORD_release(SSL3_RECORD *r, size_t num_recs)
{
size_t i;
for (i = 0; i < num_recs; i++) {
OPENSSL_free(r[i].comp);
r[i].comp = NULL;
}
}
void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num)
{
memcpy(r->seq_num, seq_num, SEQ_NUM_SIZE);
}
/*
* Peeks ahead into "read_ahead" data to see if we have a whole record waiting
* for us in the buffer.
*/
static int ssl3_record_app_data_waiting(SSL *s)
{
SSL3_BUFFER *rbuf;
size_t left, len;
unsigned char *p;
rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
p = SSL3_BUFFER_get_buf(rbuf);
if (p == NULL)
return 0;
left = SSL3_BUFFER_get_left(rbuf);
if (left < SSL3_RT_HEADER_LENGTH)
return 0;
p += SSL3_BUFFER_get_offset(rbuf);
/*
* We only check the type and record length, we will sanity check version
* etc later
*/
if (*p != SSL3_RT_APPLICATION_DATA)
return 0;
p += 3;
n2s(p, len);
if (left < SSL3_RT_HEADER_LENGTH + len)
return 0;
return 1;
}
int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
{
uint32_t max_early_data;
SSL_SESSION *sess = s->session;
/*
* If we are a client then we always use the max_early_data from the
* session/psksession. Otherwise we go with the lowest out of the max early
* data set in the session and the configured max_early_data.
*/
if (!s->server && sess->ext.max_early_data == 0) {
if (!ossl_assert(s->psksession != NULL
&& s->psksession->ext.max_early_data > 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_EARLY_DATA_COUNT_OK,
ERR_R_INTERNAL_ERROR);
return 0;
}
sess = s->psksession;
}
if (!s->server)
max_early_data = sess->ext.max_early_data;
else if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
max_early_data = s->recv_max_early_data;
else
max_early_data = s->recv_max_early_data < sess->ext.max_early_data
? s->recv_max_early_data : sess->ext.max_early_data;
if (max_early_data == 0) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
return 0;
}
/* If we are dealing with ciphertext we need to allow for the overhead */
max_early_data += overhead;
if (s->early_data_count + length > max_early_data) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
return 0;
}
s->early_data_count += length;
return 1;
}
/*
* MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
* will be processed per call to ssl3_get_record. Without this limit an
* attacker could send empty records at a faster rate than we can process and
* cause ssl3_get_record to loop forever.
*/
#define MAX_EMPTY_RECORDS 32
#define SSL2_RT_HEADER_LENGTH 2
/*-
* Call this to get new input records.
* It will return <= 0 if more data is needed, normally due to an error
* or non-blocking IO.
* When it finishes, |numrpipes| records have been decoded. For each record 'i':
* rr[i].type - is the type of record
* rr[i].data, - data
* rr[i].length, - number of bytes
* Multiple records will only be returned if the record types are all
* SSL3_RT_APPLICATION_DATA. The number of records returned will always be <=
* |max_pipelines|
*/
/* used only by ssl3_read_bytes */
int ssl3_get_record(SSL *s)
{
int enc_err, rret;
int i;
size_t more, n;
SSL3_RECORD *rr, *thisrr;
SSL3_BUFFER *rbuf;
SSL_SESSION *sess;
unsigned char *p;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int version;
size_t mac_size;
int imac_size;
size_t num_recs = 0, max_recs, j;
PACKET pkt, sslv2pkt;
size_t first_rec_len;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
max_recs = s->max_pipelines;
if (max_recs == 0)
max_recs = 1;
sess = s->session;
do {
thisrr = &rr[num_recs];
/* check if we have the header */
if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
(RECORD_LAYER_get_packet_length(&s->rlayer)
< SSL3_RT_HEADER_LENGTH)) {
size_t sslv2len;
unsigned int type;
rret = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH,
SSL3_BUFFER_get_len(rbuf), 0,
num_recs == 0 ? 1 : 0, &n);
if (rret <= 0)
return rret; /* error or non-blocking */
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
p = RECORD_LAYER_get_packet(&s->rlayer);
if (!PACKET_buf_init(&pkt, RECORD_LAYER_get_packet(&s->rlayer),
RECORD_LAYER_get_packet_length(&s->rlayer))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
ERR_R_INTERNAL_ERROR);
return -1;
}
sslv2pkt = pkt;
if (!PACKET_get_net_2_len(&sslv2pkt, &sslv2len)
|| !PACKET_get_1(&sslv2pkt, &type)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
ERR_R_INTERNAL_ERROR);
return -1;
}
/*
* The first record received by the server may be a V2ClientHello.
*/
if (s->server && RECORD_LAYER_is_first_record(&s->rlayer)
&& (sslv2len & 0x8000) != 0
&& (type == SSL2_MT_CLIENT_HELLO)) {
/*
* SSLv2 style record
*
* |num_recs| here will actually always be 0 because
* |num_recs > 0| only ever occurs when we are processing
* multiple app data records - which we know isn't the case here
* because it is an SSLv2ClientHello. We keep it using
* |num_recs| for the sake of consistency
*/
thisrr->type = SSL3_RT_HANDSHAKE;
thisrr->rec_version = SSL2_VERSION;
thisrr->length = sslv2len & 0x7fff;
if (thisrr->length > SSL3_BUFFER_get_len(rbuf)
- SSL2_RT_HEADER_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_PACKET_LENGTH_TOO_LONG);
return -1;
}
if (thisrr->length < MIN_SSL2_RECORD_LEN) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
SSL_R_LENGTH_TOO_SHORT);
return -1;
}
} else {
/* SSLv3+ style record */
if (s->msg_callback)
s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
s->msg_callback_arg);
/* Pull apart the header into the SSL3_RECORD */
if (!PACKET_get_1(&pkt, &type)
|| !PACKET_get_net_2(&pkt, &version)
|| !PACKET_get_net_2_len(&pkt, &thisrr->length)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
ERR_R_INTERNAL_ERROR);
return -1;
}
thisrr->type = type;
thisrr->rec_version = version;
/*
* Lets check version. In TLSv1.3 we only check this field
* when encryption is occurring (see later check). For the
* ServerHello after an HRR we haven't actually selected TLSv1.3
* yet, but we still treat it as TLSv1.3, so we must check for
* that explicitly
*/
if (!s->first_packet && !SSL_IS_TLS13(s)
&& s->hello_retry_request != SSL_HRR_PENDING
&& version != (unsigned int)s->version) {
if ((s->version & 0xFF00) == (version & 0xFF00)
&& !s->enc_write_ctx && !s->write_hash) {
if (thisrr->type == SSL3_RT_ALERT) {
/*
* The record is using an incorrect version number,
* but what we've got appears to be an alert. We
* haven't read the body yet to check whether its a
* fatal or not - but chances are it is. We probably
* shouldn't send a fatal alert back. We'll just
* end.
*/
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
/*
* Send back error using their minor version number :-)
*/
s->version = (unsigned short)version;
}
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL3_GET_RECORD,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
if ((version >> 8) != SSL3_VERSION_MAJOR) {
if (RECORD_LAYER_is_first_record(&s->rlayer)) {
/* Go back to start of packet, look at the five bytes
* that we have. */
p = RECORD_LAYER_get_packet(&s->rlayer);
if (strncmp((char *)p, "GET ", 4) == 0 ||
strncmp((char *)p, "POST ", 5) == 0 ||
strncmp((char *)p, "HEAD ", 5) == 0 ||
strncmp((char *)p, "PUT ", 4) == 0) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
SSL_R_HTTP_REQUEST);
return -1;
} else if (strncmp((char *)p, "CONNE", 5) == 0) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
SSL_R_HTTPS_PROXY_REQUEST);
return -1;
}
/* Doesn't look like TLS - don't send an alert */
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
} else {
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_F_SSL3_GET_RECORD,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
}
if (SSL_IS_TLS13(s) && s->enc_read_ctx != NULL) {
if (thisrr->type != SSL3_RT_APPLICATION_DATA
&& (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC
|| !SSL_IS_FIRST_HANDSHAKE(s))
&& (thisrr->type != SSL3_RT_ALERT
|| s->statem.enc_read_state
!= ENC_READ_STATE_ALLOW_PLAIN_ALERTS)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_SSL3_GET_RECORD, SSL_R_BAD_RECORD_TYPE);
return -1;
}
if (thisrr->rec_version != TLS1_2_VERSION) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
}
if (thisrr->length >
SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_PACKET_LENGTH_TOO_LONG);
return -1;
}
}
/* now s->rlayer.rstate == SSL_ST_READ_BODY */
}
if (SSL_IS_TLS13(s)) {
if (thisrr->length > SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
}
} else {
size_t len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
#ifndef OPENSSL_NO_COMP
/*
* If OPENSSL_NO_COMP is defined then SSL3_RT_MAX_ENCRYPTED_LENGTH
* does not include the compression overhead anyway.
*/
if (s->expand == NULL)
len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
if (thisrr->length > len) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
}
}
/*
* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data.
* Calculate how much more data we need to read for the rest of the
* record
*/
if (thisrr->rec_version == SSL2_VERSION) {
more = thisrr->length + SSL2_RT_HEADER_LENGTH
- SSL3_RT_HEADER_LENGTH;
} else {
more = thisrr->length;
}
if (more > 0) {
/* now s->packet_length == SSL3_RT_HEADER_LENGTH */
rret = ssl3_read_n(s, more, more, 1, 0, &n);
if (rret <= 0)
return rret; /* error or non-blocking io */
}
/* set state for later operations */
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
/*
* At this point, s->packet_length == SSL3_RT_HEADER_LENGTH
* + thisrr->length, or s->packet_length == SSL2_RT_HEADER_LENGTH
* + thisrr->length and we have that many bytes in s->packet
*/
if (thisrr->rec_version == SSL2_VERSION) {
thisrr->input =
&(RECORD_LAYER_get_packet(&s->rlayer)[SSL2_RT_HEADER_LENGTH]);
} else {
thisrr->input =
&(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]);
}
/*
* ok, we can now read from 's->packet' data into 'thisrr' thisrr->input
* points at thisrr->length bytes, which need to be copied into
* thisrr->data by either the decryption or by the decompression When
* the data is 'copied' into the thisrr->data buffer, thisrr->input will
* be pointed at the new buffer
*/
/*
* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
* thisrr->length bytes of encrypted compressed stuff.
*/
/* decrypt in place in 'thisrr->input' */
thisrr->data = thisrr->input;
thisrr->orig_len = thisrr->length;
/* Mark this record as not read by upper layers yet */
thisrr->read = 0;
num_recs++;
/* we have pulled in a full packet so zero things */
RECORD_LAYER_reset_packet_length(&s->rlayer);
RECORD_LAYER_clear_first_record(&s->rlayer);
} while (num_recs < max_recs
&& thisrr->type == SSL3_RT_APPLICATION_DATA
&& SSL_USE_EXPLICIT_IV(s)
&& s->enc_read_ctx != NULL
&& (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx))
& EVP_CIPH_FLAG_PIPELINE)
&& ssl3_record_app_data_waiting(s));
if (num_recs == 1
&& thisrr->type == SSL3_RT_CHANGE_CIPHER_SPEC
&& (SSL_IS_TLS13(s) || s->hello_retry_request != SSL_HRR_NONE)
&& SSL_IS_FIRST_HANDSHAKE(s)) {
/*
* CCS messages must be exactly 1 byte long, containing the value 0x01
*/
if (thisrr->length != 1 || thisrr->data[0] != 0x01) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL3_GET_RECORD,
SSL_R_INVALID_CCS_MESSAGE);
return -1;
}
/*
* CCS messages are ignored in TLSv1.3. We treat it like an empty
* handshake record
*/
thisrr->type = SSL3_RT_HANDSHAKE;
RECORD_LAYER_inc_empty_record_count(&s->rlayer);
if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
> MAX_EMPTY_RECORDS) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
SSL_R_UNEXPECTED_CCS_MESSAGE);
return -1;
}
thisrr->read = 1;
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
return 1;
}
/*
* If in encrypt-then-mac mode calculate mac from encrypted record. All
* the details below are public so no timing details can leak.
*/
if (SSL_READ_ETM(s) && s->read_hash) {
unsigned char *mac;
/* TODO(size_t): convert this to do size_t properly */
imac_size = EVP_MD_CTX_size(s->read_hash);
if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
ERR_LIB_EVP);
return -1;
}
mac_size = (size_t)imac_size;
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
if (thisrr->length < mac_size) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
SSL_R_LENGTH_TOO_SHORT);
return -1;
}
thisrr->length -= mac_size;
mac = thisrr->data + thisrr->length;
i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ );
if (i == 0 || CRYPTO_memcmp(md, mac, mac_size) != 0) {
SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return -1;
}
}
}
first_rec_len = rr[0].length;
enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0);
/*-
* enc_err is:
* 0: (in non-constant time) if the record is publicly invalid.
* 1: if the padding is valid
* -1: if the padding is invalid
*/
if (enc_err == 0) {
if (ossl_statem_in_error(s)) {
/* SSLfatal() already got called */
return -1;
}
if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
/*
* Valid early_data that we cannot decrypt might fail here as
* publicly invalid. We treat it like an empty record.
*/
thisrr = &rr[0];
if (!early_data_count_ok(s, thisrr->length,
EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) {
/* SSLfatal() already called */
return -1;
}
thisrr->length = 0;
thisrr->read = 1;
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
RECORD_LAYER_reset_read_sequence(&s->rlayer);
return 1;
}
SSLfatal(s, SSL_AD_DECRYPTION_FAILED, SSL_F_SSL3_GET_RECORD,
SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
return -1;
}
#ifdef SSL_DEBUG
printf("dec %lu\n", (unsigned long)rr[0].length);
{
size_t z;
for (z = 0; z < rr[0].length; z++)
printf("%02X%c", rr[0].data[z], ((z + 1) % 16) ? ' ' : '\n');
}
printf("\n");
#endif
/* r->length is now the compressed data plus mac */
if ((sess != NULL) &&
(s->enc_read_ctx != NULL) &&
(!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)) {
/* s->read_hash != NULL => mac_size != -1 */
unsigned char *mac = NULL;
unsigned char mac_tmp[EVP_MAX_MD_SIZE];
mac_size = EVP_MD_CTX_size(s->read_hash);
if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
ERR_R_INTERNAL_ERROR);
return -1;
}
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
/*
* orig_len is the length of the record before any padding was
* removed. This is public information, as is the MAC in use,
* therefore we can safely process the record in a different amount
* of time if it's too short to possibly contain a MAC.
*/
if (thisrr->orig_len < mac_size ||
/* CBC records must have a padding length byte too. */
(EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
thisrr->orig_len < mac_size + 1)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
SSL_R_LENGTH_TOO_SHORT);
return -1;
}
if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
/*
* We update the length so that the TLS header bytes can be
* constructed correctly but we need to extract the MAC in
* constant time from within the record, without leaking the
* contents of the padding bytes.
*/
mac = mac_tmp;
if (!ssl3_cbc_copy_mac(mac_tmp, thisrr, mac_size)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
ERR_R_INTERNAL_ERROR);
return -1;
}
thisrr->length -= mac_size;
} else {
/*
* In this case there's no padding, so |rec->orig_len| equals
* |rec->length| and we checked that there's enough bytes for
* |mac_size| above.
*/
thisrr->length -= mac_size;
mac = &thisrr->data[thisrr->length];
}
i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ );
if (i == 0 || mac == NULL
|| CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
enc_err = -1;
if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
enc_err = -1;
}
}
if (enc_err < 0) {
if (ossl_statem_in_error(s)) {
/* We already called SSLfatal() */
return -1;
}
if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
/*
* We assume this is unreadable early_data - we treat it like an
* empty record
*/
/*
* The record length may have been modified by the mac check above
* so we use the previously saved value
*/
if (!early_data_count_ok(s, first_rec_len,
EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) {
/* SSLfatal() already called */
return -1;
}
thisrr = &rr[0];
thisrr->length = 0;
thisrr->read = 1;
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
RECORD_LAYER_reset_read_sequence(&s->rlayer);
return 1;
}
/*
* A separate 'decryption_failed' alert was introduced with TLS 1.0,
* SSL 3.0 only has 'bad_record_mac'. But unless a decryption
* failure is directly visible from the ciphertext anyway, we should
* not reveal which kind of error occurred -- this might become
* visible to an attacker (e.g. via a logfile)
*/
SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return -1;
}
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
/* thisrr->length is now just compressed */
if (s->expand != NULL) {
if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
return -1;
}
if (!ssl3_do_uncompress(s, thisrr)) {
SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_F_SSL3_GET_RECORD,
SSL_R_BAD_DECOMPRESSION);
return -1;
}
}
if (SSL_IS_TLS13(s)
&& s->enc_read_ctx != NULL
&& thisrr->type != SSL3_RT_ALERT) {
size_t end;
if (thisrr->length == 0
|| thisrr->type != SSL3_RT_APPLICATION_DATA) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
SSL_R_BAD_RECORD_TYPE);
return -1;
}
/* Strip trailing padding */
for (end = thisrr->length - 1; end > 0 && thisrr->data[end] == 0;
end--)
continue;
thisrr->length = end;
thisrr->type = thisrr->data[end];
if (thisrr->type != SSL3_RT_APPLICATION_DATA
&& thisrr->type != SSL3_RT_ALERT
&& thisrr->type != SSL3_RT_HANDSHAKE) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
SSL_R_BAD_RECORD_TYPE);
return -1;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_INNER_CONTENT_TYPE,
&thisrr->data[end], 1, s, s->msg_callback_arg);
}
/*
* TLSv1.3 alert and handshake records are required to be non-zero in
* length.
*/
if (SSL_IS_TLS13(s)
&& (thisrr->type == SSL3_RT_HANDSHAKE
|| thisrr->type == SSL3_RT_ALERT)
&& thisrr->length == 0) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
SSL_R_BAD_LENGTH);
return -1;
}
if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_DATA_LENGTH_TOO_LONG);
return -1;
}
/* If received packet overflows current Max Fragment Length setting */
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& thisrr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_DATA_LENGTH_TOO_LONG);
return -1;
}
thisrr->off = 0;
/*-
* So at this point the following is true
* thisrr->type is the type of record
* thisrr->length == number of bytes in record
* thisrr->off == offset to first valid byte
* thisrr->data == where to take bytes from, increment after use :-).
*/
/* just read a 0 length packet */
if (thisrr->length == 0) {
RECORD_LAYER_inc_empty_record_count(&s->rlayer);
if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
> MAX_EMPTY_RECORDS) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
SSL_R_RECORD_TOO_SMALL);
return -1;
}
} else {
RECORD_LAYER_reset_empty_record_count(&s->rlayer);
}
}
if (s->early_data_state == SSL_EARLY_DATA_READING) {
thisrr = &rr[0];
if (thisrr->type == SSL3_RT_APPLICATION_DATA
&& !early_data_count_ok(s, thisrr->length, 0, 0)) {
/* SSLfatal already called */
return -1;
}
}
RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs);
return 1;
}
int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr)
{
#ifndef OPENSSL_NO_COMP
int i;
if (rr->comp == NULL) {
rr->comp = (unsigned char *)
OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
}
if (rr->comp == NULL)
return 0;
/* TODO(size_t): Convert this call */
i = COMP_expand_block(ssl->expand, rr->comp,
SSL3_RT_MAX_PLAIN_LENGTH, rr->data, (int)rr->length);
if (i < 0)
return 0;
else
rr->length = i;
rr->data = rr->comp;
#endif
return 1;
}
int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr)
{
#ifndef OPENSSL_NO_COMP
int i;
/* TODO(size_t): Convert this call */
i = COMP_compress_block(ssl->compress, wr->data,
(int)(wr->length + SSL3_RT_MAX_COMPRESSED_OVERHEAD),
wr->input, (int)wr->length);
if (i < 0)
return 0;
else
wr->length = i;
wr->input = wr->data;
#endif
return 1;
}
/*-
* ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|. Will call
* SSLfatal() for internal errors, but not otherwise.
*
* Returns:
* 0: (in non-constant time) if the record is publically invalid (i.e. too
* short etc).
* 1: if the record's padding is valid / the encryption was successful.
* -1: if the record's padding is invalid or, if sending, an internal error
* occurred.
*/
int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending)
{
SSL3_RECORD *rec;
EVP_CIPHER_CTX *ds;
size_t l, i;
size_t bs, mac_size = 0;
int imac_size;
const EVP_CIPHER *enc;
rec = inrecs;
/*
* We shouldn't ever be called with more than one record in the SSLv3 case
*/
if (n_recs != 1)
return 0;
if (sending) {
ds = s->enc_write_ctx;
if (s->enc_write_ctx == NULL)
enc = NULL;
else
enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
} else {
ds = s->enc_read_ctx;
if (s->enc_read_ctx == NULL)
enc = NULL;
else
enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
memmove(rec->data, rec->input, rec->length);
rec->input = rec->data;
} else {
l = rec->length;
/* TODO(size_t): Convert this call */
bs = EVP_CIPHER_CTX_block_size(ds);
/* COMPRESS */
if ((bs != 1) && sending) {
i = bs - (l % bs);
/* we need to add 'i-1' padding bytes */
l += i;
/*
* the last of these zero bytes will be overwritten with the
* padding length.
*/
memset(&rec->input[rec->length], 0, i);
rec->length += i;
rec->input[l - 1] = (unsigned char)(i - 1);
}
if (!sending) {
if (l == 0 || l % bs != 0)
return 0;
/* otherwise, rec->length >= bs */
}
/* TODO(size_t): Convert this call */
if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1)
return -1;
if (EVP_MD_CTX_md(s->read_hash) != NULL) {
/* TODO(size_t): convert me */
imac_size = EVP_MD_CTX_size(s->read_hash);
if (imac_size < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
}
mac_size = (size_t)imac_size;
}
if ((bs != 1) && !sending)
return ssl3_cbc_remove_padding(rec, bs, mac_size);
}
return 1;
}
#define MAX_PADDING 256
/*-
* tls1_enc encrypts/decrypts |n_recs| in |recs|. Will call SSLfatal() for
* internal errors, but not otherwise.
*
* Returns:
* 0: (in non-constant time) if the record is publically invalid (i.e. too
* short etc).
* 1: if the record's padding is valid / the encryption was successful.
* -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
* an internal error occurred.
*/
int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
{
EVP_CIPHER_CTX *ds;
size_t reclen[SSL_MAX_PIPELINES];
unsigned char buf[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN];
int i, pad = 0, ret, tmpr;
size_t bs, mac_size = 0, ctr, padnum, loop;
unsigned char padval;
int imac_size;
const EVP_CIPHER *enc;
if (n_recs == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (sending) {
if (EVP_MD_CTX_md(s->write_hash)) {
int n = EVP_MD_CTX_size(s->write_hash);
if (!ossl_assert(n >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
}
}
ds = s->enc_write_ctx;
if (s->enc_write_ctx == NULL)
enc = NULL;
else {
int ivlen;
enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
/* For TLSv1.1 and later explicit IV */
if (SSL_USE_EXPLICIT_IV(s)
&& EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
ivlen = EVP_CIPHER_iv_length(enc);
else
ivlen = 0;
if (ivlen > 1) {
for (ctr = 0; ctr < n_recs; ctr++) {
if (recs[ctr].data != recs[ctr].input) {
/*
* we can't write into the input stream: Can this ever
* happen?? (steve)
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
} else if (RAND_bytes(recs[ctr].input, ivlen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
}
}
}
}
} else {
if (EVP_MD_CTX_md(s->read_hash)) {
int n = EVP_MD_CTX_size(s->read_hash);
if (!ossl_assert(n >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
}
}
ds = s->enc_read_ctx;
if (s->enc_read_ctx == NULL)
enc = NULL;
else
enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
for (ctr = 0; ctr < n_recs; ctr++) {
memmove(recs[ctr].data, recs[ctr].input, recs[ctr].length);
recs[ctr].input = recs[ctr].data;
}
ret = 1;
} else {
bs = EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(ds));
if (n_recs > 1) {
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
& EVP_CIPH_FLAG_PIPELINE)) {
/*
* We shouldn't have been called with pipeline data if the
* cipher doesn't support pipelining
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
SSL_R_PIPELINE_FAILURE);
return -1;
}
}
for (ctr = 0; ctr < n_recs; ctr++) {
reclen[ctr] = recs[ctr].length;
if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
& EVP_CIPH_FLAG_AEAD_CIPHER) {
unsigned char *seq;
seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
: RECORD_LAYER_get_read_sequence(&s->rlayer);
if (SSL_IS_DTLS(s)) {
/* DTLS does not support pipelining */
unsigned char dtlsseq[9], *p = dtlsseq;
s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) :
DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p);
memcpy(p, &seq[2], 6);
memcpy(buf[ctr], dtlsseq, 8);
} else {
memcpy(buf[ctr], seq, 8);
for (i = 7; i >= 0; i--) { /* increment */
++seq[i];
if (seq[i] != 0)
break;
}
}
buf[ctr][8] = recs[ctr].type;
buf[ctr][9] = (unsigned char)(s->version >> 8);
buf[ctr][10] = (unsigned char)(s->version);
buf[ctr][11] = (unsigned char)(recs[ctr].length >> 8);
buf[ctr][12] = (unsigned char)(recs[ctr].length & 0xff);
pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
EVP_AEAD_TLS1_AAD_LEN, buf[ctr]);
if (pad <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
}
if (sending) {
reclen[ctr] += pad;
recs[ctr].length += pad;
}
} else if ((bs != 1) && sending) {
padnum = bs - (reclen[ctr] % bs);
/* Add weird padding of upto 256 bytes */
if (padnum > MAX_PADDING) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
}
/* we need to add 'padnum' padding bytes of value padval */
padval = (unsigned char)(padnum - 1);
for (loop = reclen[ctr]; loop < reclen[ctr] + padnum; loop++)
recs[ctr].input[loop] = padval;
reclen[ctr] += padnum;
recs[ctr].length += padnum;
}
if (!sending) {
if (reclen[ctr] == 0 || reclen[ctr] % bs != 0)
return 0;
}
}
if (n_recs > 1) {
unsigned char *data[SSL_MAX_PIPELINES];
/* Set the output buffers */
for (ctr = 0; ctr < n_recs; ctr++) {
data[ctr] = recs[ctr].data;
}
if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS,
(int)n_recs, data) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
SSL_R_PIPELINE_FAILURE);
return -1;
}
/* Set the input buffers */
for (ctr = 0; ctr < n_recs; ctr++) {
data[ctr] = recs[ctr].input;
}
if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_BUFS,
(int)n_recs, data) <= 0
|| EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS,
(int)n_recs, reclen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
SSL_R_PIPELINE_FAILURE);
return -1;
}
}
/* TODO(size_t): Convert this call */
tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input,
(unsigned int)reclen[0]);
if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
& EVP_CIPH_FLAG_CUSTOM_CIPHER)
? (tmpr < 0)
: (tmpr == 0))
return -1; /* AEAD can fail to verify MAC */
if (sending == 0) {
if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) {
for (ctr = 0; ctr < n_recs; ctr++) {
recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
}
} else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) {
for (ctr = 0; ctr < n_recs; ctr++) {
recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
}
}
}
ret = 1;
if (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL) {
imac_size = EVP_MD_CTX_size(s->read_hash);
if (imac_size < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
}
mac_size = (size_t)imac_size;
}
if ((bs != 1) && !sending) {
int tmpret;
for (ctr = 0; ctr < n_recs; ctr++) {
tmpret = tls1_cbc_remove_padding(s, &recs[ctr], bs, mac_size);
/*
* If tmpret == 0 then this means publicly invalid so we can
* short circuit things here. Otherwise we must respect constant
* time behaviour.
*/
if (tmpret == 0)
return 0;
ret = constant_time_select_int(constant_time_eq_int(tmpret, 1),
ret, -1);
}
}
if (pad && !sending) {
for (ctr = 0; ctr < n_recs; ctr++) {
recs[ctr].length -= pad;
}
}
}
return ret;
}
int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
{
unsigned char *mac_sec, *seq;
const EVP_MD_CTX *hash;
unsigned char *p, rec_char;
size_t md_size;
size_t npad;
int t;
if (sending) {
mac_sec = &(ssl->s3->write_mac_secret[0]);
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
hash = ssl->write_hash;
} else {
mac_sec = &(ssl->s3->read_mac_secret[0]);
seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
hash = ssl->read_hash;
}
t = EVP_MD_CTX_size(hash);
if (t < 0)
return 0;
md_size = t;
npad = (48 / md_size) * md_size;
if (!sending &&
EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
ssl3_cbc_record_digest_supported(hash)) {
/*
* This is a CBC-encrypted record. We must avoid leaking any
* timing-side channel information about how many blocks of data we
* are hashing because that gives an attacker a timing-oracle.
*/
/*-
* npad is, at most, 48 bytes and that's with MD5:
* 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75.
*
* With SHA-1 (the largest hash speced for SSLv3) the hash size
* goes up 4, but npad goes down by 8, resulting in a smaller
* total size.
*/
unsigned char header[75];
size_t j = 0;
memcpy(header + j, mac_sec, md_size);
j += md_size;
memcpy(header + j, ssl3_pad_1, npad);
j += npad;
memcpy(header + j, seq, 8);
j += 8;
header[j++] = rec->type;
header[j++] = (unsigned char)(rec->length >> 8);
header[j++] = (unsigned char)(rec->length & 0xff);
/* Final param == is SSLv3 */
if (ssl3_cbc_digest_record(hash,
md, &md_size,
header, rec->input,
rec->length + md_size, rec->orig_len,
mac_sec, md_size, 1) <= 0)
return 0;
} else {
unsigned int md_size_u;
/* Chop the digest off the end :-) */
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL)
return 0;
rec_char = rec->type;
p = md;
s2n(rec->length, p);
if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
|| EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
|| EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0
|| EVP_DigestUpdate(md_ctx, seq, 8) <= 0
|| EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0
|| EVP_DigestUpdate(md_ctx, md, 2) <= 0
|| EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0
|| EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0
|| EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
|| EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
|| EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0
|| EVP_DigestUpdate(md_ctx, md, md_size) <= 0
|| EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) {
EVP_MD_CTX_free(md_ctx);
return 0;
}
EVP_MD_CTX_free(md_ctx);
}
ssl3_record_sequence_update(seq);
return 1;
}
int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
{
unsigned char *seq;
EVP_MD_CTX *hash;
size_t md_size;
int i;
EVP_MD_CTX *hmac = NULL, *mac_ctx;
unsigned char header[13];
int stream_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
: (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
int t;
if (sending) {
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
hash = ssl->write_hash;
} else {
seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
hash = ssl->read_hash;
}
t = EVP_MD_CTX_size(hash);
if (!ossl_assert(t >= 0))
return 0;
md_size = t;
/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
if (stream_mac) {
mac_ctx = hash;
} else {
hmac = EVP_MD_CTX_new();
if (hmac == NULL || !EVP_MD_CTX_copy(hmac, hash)) {
EVP_MD_CTX_free(hmac);
return 0;
}
mac_ctx = hmac;
}
if (SSL_IS_DTLS(ssl)) {
unsigned char dtlsseq[8], *p = dtlsseq;
s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&ssl->rlayer) :
DTLS_RECORD_LAYER_get_r_epoch(&ssl->rlayer), p);
memcpy(p, &seq[2], 6);
memcpy(header, dtlsseq, 8);
} else
memcpy(header, seq, 8);
header[8] = rec->type;
header[9] = (unsigned char)(ssl->version >> 8);
header[10] = (unsigned char)(ssl->version);
header[11] = (unsigned char)(rec->length >> 8);
header[12] = (unsigned char)(rec->length & 0xff);
if (!sending && !SSL_READ_ETM(ssl) &&
EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
ssl3_cbc_record_digest_supported(mac_ctx)) {
/*
* This is a CBC-encrypted record. We must avoid leaking any
* timing-side channel information about how many blocks of data we
* are hashing because that gives an attacker a timing-oracle.
*/
/* Final param == not SSLv3 */
if (ssl3_cbc_digest_record(mac_ctx,
md, &md_size,
header, rec->input,
rec->length + md_size, rec->orig_len,
ssl->s3->read_mac_secret,
ssl->s3->read_mac_secret_size, 0) <= 0) {
EVP_MD_CTX_free(hmac);
return 0;
}
} else {
/* TODO(size_t): Convert these calls */
if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
|| EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
|| EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
EVP_MD_CTX_free(hmac);
return 0;
}
}
EVP_MD_CTX_free(hmac);
#ifdef SSL_DEBUG
fprintf(stderr, "seq=");
{
int z;
for (z = 0; z < 8; z++)
fprintf(stderr, "%02X ", seq[z]);
fprintf(stderr, "\n");
}
fprintf(stderr, "rec=");
{
size_t z;
for (z = 0; z < rec->length; z++)
fprintf(stderr, "%02X ", rec->data[z]);
fprintf(stderr, "\n");
}
#endif
if (!SSL_IS_DTLS(ssl)) {
for (i = 7; i >= 0; i--) {
++seq[i];
if (seq[i] != 0)
break;
}
}
#ifdef SSL_DEBUG
{
unsigned int z;
for (z = 0; z < md_size; z++)
fprintf(stderr, "%02X ", md[z]);
fprintf(stderr, "\n");
}
#endif
return 1;
}
/*-
* ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
* record in |rec| by updating |rec->length| in constant time.
*
* block_size: the block size of the cipher used to encrypt the record.
* returns:
* 0: (in non-constant time) if the record is publicly invalid.
* 1: if the padding was valid
* -1: otherwise.
*/
int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
size_t block_size, size_t mac_size)
{
size_t padding_length;
size_t good;
const size_t overhead = 1 /* padding length byte */ + mac_size;
/*
* These lengths are all public so we can test them in non-constant time.
*/
if (overhead > rec->length)
return 0;
padding_length = rec->data[rec->length - 1];
good = constant_time_ge_s(rec->length, padding_length + overhead);
/* SSLv3 requires that the padding is minimal. */
good &= constant_time_ge_s(block_size, padding_length + 1);
rec->length -= good & (padding_length + 1);
return constant_time_select_int_s(good, 1, -1);
}
/*-
* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
* record in |rec| in constant time and returns 1 if the padding is valid and
* -1 otherwise. It also removes any explicit IV from the start of the record
* without leaking any timing about whether there was enough space after the
* padding was removed.
*
* block_size: the block size of the cipher used to encrypt the record.
* returns:
* 0: (in non-constant time) if the record is publicly invalid.
* 1: if the padding was valid
* -1: otherwise.
*/
int tls1_cbc_remove_padding(const SSL *s,
SSL3_RECORD *rec,
size_t block_size, size_t mac_size)
{
size_t good;
size_t padding_length, to_check, i;
const size_t overhead = 1 /* padding length byte */ + mac_size;
/* Check if version requires explicit IV */
if (SSL_USE_EXPLICIT_IV(s)) {
/*
* These lengths are all public so we can test them in non-constant
* time.
*/
if (overhead + block_size > rec->length)
return 0;
/* We can now safely skip explicit IV */
rec->data += block_size;
rec->input += block_size;
rec->length -= block_size;
rec->orig_len -= block_size;
} else if (overhead > rec->length)
return 0;
padding_length = rec->data[rec->length - 1];
if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) &
EVP_CIPH_FLAG_AEAD_CIPHER) {
/* padding is already verified */
rec->length -= padding_length + 1;
return 1;
}
good = constant_time_ge_s(rec->length, overhead + padding_length);
/*
* The padding consists of a length byte at the end of the record and
* then that many bytes of padding, all with the same value as the length
* byte. Thus, with the length byte included, there are i+1 bytes of
* padding. We can't check just |padding_length+1| bytes because that
* leaks decrypted information. Therefore we always have to check the
* maximum amount of padding possible. (Again, the length of the record
* is public information so we can use it.)
*/
to_check = 256; /* maximum amount of padding, inc length byte. */
if (to_check > rec->length)
to_check = rec->length;
for (i = 0; i < to_check; i++) {
unsigned char mask = constant_time_ge_8_s(padding_length, i);
unsigned char b = rec->data[rec->length - 1 - i];
/*
* The final |padding_length+1| bytes should all have the value
* |padding_length|. Therefore the XOR should be zero.
*/
good &= ~(mask & (padding_length ^ b));
}
/*
* If any of the final |padding_length+1| bytes had the wrong value, one
* or more of the lower eight bits of |good| will be cleared.
*/
good = constant_time_eq_s(0xff, good & 0xff);
rec->length -= good & (padding_length + 1);
return constant_time_select_int_s(good, 1, -1);
}
/*-
* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
* constant time (independent of the concrete value of rec->length, which may
* vary within a 256-byte window).
*
* ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to
* this function.
*
* On entry:
* rec->orig_len >= md_size
* md_size <= EVP_MAX_MD_SIZE
*
* If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
* variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
* a single or pair of cache-lines, then the variable memory accesses don't
* actually affect the timing. CPUs with smaller cache-lines [if any] are
* not multi-core and are not considered vulnerable to cache-timing attacks.
*/
#define CBC_MAC_ROTATE_IN_PLACE
int ssl3_cbc_copy_mac(unsigned char *out,
const SSL3_RECORD *rec, size_t md_size)
{
#if defined(CBC_MAC_ROTATE_IN_PLACE)
unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
unsigned char *rotated_mac;
#else
unsigned char rotated_mac[EVP_MAX_MD_SIZE];
#endif
/*
* mac_end is the index of |rec->data| just after the end of the MAC.
*/
size_t mac_end = rec->length;
size_t mac_start = mac_end - md_size;
size_t in_mac;
/*
* scan_start contains the number of bytes that we can ignore because the
* MAC's position can only vary by 255 bytes.
*/
size_t scan_start = 0;
size_t i, j;
size_t rotate_offset;
if (!ossl_assert(rec->orig_len >= md_size
&& md_size <= EVP_MAX_MD_SIZE))
return 0;
#if defined(CBC_MAC_ROTATE_IN_PLACE)
rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
#endif
/* This information is public so it's safe to branch based on it. */
if (rec->orig_len > md_size + 255 + 1)
scan_start = rec->orig_len - (md_size + 255 + 1);
in_mac = 0;
rotate_offset = 0;
memset(rotated_mac, 0, md_size);
for (i = scan_start, j = 0; i < rec->orig_len; i++) {
size_t mac_started = constant_time_eq_s(i, mac_start);
size_t mac_ended = constant_time_lt_s(i, mac_end);
unsigned char b = rec->data[i];
in_mac |= mac_started;
in_mac &= mac_ended;
rotate_offset |= j & mac_started;
rotated_mac[j++] |= b & in_mac;
j &= constant_time_lt_s(j, md_size);
}
/* Now rotate the MAC */
#if defined(CBC_MAC_ROTATE_IN_PLACE)
j = 0;
for (i = 0; i < md_size; i++) {
/* in case cache-line is 32 bytes, touch second line */
((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32];
out[j++] = rotated_mac[rotate_offset++];
rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
}
#else
memset(out, 0, md_size);
rotate_offset = md_size - rotate_offset;
rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
for (i = 0; i < md_size; i++) {
for (j = 0; j < md_size; j++)
out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset);
rotate_offset++;
rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
}
#endif
return 1;
}
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
{
int i;
int enc_err;
SSL_SESSION *sess;
SSL3_RECORD *rr;
int imac_size;
size_t mac_size;
unsigned char md[EVP_MAX_MD_SIZE];
rr = RECORD_LAYER_get_rrec(&s->rlayer);
sess = s->session;
/*
* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
* and we have that many bytes in s->packet
*/
rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[DTLS1_RT_HEADER_LENGTH]);
/*
* ok, we can now read from 's->packet' data into 'rr' rr->input points
* at rr->length bytes, which need to be copied into rr->data by either
* the decryption or by the decompression When the data is 'copied' into
* the rr->data buffer, rr->input will be pointed at the new buffer
*/
/*
* We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
* bytes of encrypted compressed stuff.
*/
/* check is not needed I believe */
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return 0;
}
/* decrypt in place in 'rr->input' */
rr->data = rr->input;
rr->orig_len = rr->length;
if (SSL_READ_ETM(s) && s->read_hash) {
unsigned char *mac;
mac_size = EVP_MD_CTX_size(s->read_hash);
if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (rr->orig_len < mac_size) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
SSL_R_LENGTH_TOO_SHORT);
return 0;
}
rr->length -= mac_size;
mac = rr->data + rr->length;
i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_DTLS1_PROCESS_RECORD,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return 0;
}
}
enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0);
/*-
* enc_err is:
* 0: (in non-constant time) if the record is publically invalid.
* 1: if the padding is valid
* -1: if the padding is invalid
*/
if (enc_err == 0) {
if (ossl_statem_in_error(s)) {
/* SSLfatal() got called */
return 0;
}
/* For DTLS we simply ignore bad packets. */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
return 0;
}
#ifdef SSL_DEBUG
printf("dec %ld\n", rr->length);
{
size_t z;
for (z = 0; z < rr->length; z++)
printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
}
printf("\n");
#endif
/* r->length is now the compressed data plus mac */
if ((sess != NULL) && !SSL_READ_ETM(s) &&
(s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(s->read_hash) != NULL)) {
/* s->read_hash != NULL => mac_size != -1 */
unsigned char *mac = NULL;
unsigned char mac_tmp[EVP_MAX_MD_SIZE];
/* TODO(size_t): Convert this to do size_t properly */
imac_size = EVP_MD_CTX_size(s->read_hash);
if (imac_size < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
ERR_LIB_EVP);
return 0;
}
mac_size = (size_t)imac_size;
if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* orig_len is the length of the record before any padding was
* removed. This is public information, as is the MAC in use,
* therefore we can safely process the record in a different amount
* of time if it's too short to possibly contain a MAC.
*/
if (rr->orig_len < mac_size ||
/* CBC records must have a padding length byte too. */
(EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
rr->orig_len < mac_size + 1)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
SSL_R_LENGTH_TOO_SHORT);
return 0;
}
if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
/*
* We update the length so that the TLS header bytes can be
* constructed correctly but we need to extract the MAC in
* constant time from within the record, without leaking the
* contents of the padding bytes.
*/
mac = mac_tmp;
if (!ssl3_cbc_copy_mac(mac_tmp, rr, mac_size)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
ERR_R_INTERNAL_ERROR);
return 0;
}
rr->length -= mac_size;
} else {
/*
* In this case there's no padding, so |rec->orig_len| equals
* |rec->length| and we checked that there's enough bytes for
* |mac_size| above.
*/
rr->length -= mac_size;
mac = &rr->data[rr->length];
}
i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
if (i == 0 || mac == NULL
|| CRYPTO_memcmp(md, mac, mac_size) != 0)
enc_err = -1;
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
enc_err = -1;
}
if (enc_err < 0) {
/* decryption failed, silently discard message */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
return 0;
}
/* r->length is now just compressed */
if (s->expand != NULL) {
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
return 0;
}
if (!ssl3_do_uncompress(s, rr)) {
SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE,
SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION);
return 0;
}
}
if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD,
SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
rr->off = 0;
/*-
* So at this point the following is true
* ssl->s3->rrec.type is the type of record
* ssl->s3->rrec.length == number of bytes in record
* ssl->s3->rrec.off == offset to first valid byte
* ssl->s3->rrec.data == where to take bytes from, increment
* after use :-).
*/
/* we have pulled in a full packet so zero things */
RECORD_LAYER_reset_packet_length(&s->rlayer);
/* Mark receipt of record. */
dtls1_record_bitmap_update(s, bitmap);
return 1;
}
/*
* Retrieve a buffered record that belongs to the current epoch, i.e. processed
*/
#define dtls1_get_processed_record(s) \
dtls1_retrieve_buffered_record((s), \
&(DTLS_RECORD_LAYER_get_processed_rcds(&s->rlayer)))
/*-
* Call this to get a new input record.
* It will return <= 0 if more data is needed, normally due to an error
* or non-blocking IO.
* When it finishes, one packet has been decoded and can be found in
* ssl->s3->rrec.type - is the type of record
* ssl->s3->rrec.data, - data
* ssl->s3->rrec.length, - number of bytes
*/
/* used only by dtls1_read_bytes */
int dtls1_get_record(SSL *s)
{
int ssl_major, ssl_minor;
int rret;
size_t more, n;
SSL3_RECORD *rr;
unsigned char *p = NULL;
unsigned short version;
DTLS1_BITMAP *bitmap;
unsigned int is_next_epoch;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
again:
/*
* The epoch may have changed. If so, process all the pending records.
* This is a non-blocking operation.
*/
if (!dtls1_process_buffered_records(s)) {
/* SSLfatal() already called */
return -1;
}
/* if we're renegotiating, then there may be buffered records */
if (dtls1_get_processed_record(s))
return 1;
/* get something from the wire */
/* check if we have the header */
if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
(RECORD_LAYER_get_packet_length(&s->rlayer) < DTLS1_RT_HEADER_LENGTH)) {
rret = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH,
SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0, 1, &n);
/* read timeout is handled by dtls1_read_bytes */
if (rret <= 0) {
/* SSLfatal() already called if appropriate */
return rret; /* error or non-blocking */
}
/* this packet contained a partial record, dump it */
if (RECORD_LAYER_get_packet_length(&s->rlayer) !=
DTLS1_RT_HEADER_LENGTH) {
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
p = RECORD_LAYER_get_packet(&s->rlayer);
if (s->msg_callback)
s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
s, s->msg_callback_arg);
/* Pull apart the header into the DTLS1_RECORD */
rr->type = *(p++);
ssl_major = *(p++);
ssl_minor = *(p++);
version = (ssl_major << 8) | ssl_minor;
/* sequence number is 64 bits, with top 2 bytes = epoch */
n2s(p, rr->epoch);
memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
p += 6;
n2s(p, rr->length);
rr->read = 0;
/*
* Lets check the version. We tolerate alerts that don't have the exact
* version number (e.g. because of protocol version errors)
*/
if (!s->first_packet && rr->type != SSL3_RT_ALERT) {
if (version != s->version) {
/* unexpected version, silently discard */
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
}
if ((version & 0xff00) != (s->version & 0xff00)) {
/* wrong version, silently discard record */
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
/* record too long, silently discard it */
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
/* If received packet overflows own-client Max Fragment Length setting */
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& rr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) {
/* record too long, silently discard it */
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
/* now s->rlayer.rstate == SSL_ST_READ_BODY */
}
/* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
if (rr->length >
RECORD_LAYER_get_packet_length(&s->rlayer) - DTLS1_RT_HEADER_LENGTH) {
/* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
more = rr->length;
rret = ssl3_read_n(s, more, more, 1, 1, &n);
/* this packet contained a partial record, dump it */
if (rret <= 0 || n != more) {
if (ossl_statem_in_error(s)) {
/* ssl3_read_n() called SSLfatal() */
return -1;
}
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
/*
* now n == rr->length, and s->packet_length ==
* DTLS1_RT_HEADER_LENGTH + rr->length
*/
}
/* set state for later operations */
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
/* match epochs. NULL means the packet is dropped on the floor */
bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
if (bitmap == NULL) {
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
goto again; /* get another record */
}
#ifndef OPENSSL_NO_SCTP
/* Only do replay check if no SCTP bio */
if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
#endif
/* Check whether this is a repeat, or aged record. */
/*
* TODO: Does it make sense to have replay protection in epoch 0 where
* we have no integrity negotiated yet?
*/
if (!dtls1_record_replay_check(s, bitmap)) {
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
goto again; /* get another record */
}
#ifndef OPENSSL_NO_SCTP
}
#endif
/* just read a 0 length packet */
if (rr->length == 0) {
rr->read = 1;
goto again;
}
/*
* If this record is from the next epoch (either HM or ALERT), and a
* handshake is currently in progress, buffer it since it cannot be
* processed at this time.
*/
if (is_next_epoch) {
if ((SSL_in_init(s) || ossl_statem_get_in_handshake(s))) {
if (dtls1_buffer_record (s,
&(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)),
rr->seq_num) < 0) {
/* SSLfatal() already called */
return -1;
}
}
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
if (!dtls1_process_record(s, bitmap)) {
if (ossl_statem_in_error(s)) {
/* dtls1_process_record() called SSLfatal */
return -1;
}
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
goto again; /* get another record */
}
return 1;
}
+
+int dtls_buffer_listen_record(SSL *s, size_t len, unsigned char *seq, size_t off)
+{
+ SSL3_RECORD *rr;
+
+ rr = RECORD_LAYER_get_rrec(&s->rlayer);
+ memset(rr, 0, sizeof(SSL3_RECORD));
+
+ rr->length = len;
+ rr->type = SSL3_RT_HANDSHAKE;
+ memcpy(rr->seq_num, seq, sizeof(rr->seq_num));
+ rr->off = off;
+
+ s->rlayer.packet = RECORD_LAYER_get_rbuf(&s->rlayer)->buf;
+ s->rlayer.packet_length = DTLS1_RT_HEADER_LENGTH + len;
+ rr->data = s->rlayer.packet + DTLS1_RT_HEADER_LENGTH;
+
+ if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
+ SSL3_RECORD_get_seq_num(s->rlayer.rrec)) <= 0) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c
index 7d9c3776973d..8377d7fe13dc 100644
--- a/ssl/s3_cbc.c
+++ b/ssl/s3_cbc.c
@@ -1,486 +1,487 @@
/*
- * Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2018 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 "ssl_locl.h"
#include "internal/cryptlib.h"
#include <openssl/md5.h>
#include <openssl/sha.h>
/*
* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's
* length field. (SHA-384/512 have 128-bit length.)
*/
#define MAX_HASH_BIT_COUNT_BYTES 16
/*
* MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support.
* Currently SHA-384/512 has a 128-byte block size and that's the largest
* supported by TLS.)
*/
#define MAX_HASH_BLOCK_SIZE 128
/*
* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
* little-endian order. The value of p is advanced by four.
*/
#define u32toLE(n, p) \
(*((p)++)=(unsigned char)(n), \
*((p)++)=(unsigned char)(n>>8), \
*((p)++)=(unsigned char)(n>>16), \
*((p)++)=(unsigned char)(n>>24))
/*
* These functions serialize the state of a hash and thus perform the
* standard "final" operation without adding the padding and length that such
* a function typically does.
*/
static void tls1_md5_final_raw(void *ctx, unsigned char *md_out)
{
MD5_CTX *md5 = ctx;
u32toLE(md5->A, md_out);
u32toLE(md5->B, md_out);
u32toLE(md5->C, md_out);
u32toLE(md5->D, md_out);
}
static void tls1_sha1_final_raw(void *ctx, unsigned char *md_out)
{
SHA_CTX *sha1 = ctx;
l2n(sha1->h0, md_out);
l2n(sha1->h1, md_out);
l2n(sha1->h2, md_out);
l2n(sha1->h3, md_out);
l2n(sha1->h4, md_out);
}
static void tls1_sha256_final_raw(void *ctx, unsigned char *md_out)
{
SHA256_CTX *sha256 = ctx;
unsigned i;
for (i = 0; i < 8; i++) {
l2n(sha256->h[i], md_out);
}
}
static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out)
{
SHA512_CTX *sha512 = ctx;
unsigned i;
for (i = 0; i < 8; i++) {
l2n8(sha512->h[i], md_out);
}
}
#undef LARGEST_DIGEST_CTX
#define LARGEST_DIGEST_CTX SHA512_CTX
/*
* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
* which ssl3_cbc_digest_record supports.
*/
char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
{
switch (EVP_MD_CTX_type(ctx)) {
case NID_md5:
case NID_sha1:
case NID_sha224:
case NID_sha256:
case NID_sha384:
case NID_sha512:
return 1;
default:
return 0;
}
}
/*-
* ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS
* record.
*
* ctx: the EVP_MD_CTX from which we take the hash function.
* ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX.
* md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written.
* md_out_size: if non-NULL, the number of output bytes is written here.
* header: the 13-byte, TLS record header.
* data: the record data itself, less any preceding explicit IV.
* data_plus_mac_size: the secret, reported length of the data and MAC
* once the padding has been removed.
* data_plus_mac_plus_padding_size: the public length of the whole
* record, including padding.
* is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS.
*
* On entry: by virtue of having been through one of the remove_padding
* functions, above, we know that data_plus_mac_size is large enough to contain
* a padding byte and MAC. (If the padding was invalid, it might contain the
* padding too. )
* Returns 1 on success or 0 on error
*/
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)
{
union {
double align;
unsigned char c[sizeof(LARGEST_DIGEST_CTX)];
} md_state;
void (*md_final_raw) (void *ctx, unsigned char *md_out);
void (*md_transform) (void *ctx, const unsigned char *block);
size_t md_size, md_block_size = 64;
size_t sslv3_pad_length = 40, header_length, variance_blocks,
len, max_mac_bytes, num_blocks,
num_starting_blocks, k, mac_end_offset, c, index_a, index_b;
size_t bits; /* at most 18 bits */
unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
/* hmac_pad is the masked HMAC key. */
unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
unsigned char first_block[MAX_HASH_BLOCK_SIZE];
unsigned char mac_out[EVP_MAX_MD_SIZE];
size_t i, j;
unsigned md_out_size_u;
EVP_MD_CTX *md_ctx = NULL;
/*
* mdLengthSize is the number of bytes in the length field that
* terminates * the hash.
*/
size_t md_length_size = 8;
char length_is_big_endian = 1;
int ret;
/*
* This is a, hopefully redundant, check that allows us to forget about
* many possible overflows later in this function.
*/
if (!ossl_assert(data_plus_mac_plus_padding_size < 1024 * 1024))
return 0;
switch (EVP_MD_CTX_type(ctx)) {
case NID_md5:
if (MD5_Init((MD5_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_md5_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))MD5_Transform;
md_size = 16;
sslv3_pad_length = 48;
length_is_big_endian = 0;
break;
case NID_sha1:
if (SHA1_Init((SHA_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha1_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA1_Transform;
md_size = 20;
break;
case NID_sha224:
if (SHA224_Init((SHA256_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha256_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
md_size = 224 / 8;
break;
case NID_sha256:
if (SHA256_Init((SHA256_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha256_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
md_size = 32;
break;
case NID_sha384:
if (SHA384_Init((SHA512_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha512_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA512_Transform;
md_size = 384 / 8;
md_block_size = 128;
md_length_size = 16;
break;
case NID_sha512:
if (SHA512_Init((SHA512_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha512_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA512_Transform;
md_size = 64;
md_block_size = 128;
md_length_size = 16;
break;
default:
/*
* ssl3_cbc_record_digest_supported should have been called first to
* check that the hash function is supported.
*/
if (md_out_size != NULL)
*md_out_size = 0;
return ossl_assert(0);
}
if (!ossl_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES)
|| !ossl_assert(md_block_size <= MAX_HASH_BLOCK_SIZE)
|| !ossl_assert(md_size <= EVP_MAX_MD_SIZE))
return 0;
header_length = 13;
if (is_sslv3) {
header_length = mac_secret_length + sslv3_pad_length + 8 /* sequence
* number */ +
1 /* record type */ +
2 /* record length */ ;
}
/*
* variance_blocks is the number of blocks of the hash that we have to
* calculate in constant time because they could be altered by the
* padding value. In SSLv3, the padding must be minimal so the end of
* the plaintext varies by, at most, 15+20 = 35 bytes. (We conservatively
* assume that the MAC size varies from 0..20 bytes.) In case the 9 bytes
* of hash termination (0x80 + 64-bit length) don't fit in the final
* block, we say that the final two blocks can vary based on the padding.
* TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
- * required to be minimal. Therefore we say that the final six blocks can
+ * required to be minimal. Therefore we say that the final |variance_blocks|
+ * blocks can
* vary based on the padding. Later in the function, if the message is
* short and there obviously cannot be this many blocks then
* variance_blocks can be reduced.
*/
- variance_blocks = is_sslv3 ? 2 : 6;
+ variance_blocks = is_sslv3 ? 2 : ( ((255 + 1 + md_size + md_block_size - 1) / md_block_size) + 1);
/*
* From now on we're dealing with the MAC, which conceptually has 13
* bytes of `header' before the start of the data (TLS) or 71/75 bytes
* (SSLv3)
*/
len = data_plus_mac_plus_padding_size + header_length;
/*
* max_mac_bytes contains the maximum bytes of bytes in the MAC,
* including * |header|, assuming that there's no padding.
*/
max_mac_bytes = len - md_size - 1;
/* num_blocks is the maximum number of hash blocks. */
num_blocks =
(max_mac_bytes + 1 + md_length_size + md_block_size -
1) / md_block_size;
/*
* In order to calculate the MAC in constant time we have to handle the
* final blocks specially because the padding value could cause the end
* to appear somewhere in the final |variance_blocks| blocks and we can't
* leak where. However, |num_starting_blocks| worth of data can be hashed
* right away because no padding value can affect whether they are
* plaintext.
*/
num_starting_blocks = 0;
/*
* k is the starting byte offset into the conceptual header||data where
* we start processing.
*/
k = 0;
/*
* mac_end_offset is the index just past the end of the data to be MACed.
*/
mac_end_offset = data_plus_mac_size + header_length - md_size;
/*
* c is the index of the 0x80 byte in the final hash block that contains
* application data.
*/
c = mac_end_offset % md_block_size;
/*
* index_a is the hash block number that contains the 0x80 terminating
* value.
*/
index_a = mac_end_offset / md_block_size;
/*
* index_b is the hash block number that contains the 64-bit hash length,
* in bits.
*/
index_b = (mac_end_offset + md_length_size) / md_block_size;
/*
* bits is the hash-length in bits. It includes the additional hash block
* for the masked HMAC key, or whole of |header| in the case of SSLv3.
*/
/*
* For SSLv3, if we're going to have any starting blocks then we need at
* least two because the header is larger than a single block.
*/
if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) {
num_starting_blocks = num_blocks - variance_blocks;
k = md_block_size * num_starting_blocks;
}
bits = 8 * mac_end_offset;
if (!is_sslv3) {
/*
* Compute the initial HMAC block. For SSLv3, the padding and secret
* bytes are included in |header| because they take more than a
* single block.
*/
bits += 8 * md_block_size;
memset(hmac_pad, 0, md_block_size);
if (!ossl_assert(mac_secret_length <= sizeof(hmac_pad)))
return 0;
memcpy(hmac_pad, mac_secret, mac_secret_length);
for (i = 0; i < md_block_size; i++)
hmac_pad[i] ^= 0x36;
md_transform(md_state.c, hmac_pad);
}
if (length_is_big_endian) {
memset(length_bytes, 0, md_length_size - 4);
length_bytes[md_length_size - 4] = (unsigned char)(bits >> 24);
length_bytes[md_length_size - 3] = (unsigned char)(bits >> 16);
length_bytes[md_length_size - 2] = (unsigned char)(bits >> 8);
length_bytes[md_length_size - 1] = (unsigned char)bits;
} else {
memset(length_bytes, 0, md_length_size);
length_bytes[md_length_size - 5] = (unsigned char)(bits >> 24);
length_bytes[md_length_size - 6] = (unsigned char)(bits >> 16);
length_bytes[md_length_size - 7] = (unsigned char)(bits >> 8);
length_bytes[md_length_size - 8] = (unsigned char)bits;
}
if (k > 0) {
if (is_sslv3) {
size_t overhang;
/*
* The SSLv3 header is larger than a single block. overhang is
* the number of bytes beyond a single block that the header
* consumes: either 7 bytes (SHA1) or 11 bytes (MD5). There are no
* ciphersuites in SSLv3 that are not SHA1 or MD5 based and
* therefore we can be confident that the header_length will be
* greater than |md_block_size|. However we add a sanity check just
* in case
*/
if (header_length <= md_block_size) {
/* Should never happen */
return 0;
}
overhang = header_length - md_block_size;
md_transform(md_state.c, header);
memcpy(first_block, header + md_block_size, overhang);
memcpy(first_block + overhang, data, md_block_size - overhang);
md_transform(md_state.c, first_block);
for (i = 1; i < k / md_block_size - 1; i++)
md_transform(md_state.c, data + md_block_size * i - overhang);
} else {
/* k is a multiple of md_block_size. */
memcpy(first_block, header, 13);
memcpy(first_block + 13, data, md_block_size - 13);
md_transform(md_state.c, first_block);
for (i = 1; i < k / md_block_size; i++)
md_transform(md_state.c, data + md_block_size * i - 13);
}
}
memset(mac_out, 0, sizeof(mac_out));
/*
* We now process the final hash blocks. For each block, we construct it
* in constant time. If the |i==index_a| then we'll include the 0x80
* bytes and zero pad etc. For each block we selectively copy it, in
* constant time, to |mac_out|.
*/
for (i = num_starting_blocks; i <= num_starting_blocks + variance_blocks;
i++) {
unsigned char block[MAX_HASH_BLOCK_SIZE];
unsigned char is_block_a = constant_time_eq_8_s(i, index_a);
unsigned char is_block_b = constant_time_eq_8_s(i, index_b);
for (j = 0; j < md_block_size; j++) {
unsigned char b = 0, is_past_c, is_past_cp1;
if (k < header_length)
b = header[k];
else if (k < data_plus_mac_plus_padding_size + header_length)
b = data[k - header_length];
k++;
is_past_c = is_block_a & constant_time_ge_8_s(j, c);
is_past_cp1 = is_block_a & constant_time_ge_8_s(j, c + 1);
/*
* If this is the block containing the end of the application
* data, and we are at the offset for the 0x80 value, then
* overwrite b with 0x80.
*/
b = constant_time_select_8(is_past_c, 0x80, b);
/*
* If this block contains the end of the application data
* and we're past the 0x80 value then just write zero.
*/
b = b & ~is_past_cp1;
/*
* If this is index_b (the final block), but not index_a (the end
* of the data), then the 64-bit length didn't fit into index_a
* and we're having to add an extra block of zeros.
*/
b &= ~is_block_b | is_block_a;
/*
* The final bytes of one of the blocks contains the length.
*/
if (j >= md_block_size - md_length_size) {
/* If this is index_b, write a length byte. */
b = constant_time_select_8(is_block_b,
length_bytes[j -
(md_block_size -
md_length_size)], b);
}
block[j] = b;
}
md_transform(md_state.c, block);
md_final_raw(md_state.c, block);
/* If this is index_b, copy the hash value to |mac_out|. */
for (j = 0; j < md_size; j++)
mac_out[j] |= block[j] & is_block_b;
}
md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL)
goto err;
if (EVP_DigestInit_ex(md_ctx, EVP_MD_CTX_md(ctx), NULL /* engine */ ) <= 0)
goto err;
if (is_sslv3) {
/* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
memset(hmac_pad, 0x5c, sslv3_pad_length);
if (EVP_DigestUpdate(md_ctx, mac_secret, mac_secret_length) <= 0
|| EVP_DigestUpdate(md_ctx, hmac_pad, sslv3_pad_length) <= 0
|| EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0)
goto err;
} else {
/* Complete the HMAC in the standard manner. */
for (i = 0; i < md_block_size; i++)
hmac_pad[i] ^= 0x6a;
if (EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size) <= 0
|| EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0)
goto err;
}
/* TODO(size_t): Convert me */
ret = EVP_DigestFinal(md_ctx, md_out, &md_out_size_u);
if (ret && md_out_size)
*md_out_size = md_out_size_u;
EVP_MD_CTX_free(md_ctx);
return 1;
err:
EVP_MD_CTX_free(md_ctx);
return 0;
}
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 5f403817b4d5..fca84ef99acf 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -1,599 +1,601 @@
/*
* Copyright 1995-2018 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 <stdio.h>
#include "ssl_locl.h"
#include <openssl/evp.h>
#include <openssl/md5.h>
#include "internal/cryptlib.h"
static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
{
EVP_MD_CTX *m5;
EVP_MD_CTX *s1;
unsigned char buf[16], smd[SHA_DIGEST_LENGTH];
unsigned char c = 'A';
unsigned int i, j, k;
int ret = 0;
#ifdef CHARSET_EBCDIC
c = os_toascii[c]; /* 'A' in ASCII */
#endif
k = 0;
m5 = EVP_MD_CTX_new();
s1 = EVP_MD_CTX_new();
if (m5 == NULL || s1 == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
ERR_R_MALLOC_FAILURE);
goto err;
}
EVP_MD_CTX_set_flags(m5, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
for (i = 0; (int)i < num; i += MD5_DIGEST_LENGTH) {
k++;
if (k > sizeof(buf)) {
/* bug: 'buf' is too small for this ciphersuite */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
ERR_R_INTERNAL_ERROR);
goto err;
}
for (j = 0; j < k; j++)
buf[j] = c;
c++;
if (!EVP_DigestInit_ex(s1, EVP_sha1(), NULL)
|| !EVP_DigestUpdate(s1, buf, k)
|| !EVP_DigestUpdate(s1, s->session->master_key,
s->session->master_key_length)
|| !EVP_DigestUpdate(s1, s->s3->server_random, SSL3_RANDOM_SIZE)
|| !EVP_DigestUpdate(s1, s->s3->client_random, SSL3_RANDOM_SIZE)
|| !EVP_DigestFinal_ex(s1, smd, NULL)
|| !EVP_DigestInit_ex(m5, EVP_md5(), NULL)
|| !EVP_DigestUpdate(m5, s->session->master_key,
s->session->master_key_length)
|| !EVP_DigestUpdate(m5, smd, SHA_DIGEST_LENGTH)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
ERR_R_INTERNAL_ERROR);
goto err;
}
if ((int)(i + MD5_DIGEST_LENGTH) > num) {
if (!EVP_DigestFinal_ex(m5, smd, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(km, smd, (num - i));
} else {
if (!EVP_DigestFinal_ex(m5, km, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
goto err;
}
}
km += MD5_DIGEST_LENGTH;
}
OPENSSL_cleanse(smd, sizeof(smd));
ret = 1;
err:
EVP_MD_CTX_free(m5);
EVP_MD_CTX_free(s1);
return ret;
}
int ssl3_change_cipher_state(SSL *s, int which)
{
unsigned char *p, *mac_secret;
unsigned char exp_key[EVP_MAX_KEY_LENGTH];
unsigned char exp_iv[EVP_MAX_IV_LENGTH];
unsigned char *ms, *key, *iv;
EVP_CIPHER_CTX *dd;
const EVP_CIPHER *c;
#ifndef OPENSSL_NO_COMP
COMP_METHOD *comp;
#endif
const EVP_MD *m;
int mdi;
size_t n, i, j, k, cl;
int reuse_dd = 0;
c = s->s3->tmp.new_sym_enc;
m = s->s3->tmp.new_hash;
/* m == NULL will lead to a crash later */
if (!ossl_assert(m != NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
#ifndef OPENSSL_NO_COMP
if (s->s3->tmp.new_compression == NULL)
comp = NULL;
else
comp = s->s3->tmp.new_compression->method;
#endif
if (which & SSL3_CC_READ) {
if (s->enc_read_ctx != NULL) {
reuse_dd = 1;
} else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
ERR_R_MALLOC_FAILURE);
goto err;
} else {
/*
* make sure it's initialised in case we exit later with an error
*/
EVP_CIPHER_CTX_reset(s->enc_read_ctx);
}
dd = s->enc_read_ctx;
if (ssl_replace_hash(&s->read_hash, m) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
#ifndef OPENSSL_NO_COMP
/* COMPRESS */
COMP_CTX_free(s->expand);
s->expand = NULL;
if (comp != NULL) {
s->expand = COMP_CTX_new(comp);
if (s->expand == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_SSL3_CHANGE_CIPHER_STATE,
SSL_R_COMPRESSION_LIBRARY_ERROR);
goto err;
}
}
#endif
RECORD_LAYER_reset_read_sequence(&s->rlayer);
mac_secret = &(s->s3->read_mac_secret[0]);
} else {
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
if (s->enc_write_ctx != NULL) {
reuse_dd = 1;
} else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
ERR_R_MALLOC_FAILURE);
goto err;
} else {
/*
* make sure it's initialised in case we exit later with an error
*/
EVP_CIPHER_CTX_reset(s->enc_write_ctx);
}
dd = s->enc_write_ctx;
if (ssl_replace_hash(&s->write_hash, m) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
ERR_R_MALLOC_FAILURE);
goto err;
}
#ifndef OPENSSL_NO_COMP
/* COMPRESS */
COMP_CTX_free(s->compress);
s->compress = NULL;
if (comp != NULL) {
s->compress = COMP_CTX_new(comp);
if (s->compress == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_SSL3_CHANGE_CIPHER_STATE,
SSL_R_COMPRESSION_LIBRARY_ERROR);
goto err;
}
}
#endif
RECORD_LAYER_reset_write_sequence(&s->rlayer);
mac_secret = &(s->s3->write_mac_secret[0]);
}
if (reuse_dd)
EVP_CIPHER_CTX_reset(dd);
p = s->s3->tmp.key_block;
mdi = EVP_MD_size(m);
if (mdi < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
i = mdi;
cl = EVP_CIPHER_key_length(c);
j = cl;
k = EVP_CIPHER_iv_length(c);
if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
(which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
ms = &(p[0]);
n = i + i;
key = &(p[n]);
n += j + j;
iv = &(p[n]);
n += k + k;
} else {
n = i;
ms = &(p[n]);
n += i + j;
key = &(p[n]);
n += j + k;
iv = &(p[n]);
n += k;
}
if (n > s->s3->tmp.key_block_length) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(mac_secret, ms, i);
if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
OPENSSL_cleanse(exp_key, sizeof(exp_key));
OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
return 1;
err:
OPENSSL_cleanse(exp_key, sizeof(exp_key));
OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
return 0;
}
int ssl3_setup_key_block(SSL *s)
{
unsigned char *p;
const EVP_CIPHER *c;
const EVP_MD *hash;
int num;
int ret = 0;
SSL_COMP *comp;
if (s->s3->tmp.key_block_length != 0)
return 1;
if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, &comp, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK,
SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
return 0;
}
s->s3->tmp.new_sym_enc = c;
s->s3->tmp.new_hash = hash;
#ifdef OPENSSL_NO_COMP
s->s3->tmp.new_compression = NULL;
#else
s->s3->tmp.new_compression = comp;
#endif
num = EVP_MD_size(hash);
if (num < 0)
return 0;
num = EVP_CIPHER_key_length(c) + num + EVP_CIPHER_iv_length(c);
num *= 2;
ssl3_cleanup_key_block(s);
if ((p = OPENSSL_malloc(num)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK,
ERR_R_MALLOC_FAILURE);
return 0;
}
s->s3->tmp.key_block_length = num;
s->s3->tmp.key_block = p;
/* Calls SSLfatal() as required */
ret = ssl3_generate_key_block(s, p, num);
if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) {
/*
* enable vulnerability countermeasure for CBC ciphers with known-IV
* problem (http://www.openssl.org/~bodo/tls-cbc.txt)
*/
s->s3->need_empty_fragments = 1;
if (s->session->cipher != NULL) {
if (s->session->cipher->algorithm_enc == SSL_eNULL)
s->s3->need_empty_fragments = 0;
#ifndef OPENSSL_NO_RC4
if (s->session->cipher->algorithm_enc == SSL_RC4)
s->s3->need_empty_fragments = 0;
#endif
}
}
return ret;
}
void ssl3_cleanup_key_block(SSL *s)
{
OPENSSL_clear_free(s->s3->tmp.key_block, s->s3->tmp.key_block_length);
s->s3->tmp.key_block = NULL;
s->s3->tmp.key_block_length = 0;
}
int ssl3_init_finished_mac(SSL *s)
{
BIO *buf = BIO_new(BIO_s_mem());
if (buf == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_INIT_FINISHED_MAC,
ERR_R_MALLOC_FAILURE);
return 0;
}
ssl3_free_digest_list(s);
s->s3->handshake_buffer = buf;
(void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE);
return 1;
}
/*
* Free digest list. Also frees handshake buffer since they are always freed
* together.
*/
void ssl3_free_digest_list(SSL *s)
{
BIO_free(s->s3->handshake_buffer);
s->s3->handshake_buffer = NULL;
EVP_MD_CTX_free(s->s3->handshake_dgst);
s->s3->handshake_dgst = NULL;
}
int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len)
{
int ret;
if (s->s3->handshake_dgst == NULL) {
/* Note: this writes to a memory BIO so a failure is a fatal error */
if (len > INT_MAX) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
SSL_R_OVERFLOW_ERROR);
return 0;
}
ret = BIO_write(s->s3->handshake_buffer, (void *)buf, (int)len);
if (ret <= 0 || ret != (int)len) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
ret = EVP_DigestUpdate(s->s3->handshake_dgst, buf, len);
if (!ret) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
int ssl3_digest_cached_records(SSL *s, int keep)
{
const EVP_MD *md;
long hdatalen;
void *hdata;
if (s->s3->handshake_dgst == NULL) {
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
if (hdatalen <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
SSL_R_BAD_HANDSHAKE_LENGTH);
return 0;
}
s->s3->handshake_dgst = EVP_MD_CTX_new();
if (s->s3->handshake_dgst == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
ERR_R_MALLOC_FAILURE);
return 0;
}
md = ssl_handshake_md(s);
if (md == NULL || !EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL)
|| !EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (keep == 0) {
BIO_free(s->s3->handshake_buffer);
s->s3->handshake_buffer = NULL;
}
return 1;
}
size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
unsigned char *p)
{
int ret;
EVP_MD_CTX *ctx = NULL;
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
return 0;
}
if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
SSL_R_NO_REQUIRED_DIGEST);
return 0;
}
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
ERR_R_MALLOC_FAILURE);
return 0;
}
if (!EVP_MD_CTX_copy_ex(ctx, s->s3->handshake_dgst)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
ERR_R_INTERNAL_ERROR);
- return 0;
+ ret = 0;
+ goto err;
}
ret = EVP_MD_CTX_size(ctx);
if (ret < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
ERR_R_INTERNAL_ERROR);
- EVP_MD_CTX_reset(ctx);
- return 0;
+ ret = 0;
+ goto err;
}
if ((sender != NULL && EVP_DigestUpdate(ctx, sender, len) <= 0)
|| EVP_MD_CTX_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET,
(int)s->session->master_key_length,
s->session->master_key) <= 0
|| EVP_DigestFinal_ex(ctx, p, NULL) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
ERR_R_INTERNAL_ERROR);
ret = 0;
}
+ err:
EVP_MD_CTX_free(ctx);
return ret;
}
int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
size_t len, size_t *secret_size)
{
static const unsigned char *salt[3] = {
#ifndef CHARSET_EBCDIC
(const unsigned char *)"A",
(const unsigned char *)"BB",
(const unsigned char *)"CCC",
#else
(const unsigned char *)"\x41",
(const unsigned char *)"\x42\x42",
(const unsigned char *)"\x43\x43\x43",
#endif
};
unsigned char buf[EVP_MAX_MD_SIZE];
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
int i, ret = 1;
unsigned int n;
size_t ret_secret_size = 0;
if (ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_MASTER_SECRET,
ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < 3; i++) {
if (EVP_DigestInit_ex(ctx, s->ctx->sha1, NULL) <= 0
|| EVP_DigestUpdate(ctx, salt[i],
strlen((const char *)salt[i])) <= 0
|| EVP_DigestUpdate(ctx, p, len) <= 0
|| EVP_DigestUpdate(ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_DigestUpdate(ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
/* TODO(size_t) : convert me */
|| EVP_DigestFinal_ex(ctx, buf, &n) <= 0
|| EVP_DigestInit_ex(ctx, s->ctx->md5, NULL) <= 0
|| EVP_DigestUpdate(ctx, p, len) <= 0
|| EVP_DigestUpdate(ctx, buf, n) <= 0
|| EVP_DigestFinal_ex(ctx, out, &n) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
ret = 0;
break;
}
out += n;
ret_secret_size += n;
}
EVP_MD_CTX_free(ctx);
OPENSSL_cleanse(buf, sizeof(buf));
if (ret)
*secret_size = ret_secret_size;
return ret;
}
int ssl3_alert_code(int code)
{
switch (code) {
case SSL_AD_CLOSE_NOTIFY:
return SSL3_AD_CLOSE_NOTIFY;
case SSL_AD_UNEXPECTED_MESSAGE:
return SSL3_AD_UNEXPECTED_MESSAGE;
case SSL_AD_BAD_RECORD_MAC:
return SSL3_AD_BAD_RECORD_MAC;
case SSL_AD_DECRYPTION_FAILED:
return SSL3_AD_BAD_RECORD_MAC;
case SSL_AD_RECORD_OVERFLOW:
return SSL3_AD_BAD_RECORD_MAC;
case SSL_AD_DECOMPRESSION_FAILURE:
return SSL3_AD_DECOMPRESSION_FAILURE;
case SSL_AD_HANDSHAKE_FAILURE:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_NO_CERTIFICATE:
return SSL3_AD_NO_CERTIFICATE;
case SSL_AD_BAD_CERTIFICATE:
return SSL3_AD_BAD_CERTIFICATE;
case SSL_AD_UNSUPPORTED_CERTIFICATE:
return SSL3_AD_UNSUPPORTED_CERTIFICATE;
case SSL_AD_CERTIFICATE_REVOKED:
return SSL3_AD_CERTIFICATE_REVOKED;
case SSL_AD_CERTIFICATE_EXPIRED:
return SSL3_AD_CERTIFICATE_EXPIRED;
case SSL_AD_CERTIFICATE_UNKNOWN:
return SSL3_AD_CERTIFICATE_UNKNOWN;
case SSL_AD_ILLEGAL_PARAMETER:
return SSL3_AD_ILLEGAL_PARAMETER;
case SSL_AD_UNKNOWN_CA:
return SSL3_AD_BAD_CERTIFICATE;
case SSL_AD_ACCESS_DENIED:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_DECODE_ERROR:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_DECRYPT_ERROR:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_EXPORT_RESTRICTION:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_PROTOCOL_VERSION:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_INSUFFICIENT_SECURITY:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_INTERNAL_ERROR:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_USER_CANCELLED:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_NO_RENEGOTIATION:
return -1; /* Don't send it :-) */
case SSL_AD_UNSUPPORTED_EXTENSION:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_CERTIFICATE_UNOBTAINABLE:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_UNRECOGNIZED_NAME:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
return SSL3_AD_HANDSHAKE_FAILURE;
case SSL_AD_UNKNOWN_PSK_IDENTITY:
return TLS1_AD_UNKNOWN_PSK_IDENTITY;
case SSL_AD_INAPPROPRIATE_FALLBACK:
return TLS1_AD_INAPPROPRIATE_FALLBACK;
case SSL_AD_NO_APPLICATION_PROTOCOL:
return TLS1_AD_NO_APPLICATION_PROTOCOL;
case SSL_AD_CERTIFICATE_REQUIRED:
return SSL_AD_HANDSHAKE_FAILURE;
default:
return -1;
}
}
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 7713f767b2d3..866ca4dfa9b0 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -1,4844 +1,4864 @@
/*
* Copyright 1995-2018 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 <openssl/objects.h>
#include "internal/nelem.h"
#include "ssl_locl.h"
#include <openssl/md5.h>
#include <openssl/dh.h>
#include <openssl/rand.h>
#include "internal/cryptlib.h"
#define TLS13_NUM_CIPHERS OSSL_NELEM(tls13_ciphers)
#define SSL3_NUM_CIPHERS OSSL_NELEM(ssl3_ciphers)
#define SSL3_NUM_SCSVS OSSL_NELEM(ssl3_scsvs)
/* TLSv1.3 downgrade protection sentinel values */
const unsigned char tls11downgrade[] = {
0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x00
};
const unsigned char tls12downgrade[] = {
0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01
};
/* The list of available TLSv1.3 ciphers */
static SSL_CIPHER tls13_ciphers[] = {
{
1,
TLS1_3_RFC_AES_128_GCM_SHA256,
TLS1_3_RFC_AES_128_GCM_SHA256,
TLS1_3_CK_AES_128_GCM_SHA256,
SSL_kANY,
SSL_aANY,
SSL_AES128GCM,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256,
128,
128,
}, {
1,
TLS1_3_RFC_AES_256_GCM_SHA384,
TLS1_3_RFC_AES_256_GCM_SHA384,
TLS1_3_CK_AES_256_GCM_SHA384,
SSL_kANY,
SSL_aANY,
SSL_AES256GCM,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384,
256,
256,
},
#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
{
1,
TLS1_3_RFC_CHACHA20_POLY1305_SHA256,
TLS1_3_RFC_CHACHA20_POLY1305_SHA256,
TLS1_3_CK_CHACHA20_POLY1305_SHA256,
SSL_kANY,
SSL_aANY,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256,
256,
256,
},
#endif
{
1,
TLS1_3_RFC_AES_128_CCM_SHA256,
TLS1_3_RFC_AES_128_CCM_SHA256,
TLS1_3_CK_AES_128_CCM_SHA256,
SSL_kANY,
SSL_aANY,
SSL_AES128CCM,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256,
128,
128,
}, {
1,
TLS1_3_RFC_AES_128_CCM_8_SHA256,
TLS1_3_RFC_AES_128_CCM_8_SHA256,
TLS1_3_CK_AES_128_CCM_8_SHA256,
SSL_kANY,
SSL_aANY,
SSL_AES128CCM8,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256,
128,
128,
}
};
/*
* The list of available ciphers, mostly organized into the following
* groups:
* Always there
* EC
* PSK
* SRP (within that: RSA EC PSK)
* Cipher families: Chacha/poly, Camellia, Gost, IDEA, SEED
* Weak ciphers
*/
static SSL_CIPHER ssl3_ciphers[] = {
{
1,
SSL3_TXT_RSA_NULL_MD5,
SSL3_RFC_RSA_NULL_MD5,
SSL3_CK_RSA_NULL_MD5,
SSL_kRSA,
SSL_aRSA,
SSL_eNULL,
SSL_MD5,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
SSL3_TXT_RSA_NULL_SHA,
SSL3_RFC_RSA_NULL_SHA,
SSL3_CK_RSA_NULL_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_eNULL,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
SSL3_TXT_RSA_DES_192_CBC3_SHA,
SSL3_RFC_RSA_DES_192_CBC3_SHA,
SSL3_CK_RSA_DES_192_CBC3_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
{
1,
SSL3_TXT_DHE_DSS_DES_192_CBC3_SHA,
SSL3_RFC_DHE_DSS_DES_192_CBC3_SHA,
SSL3_CK_DHE_DSS_DES_192_CBC3_SHA,
SSL_kDHE,
SSL_aDSS,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
{
1,
SSL3_TXT_DHE_RSA_DES_192_CBC3_SHA,
SSL3_RFC_DHE_RSA_DES_192_CBC3_SHA,
SSL3_CK_DHE_RSA_DES_192_CBC3_SHA,
SSL_kDHE,
SSL_aRSA,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
{
1,
SSL3_TXT_ADH_DES_192_CBC_SHA,
SSL3_RFC_ADH_DES_192_CBC_SHA,
SSL3_CK_ADH_DES_192_CBC_SHA,
SSL_kDHE,
SSL_aNULL,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
#endif
{
1,
TLS1_TXT_RSA_WITH_AES_128_SHA,
TLS1_RFC_RSA_WITH_AES_128_SHA,
TLS1_CK_RSA_WITH_AES_128_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_AES_128_SHA,
TLS1_RFC_DHE_DSS_WITH_AES_128_SHA,
TLS1_CK_DHE_DSS_WITH_AES_128_SHA,
SSL_kDHE,
SSL_aDSS,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_128_SHA,
TLS1_RFC_DHE_RSA_WITH_AES_128_SHA,
TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
SSL_kDHE,
SSL_aRSA,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ADH_WITH_AES_128_SHA,
TLS1_RFC_ADH_WITH_AES_128_SHA,
TLS1_CK_ADH_WITH_AES_128_SHA,
SSL_kDHE,
SSL_aNULL,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_RSA_WITH_AES_256_SHA,
TLS1_RFC_RSA_WITH_AES_256_SHA,
TLS1_CK_RSA_WITH_AES_256_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_AES_256_SHA,
TLS1_RFC_DHE_DSS_WITH_AES_256_SHA,
TLS1_CK_DHE_DSS_WITH_AES_256_SHA,
SSL_kDHE,
SSL_aDSS,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_256_SHA,
TLS1_RFC_DHE_RSA_WITH_AES_256_SHA,
TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
SSL_kDHE,
SSL_aRSA,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_ADH_WITH_AES_256_SHA,
TLS1_RFC_ADH_WITH_AES_256_SHA,
TLS1_CK_ADH_WITH_AES_256_SHA,
SSL_kDHE,
SSL_aNULL,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_RSA_WITH_NULL_SHA256,
TLS1_RFC_RSA_WITH_NULL_SHA256,
TLS1_CK_RSA_WITH_NULL_SHA256,
SSL_kRSA,
SSL_aRSA,
SSL_eNULL,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
TLS1_TXT_RSA_WITH_AES_128_SHA256,
TLS1_RFC_RSA_WITH_AES_128_SHA256,
TLS1_CK_RSA_WITH_AES_128_SHA256,
SSL_kRSA,
SSL_aRSA,
SSL_AES128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_RSA_WITH_AES_256_SHA256,
TLS1_RFC_RSA_WITH_AES_256_SHA256,
TLS1_CK_RSA_WITH_AES_256_SHA256,
SSL_kRSA,
SSL_aRSA,
SSL_AES256,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256,
TLS1_RFC_DHE_DSS_WITH_AES_128_SHA256,
TLS1_CK_DHE_DSS_WITH_AES_128_SHA256,
SSL_kDHE,
SSL_aDSS,
SSL_AES128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256,
TLS1_RFC_DHE_RSA_WITH_AES_128_SHA256,
TLS1_CK_DHE_RSA_WITH_AES_128_SHA256,
SSL_kDHE,
SSL_aRSA,
SSL_AES128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256,
TLS1_RFC_DHE_DSS_WITH_AES_256_SHA256,
TLS1_CK_DHE_DSS_WITH_AES_256_SHA256,
SSL_kDHE,
SSL_aDSS,
SSL_AES256,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256,
TLS1_RFC_DHE_RSA_WITH_AES_256_SHA256,
TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
SSL_kDHE,
SSL_aRSA,
SSL_AES256,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_ADH_WITH_AES_128_SHA256,
TLS1_RFC_ADH_WITH_AES_128_SHA256,
TLS1_CK_ADH_WITH_AES_128_SHA256,
SSL_kDHE,
SSL_aNULL,
SSL_AES128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ADH_WITH_AES_256_SHA256,
TLS1_RFC_ADH_WITH_AES_256_SHA256,
TLS1_CK_ADH_WITH_AES_256_SHA256,
SSL_kDHE,
SSL_aNULL,
SSL_AES256,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256,
TLS1_RFC_RSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_RSA_WITH_AES_128_GCM_SHA256,
SSL_kRSA,
SSL_aRSA,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384,
TLS1_RFC_RSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_RSA_WITH_AES_256_GCM_SHA384,
SSL_kRSA,
SSL_aRSA,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256,
TLS1_RFC_DHE_RSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256,
SSL_kDHE,
SSL_aRSA,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384,
TLS1_RFC_DHE_RSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384,
SSL_kDHE,
SSL_aRSA,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256,
TLS1_RFC_DHE_DSS_WITH_AES_128_GCM_SHA256,
TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256,
SSL_kDHE,
SSL_aDSS,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384,
TLS1_RFC_DHE_DSS_WITH_AES_256_GCM_SHA384,
TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384,
SSL_kDHE,
SSL_aDSS,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256,
TLS1_RFC_ADH_WITH_AES_128_GCM_SHA256,
TLS1_CK_ADH_WITH_AES_128_GCM_SHA256,
SSL_kDHE,
SSL_aNULL,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384,
TLS1_RFC_ADH_WITH_AES_256_GCM_SHA384,
TLS1_CK_ADH_WITH_AES_256_GCM_SHA384,
SSL_kDHE,
SSL_aNULL,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_RSA_WITH_AES_128_CCM,
TLS1_RFC_RSA_WITH_AES_128_CCM,
TLS1_CK_RSA_WITH_AES_128_CCM,
SSL_kRSA,
SSL_aRSA,
SSL_AES128CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_RSA_WITH_AES_256_CCM,
TLS1_RFC_RSA_WITH_AES_256_CCM,
TLS1_CK_RSA_WITH_AES_256_CCM,
SSL_kRSA,
SSL_aRSA,
SSL_AES256CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_128_CCM,
TLS1_RFC_DHE_RSA_WITH_AES_128_CCM,
TLS1_CK_DHE_RSA_WITH_AES_128_CCM,
SSL_kDHE,
SSL_aRSA,
SSL_AES128CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_256_CCM,
TLS1_RFC_DHE_RSA_WITH_AES_256_CCM,
TLS1_CK_DHE_RSA_WITH_AES_256_CCM,
SSL_kDHE,
SSL_aRSA,
SSL_AES256CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_RSA_WITH_AES_128_CCM_8,
TLS1_RFC_RSA_WITH_AES_128_CCM_8,
TLS1_CK_RSA_WITH_AES_128_CCM_8,
SSL_kRSA,
SSL_aRSA,
SSL_AES128CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_RSA_WITH_AES_256_CCM_8,
TLS1_RFC_RSA_WITH_AES_256_CCM_8,
TLS1_CK_RSA_WITH_AES_256_CCM_8,
SSL_kRSA,
SSL_aRSA,
SSL_AES256CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_128_CCM_8,
TLS1_RFC_DHE_RSA_WITH_AES_128_CCM_8,
TLS1_CK_DHE_RSA_WITH_AES_128_CCM_8,
SSL_kDHE,
SSL_aRSA,
SSL_AES128CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_AES_256_CCM_8,
TLS1_RFC_DHE_RSA_WITH_AES_256_CCM_8,
TLS1_CK_DHE_RSA_WITH_AES_256_CCM_8,
SSL_kDHE,
SSL_aRSA,
SSL_AES256CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_AES_128_CCM,
TLS1_RFC_PSK_WITH_AES_128_CCM,
TLS1_CK_PSK_WITH_AES_128_CCM,
SSL_kPSK,
SSL_aPSK,
SSL_AES128CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_PSK_WITH_AES_256_CCM,
TLS1_RFC_PSK_WITH_AES_256_CCM,
TLS1_CK_PSK_WITH_AES_256_CCM,
SSL_kPSK,
SSL_aPSK,
SSL_AES256CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_128_CCM,
TLS1_RFC_DHE_PSK_WITH_AES_128_CCM,
TLS1_CK_DHE_PSK_WITH_AES_128_CCM,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES128CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_256_CCM,
TLS1_RFC_DHE_PSK_WITH_AES_256_CCM,
TLS1_CK_DHE_PSK_WITH_AES_256_CCM,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES256CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_AES_128_CCM_8,
TLS1_RFC_PSK_WITH_AES_128_CCM_8,
TLS1_CK_PSK_WITH_AES_128_CCM_8,
SSL_kPSK,
SSL_aPSK,
SSL_AES128CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_PSK_WITH_AES_256_CCM_8,
TLS1_RFC_PSK_WITH_AES_256_CCM_8,
TLS1_CK_PSK_WITH_AES_256_CCM_8,
SSL_kPSK,
SSL_aPSK,
SSL_AES256CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_128_CCM_8,
TLS1_RFC_DHE_PSK_WITH_AES_128_CCM_8,
TLS1_CK_DHE_PSK_WITH_AES_128_CCM_8,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES128CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_256_CCM_8,
TLS1_RFC_DHE_PSK_WITH_AES_256_CCM_8,
TLS1_CK_DHE_PSK_WITH_AES_256_CCM_8,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES256CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM,
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES128CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM,
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES256CCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM_8,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM_8,
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM_8,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES128CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM_8,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM_8,
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM_8,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES256CCM8,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA,
TLS1_RFC_ECDHE_ECDSA_WITH_NULL_SHA,
TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA,
SSL_kECDHE,
SSL_aECDSA,
SSL_eNULL,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
TLS1_RFC_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
SSL_kECDHE,
SSL_aECDSA,
SSL_3DES,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
# endif
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES128,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES256,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA,
TLS1_RFC_ECDHE_RSA_WITH_NULL_SHA,
TLS1_CK_ECDHE_RSA_WITH_NULL_SHA,
SSL_kECDHE,
SSL_aRSA,
SSL_eNULL,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
TLS1_RFC_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
SSL_kECDHE,
SSL_aRSA,
SSL_3DES,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
# endif
{
1,
TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS1_RFC_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA,
SSL_kECDHE,
SSL_aRSA,
SSL_AES128,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS1_RFC_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA,
SSL_kECDHE,
SSL_aRSA,
SSL_AES256,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_ECDH_anon_WITH_NULL_SHA,
TLS1_RFC_ECDH_anon_WITH_NULL_SHA,
TLS1_CK_ECDH_anon_WITH_NULL_SHA,
SSL_kECDHE,
SSL_aNULL,
SSL_eNULL,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA,
TLS1_RFC_ECDH_anon_WITH_DES_192_CBC3_SHA,
TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA,
SSL_kECDHE,
SSL_aNULL,
SSL_3DES,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
# endif
{
1,
TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA,
TLS1_RFC_ECDH_anon_WITH_AES_128_CBC_SHA,
TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA,
SSL_kECDHE,
SSL_aNULL,
SSL_AES128,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA,
TLS1_RFC_ECDH_anon_WITH_AES_256_CBC_SHA,
TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA,
SSL_kECDHE,
SSL_aNULL,
SSL_AES256,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_SHA256,
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_SHA384,
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES256,
SSL_SHA384,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256,
TLS1_RFC_ECDHE_RSA_WITH_AES_128_SHA256,
TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
SSL_kECDHE,
SSL_aRSA,
SSL_AES128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384,
TLS1_RFC_ECDHE_RSA_WITH_AES_256_SHA384,
TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
SSL_kECDHE,
SSL_aRSA,
SSL_AES256,
SSL_SHA384,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
SSL_kECDHE,
SSL_aECDSA,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS1_RFC_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
SSL_kECDHE,
SSL_aRSA,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS1_RFC_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
SSL_kECDHE,
SSL_aRSA,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_NULL_SHA,
TLS1_RFC_PSK_WITH_NULL_SHA,
TLS1_CK_PSK_WITH_NULL_SHA,
SSL_kPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_NULL_SHA,
TLS1_RFC_DHE_PSK_WITH_NULL_SHA,
TLS1_CK_DHE_PSK_WITH_NULL_SHA,
SSL_kDHEPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_NULL_SHA,
TLS1_RFC_RSA_PSK_WITH_NULL_SHA,
TLS1_CK_RSA_PSK_WITH_NULL_SHA,
SSL_kRSAPSK,
SSL_aRSA,
SSL_eNULL,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA,
TLS1_RFC_PSK_WITH_3DES_EDE_CBC_SHA,
TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA,
SSL_kPSK,
SSL_aPSK,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
# endif
{
1,
TLS1_TXT_PSK_WITH_AES_128_CBC_SHA,
TLS1_RFC_PSK_WITH_AES_128_CBC_SHA,
TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
SSL_kPSK,
SSL_aPSK,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_PSK_WITH_AES_256_CBC_SHA,
TLS1_RFC_PSK_WITH_AES_256_CBC_SHA,
TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
SSL_kPSK,
SSL_aPSK,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
TLS1_TXT_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
TLS1_RFC_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
TLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
SSL_kDHEPSK,
SSL_aPSK,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
# endif
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA,
TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA,
TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA,
TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA,
TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
TLS1_RFC_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
SSL_kRSAPSK,
SSL_aRSA,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
# endif
{
1,
TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA,
TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA,
TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA,
SSL_kRSAPSK,
SSL_aRSA,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA,
TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA,
TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA,
SSL_kRSAPSK,
SSL_aRSA,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256,
TLS1_RFC_PSK_WITH_AES_128_GCM_SHA256,
TLS1_CK_PSK_WITH_AES_128_GCM_SHA256,
SSL_kPSK,
SSL_aPSK,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384,
TLS1_RFC_PSK_WITH_AES_256_GCM_SHA384,
TLS1_CK_PSK_WITH_AES_256_GCM_SHA384,
SSL_kPSK,
SSL_aPSK,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_128_GCM_SHA256,
TLS1_RFC_DHE_PSK_WITH_AES_128_GCM_SHA256,
TLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_256_GCM_SHA384,
TLS1_RFC_DHE_PSK_WITH_AES_256_GCM_SHA384,
TLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256,
TLS1_RFC_RSA_PSK_WITH_AES_128_GCM_SHA256,
TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256,
SSL_kRSAPSK,
SSL_aRSA,
SSL_AES128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384,
TLS1_RFC_RSA_PSK_WITH_AES_256_GCM_SHA384,
TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384,
SSL_kRSAPSK,
SSL_aRSA,
SSL_AES256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256,
TLS1_RFC_PSK_WITH_AES_128_CBC_SHA256,
TLS1_CK_PSK_WITH_AES_128_CBC_SHA256,
SSL_kPSK,
SSL_aPSK,
SSL_AES128,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384,
TLS1_RFC_PSK_WITH_AES_256_CBC_SHA384,
TLS1_CK_PSK_WITH_AES_256_CBC_SHA384,
SSL_kPSK,
SSL_aPSK,
SSL_AES256,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_NULL_SHA256,
TLS1_RFC_PSK_WITH_NULL_SHA256,
TLS1_CK_PSK_WITH_NULL_SHA256,
SSL_kPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
TLS1_TXT_PSK_WITH_NULL_SHA384,
TLS1_RFC_PSK_WITH_NULL_SHA384,
TLS1_CK_PSK_WITH_NULL_SHA384,
SSL_kPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
0,
0,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256,
TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA256,
TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES128,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA384,
TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA384,
TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384,
SSL_kDHEPSK,
SSL_aPSK,
SSL_AES256,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_NULL_SHA256,
TLS1_RFC_DHE_PSK_WITH_NULL_SHA256,
TLS1_CK_DHE_PSK_WITH_NULL_SHA256,
SSL_kDHEPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_NULL_SHA384,
TLS1_RFC_DHE_PSK_WITH_NULL_SHA384,
TLS1_CK_DHE_PSK_WITH_NULL_SHA384,
SSL_kDHEPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
0,
0,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256,
TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA256,
TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256,
SSL_kRSAPSK,
SSL_aRSA,
SSL_AES128,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384,
TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA384,
TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384,
SSL_kRSAPSK,
SSL_aRSA,
SSL_AES256,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_NULL_SHA256,
TLS1_RFC_RSA_PSK_WITH_NULL_SHA256,
TLS1_CK_RSA_PSK_WITH_NULL_SHA256,
SSL_kRSAPSK,
SSL_aRSA,
SSL_eNULL,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_NULL_SHA384,
TLS1_RFC_RSA_PSK_WITH_NULL_SHA384,
TLS1_CK_RSA_PSK_WITH_NULL_SHA384,
SSL_kRSAPSK,
SSL_aRSA,
SSL_eNULL,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
0,
0,
},
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
TLS1_TXT_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
TLS1_RFC_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
TLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_3DES,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
# endif
{
1,
TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA,
TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA,
TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_AES128,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA,
TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA,
TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_AES256,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_AES128,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_AES256,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA,
TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA,
TLS1_CK_ECDHE_PSK_WITH_NULL_SHA,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA256,
TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA256,
TLS1_CK_ECDHE_PSK_WITH_NULL_SHA256,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
0,
0,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA384,
TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA384,
TLS1_CK_ECDHE_PSK_WITH_NULL_SHA384,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_eNULL,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_STRONG_NONE | SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
0,
0,
},
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
TLS1_RFC_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
SSL_kSRP,
SSL_aSRP,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
{
1,
TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
TLS1_RFC_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
SSL_kSRP,
SSL_aRSA,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
{
1,
TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
TLS1_RFC_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
SSL_kSRP,
SSL_aDSS,
SSL_3DES,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
},
# endif
{
1,
TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA,
TLS1_RFC_SRP_SHA_WITH_AES_128_CBC_SHA,
TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA,
SSL_kSRP,
SSL_aSRP,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
TLS1_RFC_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
SSL_kSRP,
SSL_aRSA,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
TLS1_RFC_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
SSL_kSRP,
SSL_aDSS,
SSL_AES128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA,
TLS1_RFC_SRP_SHA_WITH_AES_256_CBC_SHA,
TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA,
SSL_kSRP,
SSL_aSRP,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
TLS1_RFC_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
SSL_kSRP,
SSL_aRSA,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
TLS1_RFC_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
SSL_kSRP,
SSL_aDSS,
SSL_AES256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
{
1,
TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
TLS1_RFC_DHE_RSA_WITH_CHACHA20_POLY1305,
TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305,
SSL_kDHE,
SSL_aRSA,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
TLS1_RFC_ECDHE_RSA_WITH_CHACHA20_POLY1305,
TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305,
SSL_kECDHE,
SSL_aRSA,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
TLS1_RFC_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
SSL_kECDHE,
SSL_aECDSA,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_CHACHA20_POLY1305,
TLS1_RFC_PSK_WITH_CHACHA20_POLY1305,
TLS1_CK_PSK_WITH_CHACHA20_POLY1305,
SSL_kPSK,
SSL_aPSK,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305,
TLS1_RFC_ECDHE_PSK_WITH_CHACHA20_POLY1305,
TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305,
TLS1_RFC_DHE_PSK_WITH_CHACHA20_POLY1305,
TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305,
SSL_kDHEPSK,
SSL_aPSK,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305,
TLS1_RFC_RSA_PSK_WITH_CHACHA20_POLY1305,
TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305,
SSL_kRSAPSK,
SSL_aRSA,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
#endif /* !defined(OPENSSL_NO_CHACHA) &&
* !defined(OPENSSL_NO_POLY1305) */
#ifndef OPENSSL_NO_CAMELLIA
{
1,
TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kRSA,
SSL_aRSA,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kEDH,
SSL_aDSS,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kEDH,
SSL_aRSA,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kEDH,
SSL_aNULL,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256,
TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA256,
TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256,
SSL_kRSA,
SSL_aRSA,
SSL_CAMELLIA256,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
SSL_kEDH,
SSL_aDSS,
SSL_CAMELLIA256,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
SSL_kEDH,
SSL_aRSA,
SSL_CAMELLIA256,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256,
TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA256,
TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256,
SSL_kEDH,
SSL_aNULL,
SSL_CAMELLIA256,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
256,
256,
},
{
1,
TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA,
TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA,
TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_CAMELLIA256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
SSL_kDHE,
SSL_aDSS,
SSL_CAMELLIA256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
SSL_kDHE,
SSL_aRSA,
SSL_CAMELLIA256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA,
TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA,
TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA,
SSL_kDHE,
SSL_aNULL,
SSL_CAMELLIA256,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
256,
256,
},
{
1,
TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA,
TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA,
TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_CAMELLIA128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
SSL_kDHE,
SSL_aDSS,
SSL_CAMELLIA128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
SSL_kDHE,
SSL_aRSA,
SSL_CAMELLIA128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA,
TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA,
TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA,
SSL_kDHE,
SSL_aNULL,
SSL_CAMELLIA128,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kECDHE,
SSL_aECDSA,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
SSL_kECDHE,
SSL_aECDSA,
SSL_CAMELLIA256,
SSL_SHA384,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kECDHE,
SSL_aRSA,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
SSL_kECDHE,
SSL_aRSA,
SSL_CAMELLIA256,
SSL_SHA384,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kPSK,
SSL_aPSK,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_RFC_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384,
SSL_kPSK,
SSL_aPSK,
SSL_CAMELLIA256,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kDHEPSK,
SSL_aPSK,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_RFC_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
SSL_kDHEPSK,
SSL_aPSK,
SSL_CAMELLIA256,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kRSAPSK,
SSL_aRSA,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_RFC_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
SSL_kRSAPSK,
SSL_aRSA,
SSL_CAMELLIA256,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_CAMELLIA128,
SSL_SHA256,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_CAMELLIA256,
SSL_SHA384,
TLS1_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
#endif /* OPENSSL_NO_CAMELLIA */
#ifndef OPENSSL_NO_GOST
{
1,
"GOST2001-GOST89-GOST89",
"TLS_GOSTR341001_WITH_28147_CNT_IMIT",
0x3000081,
SSL_kGOST,
SSL_aGOST01,
SSL_eGOST2814789CNT,
SSL_GOST89MAC,
TLS1_VERSION, TLS1_2_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_GOST94 | TLS1_PRF_GOST94 | TLS1_STREAM_MAC,
256,
256,
},
{
1,
"GOST2001-NULL-GOST94",
"TLS_GOSTR341001_WITH_NULL_GOSTR3411",
0x3000083,
SSL_kGOST,
SSL_aGOST01,
SSL_eNULL,
SSL_GOST94,
TLS1_VERSION, TLS1_2_VERSION,
0, 0,
SSL_STRONG_NONE,
SSL_HANDSHAKE_MAC_GOST94 | TLS1_PRF_GOST94,
0,
0,
},
{
1,
"GOST2012-GOST8912-GOST8912",
NULL,
0x0300ff85,
SSL_kGOST,
SSL_aGOST12 | SSL_aGOST01,
SSL_eGOST2814789CNT12,
SSL_GOST89MAC12,
TLS1_VERSION, TLS1_2_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC,
256,
256,
},
{
1,
"GOST2012-NULL-GOST12",
NULL,
0x0300ff87,
SSL_kGOST,
SSL_aGOST12 | SSL_aGOST01,
SSL_eNULL,
SSL_GOST12_256,
TLS1_VERSION, TLS1_2_VERSION,
0, 0,
SSL_STRONG_NONE,
SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC,
0,
0,
},
#endif /* OPENSSL_NO_GOST */
#ifndef OPENSSL_NO_IDEA
{
1,
SSL3_TXT_RSA_IDEA_128_SHA,
SSL3_RFC_RSA_IDEA_128_SHA,
SSL3_CK_RSA_IDEA_128_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_IDEA,
SSL_SHA1,
SSL3_VERSION, TLS1_1_VERSION,
DTLS1_BAD_VER, DTLS1_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
#endif
#ifndef OPENSSL_NO_SEED
{
1,
TLS1_TXT_RSA_WITH_SEED_SHA,
TLS1_RFC_RSA_WITH_SEED_SHA,
TLS1_CK_RSA_WITH_SEED_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_SEED,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_SEED_SHA,
TLS1_RFC_DHE_DSS_WITH_SEED_SHA,
TLS1_CK_DHE_DSS_WITH_SEED_SHA,
SSL_kDHE,
SSL_aDSS,
SSL_SEED,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_SEED_SHA,
TLS1_RFC_DHE_RSA_WITH_SEED_SHA,
TLS1_CK_DHE_RSA_WITH_SEED_SHA,
SSL_kDHE,
SSL_aRSA,
SSL_SEED,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ADH_WITH_SEED_SHA,
TLS1_RFC_ADH_WITH_SEED_SHA,
TLS1_CK_ADH_WITH_SEED_SHA,
SSL_kDHE,
SSL_aNULL,
SSL_SEED,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
#endif /* OPENSSL_NO_SEED */
#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
1,
SSL3_TXT_RSA_RC4_128_MD5,
SSL3_RFC_RSA_RC4_128_MD5,
SSL3_CK_RSA_RC4_128_MD5,
SSL_kRSA,
SSL_aRSA,
SSL_RC4,
SSL_MD5,
SSL3_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
SSL3_TXT_RSA_RC4_128_SHA,
SSL3_RFC_RSA_RC4_128_SHA,
SSL3_CK_RSA_RC4_128_SHA,
SSL_kRSA,
SSL_aRSA,
SSL_RC4,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
SSL3_TXT_ADH_RC4_128_MD5,
SSL3_RFC_ADH_RC4_128_MD5,
SSL3_CK_ADH_RC4_128_MD5,
SSL_kDHE,
SSL_aNULL,
SSL_RC4,
SSL_MD5,
SSL3_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_PSK_WITH_RC4_128_SHA,
TLS1_RFC_ECDHE_PSK_WITH_RC4_128_SHA,
TLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA,
SSL_kECDHEPSK,
SSL_aPSK,
SSL_RC4,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA,
TLS1_RFC_ECDH_anon_WITH_RC4_128_SHA,
TLS1_CK_ECDH_anon_WITH_RC4_128_SHA,
SSL_kECDHE,
SSL_aNULL,
SSL_RC4,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS1_RFC_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA,
SSL_kECDHE,
SSL_aECDSA,
SSL_RC4,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA,
TLS1_RFC_ECDHE_RSA_WITH_RC4_128_SHA,
TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA,
SSL_kECDHE,
SSL_aRSA,
SSL_RC4,
SSL_SHA1,
TLS1_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_PSK_WITH_RC4_128_SHA,
TLS1_RFC_PSK_WITH_RC4_128_SHA,
TLS1_CK_PSK_WITH_RC4_128_SHA,
SSL_kPSK,
SSL_aPSK,
SSL_RC4,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA,
TLS1_RFC_RSA_PSK_WITH_RC4_128_SHA,
TLS1_CK_RSA_PSK_WITH_RC4_128_SHA,
SSL_kRSAPSK,
SSL_aRSA,
SSL_RC4,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_RC4_128_SHA,
TLS1_RFC_DHE_PSK_WITH_RC4_128_SHA,
TLS1_CK_DHE_PSK_WITH_RC4_128_SHA,
SSL_kDHEPSK,
SSL_aPSK,
SSL_RC4,
SSL_SHA1,
SSL3_VERSION, TLS1_2_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
128,
128,
},
#endif /* OPENSSL_NO_WEAK_SSL_CIPHERS */
#ifndef OPENSSL_NO_ARIA
{
1,
TLS1_TXT_RSA_WITH_ARIA_128_GCM_SHA256,
TLS1_RFC_RSA_WITH_ARIA_128_GCM_SHA256,
TLS1_CK_RSA_WITH_ARIA_128_GCM_SHA256,
SSL_kRSA,
SSL_aRSA,
SSL_ARIA128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_RSA_WITH_ARIA_256_GCM_SHA384,
TLS1_RFC_RSA_WITH_ARIA_256_GCM_SHA384,
TLS1_CK_RSA_WITH_ARIA_256_GCM_SHA384,
SSL_kRSA,
SSL_aRSA,
SSL_ARIA256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
TLS1_RFC_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
TLS1_CK_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
SSL_kDHE,
SSL_aRSA,
SSL_ARIA128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
TLS1_RFC_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
TLS1_CK_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
SSL_kDHE,
SSL_aRSA,
SSL_ARIA256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_ARIA_128_GCM_SHA256,
TLS1_RFC_DHE_DSS_WITH_ARIA_128_GCM_SHA256,
TLS1_CK_DHE_DSS_WITH_ARIA_128_GCM_SHA256,
SSL_kDHE,
SSL_aDSS,
SSL_ARIA128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_DSS_WITH_ARIA_256_GCM_SHA384,
TLS1_RFC_DHE_DSS_WITH_ARIA_256_GCM_SHA384,
TLS1_CK_DHE_DSS_WITH_ARIA_256_GCM_SHA384,
SSL_kDHE,
SSL_aDSS,
SSL_ARIA256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
TLS1_CK_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
SSL_kECDHE,
SSL_aECDSA,
SSL_ARIA128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
TLS1_CK_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
SSL_kECDHE,
SSL_aECDSA,
SSL_ARIA256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
TLS1_RFC_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
TLS1_CK_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
SSL_kECDHE,
SSL_aRSA,
SSL_ARIA128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
TLS1_RFC_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
TLS1_CK_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
SSL_kECDHE,
SSL_aRSA,
SSL_ARIA256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_PSK_WITH_ARIA_128_GCM_SHA256,
TLS1_RFC_PSK_WITH_ARIA_128_GCM_SHA256,
TLS1_CK_PSK_WITH_ARIA_128_GCM_SHA256,
SSL_kPSK,
SSL_aPSK,
SSL_ARIA128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_PSK_WITH_ARIA_256_GCM_SHA384,
TLS1_RFC_PSK_WITH_ARIA_256_GCM_SHA384,
TLS1_CK_PSK_WITH_ARIA_256_GCM_SHA384,
SSL_kPSK,
SSL_aPSK,
SSL_ARIA256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
TLS1_RFC_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
TLS1_CK_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
SSL_kDHEPSK,
SSL_aPSK,
SSL_ARIA128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
TLS1_RFC_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
TLS1_CK_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
SSL_kDHEPSK,
SSL_aPSK,
SSL_ARIA256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
TLS1_RFC_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
TLS1_CK_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
SSL_kRSAPSK,
SSL_aRSA,
SSL_ARIA128GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
128,
128,
},
{
1,
TLS1_TXT_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
TLS1_RFC_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
TLS1_CK_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
SSL_kRSAPSK,
SSL_aRSA,
SSL_ARIA256GCM,
SSL_AEAD,
TLS1_2_VERSION, TLS1_2_VERSION,
DTLS1_2_VERSION, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
256,
256,
},
#endif /* OPENSSL_NO_ARIA */
};
/*
* The list of known Signalling Cipher-Suite Value "ciphers", non-valid
* values stuffed into the ciphers field of the wire protocol for signalling
* purposes.
*/
static SSL_CIPHER ssl3_scsvs[] = {
{
0,
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
SSL3_CK_SCSV,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
},
{
0,
"TLS_FALLBACK_SCSV",
"TLS_FALLBACK_SCSV",
SSL3_CK_FALLBACK_SCSV,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
},
};
static int cipher_compare(const void *a, const void *b)
{
const SSL_CIPHER *ap = (const SSL_CIPHER *)a;
const SSL_CIPHER *bp = (const SSL_CIPHER *)b;
if (ap->id == bp->id)
return 0;
return ap->id < bp->id ? -1 : 1;
}
void ssl_sort_cipher_list(void)
{
qsort(tls13_ciphers, TLS13_NUM_CIPHERS, sizeof(tls13_ciphers[0]),
cipher_compare);
qsort(ssl3_ciphers, SSL3_NUM_CIPHERS, sizeof(ssl3_ciphers[0]),
cipher_compare);
qsort(ssl3_scsvs, SSL3_NUM_SCSVS, sizeof(ssl3_scsvs[0]), cipher_compare);
}
static int ssl_undefined_function_1(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);
}
const SSL3_ENC_METHOD SSLv3_enc_data = {
ssl3_enc,
n_ssl3_mac,
ssl3_setup_key_block,
ssl3_generate_master_secret,
ssl3_change_cipher_state,
ssl3_final_finish_mac,
SSL3_MD_CLIENT_FINISHED_CONST, 4,
SSL3_MD_SERVER_FINISHED_CONST, 4,
ssl3_alert_code,
ssl_undefined_function_1,
0,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
long ssl3_default_timeout(void)
{
/*
* 2 hours, the 24 hours mentioned in the SSLv3 spec is way too long for
* http, the cache would over fill
*/
return (60 * 60 * 2);
}
int ssl3_num_ciphers(void)
{
return SSL3_NUM_CIPHERS;
}
const SSL_CIPHER *ssl3_get_cipher(unsigned int u)
{
if (u < SSL3_NUM_CIPHERS)
return &(ssl3_ciphers[SSL3_NUM_CIPHERS - 1 - u]);
else
return NULL;
}
int ssl3_set_handshake_header(SSL *s, WPACKET *pkt, int htype)
{
/* No header in the event of a CCS */
if (htype == SSL3_MT_CHANGE_CIPHER_SPEC)
return 1;
/* Set the content type and 3 bytes for the message len */
if (!WPACKET_put_bytes_u8(pkt, htype)
|| !WPACKET_start_sub_packet_u24(pkt))
return 0;
return 1;
}
int ssl3_handshake_write(SSL *s)
{
return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
}
int ssl3_new(SSL *s)
{
SSL3_STATE *s3;
if ((s3 = OPENSSL_zalloc(sizeof(*s3))) == NULL)
goto err;
s->s3 = s3;
#ifndef OPENSSL_NO_SRP
if (!SSL_SRP_CTX_init(s))
goto err;
#endif
if (!s->method->ssl_clear(s))
return 0;
return 1;
err:
return 0;
}
void ssl3_free(SSL *s)
{
if (s == NULL || s->s3 == NULL)
return;
ssl3_cleanup_key_block(s);
#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
EVP_PKEY_free(s->s3->peer_tmp);
s->s3->peer_tmp = NULL;
EVP_PKEY_free(s->s3->tmp.pkey);
s->s3->tmp.pkey = NULL;
#endif
OPENSSL_free(s->s3->tmp.ctype);
sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
OPENSSL_free(s->s3->tmp.ciphers_raw);
OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
OPENSSL_free(s->s3->tmp.peer_sigalgs);
OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
ssl3_free_digest_list(s);
OPENSSL_free(s->s3->alpn_selected);
OPENSSL_free(s->s3->alpn_proposed);
#ifndef OPENSSL_NO_SRP
SSL_SRP_CTX_free(s);
#endif
OPENSSL_clear_free(s->s3, sizeof(*s->s3));
s->s3 = NULL;
}
int ssl3_clear(SSL *s)
{
ssl3_cleanup_key_block(s);
OPENSSL_free(s->s3->tmp.ctype);
sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
OPENSSL_free(s->s3->tmp.ciphers_raw);
OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
OPENSSL_free(s->s3->tmp.peer_sigalgs);
OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
EVP_PKEY_free(s->s3->tmp.pkey);
EVP_PKEY_free(s->s3->peer_tmp);
#endif /* !OPENSSL_NO_EC */
ssl3_free_digest_list(s);
OPENSSL_free(s->s3->alpn_selected);
OPENSSL_free(s->s3->alpn_proposed);
/* NULL/zero-out everything in the s3 struct */
memset(s->s3, 0, sizeof(*s->s3));
if (!ssl_free_wbio_buffer(s))
return 0;
s->version = SSL3_VERSION;
#if !defined(OPENSSL_NO_NEXTPROTONEG)
OPENSSL_free(s->ext.npn);
s->ext.npn = NULL;
s->ext.npn_len = 0;
#endif
return 1;
}
#ifndef OPENSSL_NO_SRP
static char *srp_password_from_info_cb(SSL *s, void *arg)
{
return OPENSSL_strdup(s->srp_ctx.info);
}
#endif
static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len);
long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
{
int ret = 0;
switch (cmd) {
case SSL_CTRL_GET_CLIENT_CERT_REQUEST:
break;
case SSL_CTRL_GET_NUM_RENEGOTIATIONS:
ret = s->s3->num_renegotiations;
break;
case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS:
ret = s->s3->num_renegotiations;
s->s3->num_renegotiations = 0;
break;
case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS:
ret = s->s3->total_renegotiations;
break;
case SSL_CTRL_GET_FLAGS:
ret = (int)(s->s3->flags);
break;
#ifndef OPENSSL_NO_DH
case SSL_CTRL_SET_TMP_DH:
{
DH *dh = (DH *)parg;
EVP_PKEY *pkdh = NULL;
if (dh == NULL) {
SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
return ret;
}
pkdh = ssl_dh_to_pkey(dh);
if (pkdh == NULL) {
SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ssl_security(s, SSL_SECOP_TMP_DH,
EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
SSLerr(SSL_F_SSL3_CTRL, SSL_R_DH_KEY_TOO_SMALL);
EVP_PKEY_free(pkdh);
return ret;
}
EVP_PKEY_free(s->cert->dh_tmp);
s->cert->dh_tmp = pkdh;
ret = 1;
}
break;
case SSL_CTRL_SET_TMP_DH_CB:
{
SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return ret;
}
case SSL_CTRL_SET_DH_AUTO:
s->cert->dh_tmp_auto = larg;
return 1;
#endif
#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_TMP_ECDH:
{
const EC_GROUP *group = NULL;
int nid;
if (parg == NULL) {
SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
group = EC_KEY_get0_group((const EC_KEY *)parg);
if (group == NULL) {
SSLerr(SSL_F_SSL3_CTRL, EC_R_MISSING_PARAMETERS);
return 0;
}
nid = EC_GROUP_get_curve_name(group);
if (nid == NID_undef)
return 0;
return tls1_set_groups(&s->ext.supportedgroups,
&s->ext.supportedgroups_len,
&nid, 1);
}
break;
#endif /* !OPENSSL_NO_EC */
case SSL_CTRL_SET_TLSEXT_HOSTNAME:
/*
* TODO(OpenSSL1.2)
* This API is only used for a client to set what SNI it will request
* from the server, but we currently allow it to be used on servers
* as well, which is a programming error. Currently we just clear
* the field in SSL_do_handshake() for server SSLs, but when we can
* make ABI-breaking changes, we may want to make use of this API
* an error on server SSLs.
*/
if (larg == TLSEXT_NAMETYPE_host_name) {
size_t len;
OPENSSL_free(s->ext.hostname);
s->ext.hostname = NULL;
ret = 1;
if (parg == NULL)
break;
len = strlen((char *)parg);
if (len == 0 || len > TLSEXT_MAXLEN_host_name) {
SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
return 0;
}
if ((s->ext.hostname = OPENSSL_strdup((char *)parg)) == NULL) {
SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
return 0;
}
break;
case SSL_CTRL_SET_TLSEXT_DEBUG_ARG:
s->ext.debug_arg = parg;
ret = 1;
break;
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE:
ret = s->ext.status_type;
break;
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE:
s->ext.status_type = larg;
ret = 1;
break;
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS:
*(STACK_OF(X509_EXTENSION) **)parg = s->ext.ocsp.exts;
ret = 1;
break;
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS:
s->ext.ocsp.exts = parg;
ret = 1;
break;
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS:
*(STACK_OF(OCSP_RESPID) **)parg = s->ext.ocsp.ids;
ret = 1;
break;
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS:
s->ext.ocsp.ids = parg;
ret = 1;
break;
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP:
*(unsigned char **)parg = s->ext.ocsp.resp;
if (s->ext.ocsp.resp_len == 0
|| s->ext.ocsp.resp_len > LONG_MAX)
return -1;
return (long)s->ext.ocsp.resp_len;
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP:
OPENSSL_free(s->ext.ocsp.resp);
s->ext.ocsp.resp = parg;
s->ext.ocsp.resp_len = larg;
ret = 1;
break;
#ifndef OPENSSL_NO_HEARTBEATS
case SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT:
case SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING:
case SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS:
break;
#endif
case SSL_CTRL_CHAIN:
if (larg)
return ssl_cert_set1_chain(s, NULL, (STACK_OF(X509) *)parg);
else
return ssl_cert_set0_chain(s, NULL, (STACK_OF(X509) *)parg);
case SSL_CTRL_CHAIN_CERT:
if (larg)
return ssl_cert_add1_chain_cert(s, NULL, (X509 *)parg);
else
return ssl_cert_add0_chain_cert(s, NULL, (X509 *)parg);
case SSL_CTRL_GET_CHAIN_CERTS:
*(STACK_OF(X509) **)parg = s->cert->key->chain;
break;
case SSL_CTRL_SELECT_CURRENT_CERT:
return ssl_cert_select_current(s->cert, (X509 *)parg);
case SSL_CTRL_SET_CURRENT_CERT:
if (larg == SSL_CERT_SET_SERVER) {
const SSL_CIPHER *cipher;
if (!s->server)
return 0;
cipher = s->s3->tmp.new_cipher;
if (cipher == NULL)
return 0;
/*
* No certificate for unauthenticated ciphersuites or using SRP
* authentication
*/
if (cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
return 2;
if (s->s3->tmp.cert == NULL)
return 0;
s->cert->key = s->s3->tmp.cert;
return 1;
}
return ssl_cert_set_current(s->cert, larg);
#ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_GROUPS:
{
uint16_t *clist;
size_t clistlen;
if (!s->session)
return 0;
clist = s->session->ext.supportedgroups;
clistlen = s->session->ext.supportedgroups_len;
if (parg) {
size_t i;
int *cptr = parg;
for (i = 0; i < clistlen; i++) {
const TLS_GROUP_INFO *cinf = tls1_group_id_lookup(clist[i]);
if (cinf != NULL)
cptr[i] = cinf->nid;
else
cptr[i] = TLSEXT_nid_unknown | clist[i];
}
}
return (int)clistlen;
}
case SSL_CTRL_SET_GROUPS:
return tls1_set_groups(&s->ext.supportedgroups,
&s->ext.supportedgroups_len, parg, larg);
case SSL_CTRL_SET_GROUPS_LIST:
return tls1_set_groups_list(&s->ext.supportedgroups,
&s->ext.supportedgroups_len, parg);
case SSL_CTRL_GET_SHARED_GROUP:
{
uint16_t id = tls1_shared_group(s, larg);
if (larg != -1) {
const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id);
return ginf == NULL ? 0 : ginf->nid;
}
return id;
}
#endif
case SSL_CTRL_SET_SIGALGS:
return tls1_set_sigalgs(s->cert, parg, larg, 0);
case SSL_CTRL_SET_SIGALGS_LIST:
return tls1_set_sigalgs_list(s->cert, parg, 0);
case SSL_CTRL_SET_CLIENT_SIGALGS:
return tls1_set_sigalgs(s->cert, parg, larg, 1);
case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
return tls1_set_sigalgs_list(s->cert, parg, 1);
case SSL_CTRL_GET_CLIENT_CERT_TYPES:
{
const unsigned char **pctype = parg;
if (s->server || !s->s3->tmp.cert_req)
return 0;
if (pctype)
*pctype = s->s3->tmp.ctype;
return s->s3->tmp.ctype_len;
}
case SSL_CTRL_SET_CLIENT_CERT_TYPES:
if (!s->server)
return 0;
return ssl3_set_req_cert_type(s->cert, parg, larg);
case SSL_CTRL_BUILD_CERT_CHAIN:
return ssl_build_cert_chain(s, NULL, larg);
case SSL_CTRL_SET_VERIFY_CERT_STORE:
return ssl_cert_set_cert_store(s->cert, parg, 0, larg);
case SSL_CTRL_SET_CHAIN_CERT_STORE:
return ssl_cert_set_cert_store(s->cert, parg, 1, larg);
case SSL_CTRL_GET_PEER_SIGNATURE_NID:
if (s->s3->tmp.peer_sigalg == NULL)
return 0;
*(int *)parg = s->s3->tmp.peer_sigalg->hash;
return 1;
- case SSL_CTRL_GET_SERVER_TMP_KEY:
+ case SSL_CTRL_GET_SIGNATURE_NID:
+ if (s->s3->tmp.sigalg == NULL)
+ return 0;
+ *(int *)parg = s->s3->tmp.sigalg->hash;
+ return 1;
+
+ case SSL_CTRL_GET_PEER_TMP_KEY:
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
- if (s->server || s->session == NULL || s->s3->peer_tmp == NULL) {
+ if (s->session == NULL || s->s3->peer_tmp == NULL) {
return 0;
} else {
EVP_PKEY_up_ref(s->s3->peer_tmp);
*(EVP_PKEY **)parg = s->s3->peer_tmp;
return 1;
}
#else
return 0;
#endif
+
+ case SSL_CTRL_GET_TMP_KEY:
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
+ if (s->session == NULL || s->s3->tmp.pkey == NULL) {
+ return 0;
+ } else {
+ EVP_PKEY_up_ref(s->s3->tmp.pkey);
+ *(EVP_PKEY **)parg = s->s3->tmp.pkey;
+ return 1;
+ }
+#else
+ return 0;
+#endif
+
#ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_EC_POINT_FORMATS:
{
SSL_SESSION *sess = s->session;
const unsigned char **pformat = parg;
if (sess == NULL || sess->ext.ecpointformats == NULL)
return 0;
*pformat = sess->ext.ecpointformats;
return (int)sess->ext.ecpointformats_len;
}
#endif
default:
break;
}
return ret;
}
long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void))
{
int ret = 0;
switch (cmd) {
#ifndef OPENSSL_NO_DH
case SSL_CTRL_SET_TMP_DH_CB:
{
s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
}
break;
#endif
case SSL_CTRL_SET_TLSEXT_DEBUG_CB:
s->ext.debug_cb = (void (*)(SSL *, int, int,
const unsigned char *, int, void *))fp;
break;
case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB:
{
s->not_resumable_session_cb = (int (*)(SSL *, int))fp;
}
break;
default:
break;
}
return ret;
}
long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
{
switch (cmd) {
#ifndef OPENSSL_NO_DH
case SSL_CTRL_SET_TMP_DH:
{
DH *dh = (DH *)parg;
EVP_PKEY *pkdh = NULL;
if (dh == NULL) {
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
pkdh = ssl_dh_to_pkey(dh);
if (pkdh == NULL) {
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_DH_KEY_TOO_SMALL);
EVP_PKEY_free(pkdh);
return 1;
}
EVP_PKEY_free(ctx->cert->dh_tmp);
ctx->cert->dh_tmp = pkdh;
return 1;
}
case SSL_CTRL_SET_TMP_DH_CB:
{
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
case SSL_CTRL_SET_DH_AUTO:
ctx->cert->dh_tmp_auto = larg;
return 1;
#endif
#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_TMP_ECDH:
{
const EC_GROUP *group = NULL;
int nid;
if (parg == NULL) {
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
group = EC_KEY_get0_group((const EC_KEY *)parg);
if (group == NULL) {
SSLerr(SSL_F_SSL3_CTX_CTRL, EC_R_MISSING_PARAMETERS);
return 0;
}
nid = EC_GROUP_get_curve_name(group);
if (nid == NID_undef)
return 0;
return tls1_set_groups(&ctx->ext.supportedgroups,
&ctx->ext.supportedgroups_len,
&nid, 1);
}
#endif /* !OPENSSL_NO_EC */
case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
ctx->ext.servername_arg = parg;
break;
case SSL_CTRL_SET_TLSEXT_TICKET_KEYS:
case SSL_CTRL_GET_TLSEXT_TICKET_KEYS:
{
unsigned char *keys = parg;
long tick_keylen = (sizeof(ctx->ext.tick_key_name) +
sizeof(ctx->ext.secure->tick_hmac_key) +
sizeof(ctx->ext.secure->tick_aes_key));
if (keys == NULL)
return tick_keylen;
if (larg != tick_keylen) {
SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
return 0;
}
if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS) {
memcpy(ctx->ext.tick_key_name, keys,
sizeof(ctx->ext.tick_key_name));
memcpy(ctx->ext.secure->tick_hmac_key,
keys + sizeof(ctx->ext.tick_key_name),
sizeof(ctx->ext.secure->tick_hmac_key));
memcpy(ctx->ext.secure->tick_aes_key,
keys + sizeof(ctx->ext.tick_key_name) +
sizeof(ctx->ext.secure->tick_hmac_key),
sizeof(ctx->ext.secure->tick_aes_key));
} else {
memcpy(keys, ctx->ext.tick_key_name,
sizeof(ctx->ext.tick_key_name));
memcpy(keys + sizeof(ctx->ext.tick_key_name),
ctx->ext.secure->tick_hmac_key,
sizeof(ctx->ext.secure->tick_hmac_key));
memcpy(keys + sizeof(ctx->ext.tick_key_name) +
sizeof(ctx->ext.secure->tick_hmac_key),
ctx->ext.secure->tick_aes_key,
sizeof(ctx->ext.secure->tick_aes_key));
}
return 1;
}
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE:
return ctx->ext.status_type;
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE:
ctx->ext.status_type = larg;
break;
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG:
ctx->ext.status_arg = parg;
return 1;
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG:
*(void**)parg = ctx->ext.status_arg;
break;
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB:
*(int (**)(SSL*, void*))parg = ctx->ext.status_cb;
break;
#ifndef OPENSSL_NO_SRP
case SSL_CTRL_SET_TLS_EXT_SRP_USERNAME:
ctx->srp_ctx.srp_Mask |= SSL_kSRP;
OPENSSL_free(ctx->srp_ctx.login);
ctx->srp_ctx.login = NULL;
if (parg == NULL)
break;
if (strlen((const char *)parg) > 255 || strlen((const char *)parg) < 1) {
SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_SRP_USERNAME);
return 0;
}
if ((ctx->srp_ctx.login = OPENSSL_strdup((char *)parg)) == NULL) {
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR);
return 0;
}
break;
case SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD:
ctx->srp_ctx.SRP_give_srp_client_pwd_callback =
srp_password_from_info_cb;
if (ctx->srp_ctx.info != NULL)
OPENSSL_free(ctx->srp_ctx.info);
if ((ctx->srp_ctx.info = BUF_strdup((char *)parg)) == NULL) {
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR);
return 0;
}
break;
case SSL_CTRL_SET_SRP_ARG:
ctx->srp_ctx.srp_Mask |= SSL_kSRP;
ctx->srp_ctx.SRP_cb_arg = parg;
break;
case SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH:
ctx->srp_ctx.strength = larg;
break;
#endif
#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_GROUPS:
return tls1_set_groups(&ctx->ext.supportedgroups,
&ctx->ext.supportedgroups_len,
parg, larg);
case SSL_CTRL_SET_GROUPS_LIST:
return tls1_set_groups_list(&ctx->ext.supportedgroups,
&ctx->ext.supportedgroups_len,
parg);
#endif
case SSL_CTRL_SET_SIGALGS:
return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
case SSL_CTRL_SET_SIGALGS_LIST:
return tls1_set_sigalgs_list(ctx->cert, parg, 0);
case SSL_CTRL_SET_CLIENT_SIGALGS:
return tls1_set_sigalgs(ctx->cert, parg, larg, 1);
case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
return tls1_set_sigalgs_list(ctx->cert, parg, 1);
case SSL_CTRL_SET_CLIENT_CERT_TYPES:
return ssl3_set_req_cert_type(ctx->cert, parg, larg);
case SSL_CTRL_BUILD_CERT_CHAIN:
return ssl_build_cert_chain(NULL, ctx, larg);
case SSL_CTRL_SET_VERIFY_CERT_STORE:
return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg);
case SSL_CTRL_SET_CHAIN_CERT_STORE:
return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg);
/* A Thawte special :-) */
case SSL_CTRL_EXTRA_CHAIN_CERT:
if (ctx->extra_certs == NULL) {
if ((ctx->extra_certs = sk_X509_new_null()) == NULL) {
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (!sk_X509_push(ctx->extra_certs, (X509 *)parg)) {
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
break;
case SSL_CTRL_GET_EXTRA_CHAIN_CERTS:
if (ctx->extra_certs == NULL && larg == 0)
*(STACK_OF(X509) **)parg = ctx->cert->key->chain;
else
*(STACK_OF(X509) **)parg = ctx->extra_certs;
break;
case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS:
sk_X509_pop_free(ctx->extra_certs, X509_free);
ctx->extra_certs = NULL;
break;
case SSL_CTRL_CHAIN:
if (larg)
return ssl_cert_set1_chain(NULL, ctx, (STACK_OF(X509) *)parg);
else
return ssl_cert_set0_chain(NULL, ctx, (STACK_OF(X509) *)parg);
case SSL_CTRL_CHAIN_CERT:
if (larg)
return ssl_cert_add1_chain_cert(NULL, ctx, (X509 *)parg);
else
return ssl_cert_add0_chain_cert(NULL, ctx, (X509 *)parg);
case SSL_CTRL_GET_CHAIN_CERTS:
*(STACK_OF(X509) **)parg = ctx->cert->key->chain;
break;
case SSL_CTRL_SELECT_CURRENT_CERT:
return ssl_cert_select_current(ctx->cert, (X509 *)parg);
case SSL_CTRL_SET_CURRENT_CERT:
return ssl_cert_set_current(ctx->cert, larg);
default:
return 0;
}
return 1;
}
long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
{
switch (cmd) {
#ifndef OPENSSL_NO_DH
case SSL_CTRL_SET_TMP_DH_CB:
{
ctx->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
}
break;
#endif
case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB:
ctx->ext.servername_cb = (int (*)(SSL *, int *, void *))fp;
break;
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB:
ctx->ext.status_cb = (int (*)(SSL *, void *))fp;
break;
case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB:
ctx->ext.ticket_key_cb = (int (*)(SSL *, unsigned char *,
unsigned char *,
EVP_CIPHER_CTX *,
HMAC_CTX *, int))fp;
break;
#ifndef OPENSSL_NO_SRP
case SSL_CTRL_SET_SRP_VERIFY_PARAM_CB:
ctx->srp_ctx.srp_Mask |= SSL_kSRP;
ctx->srp_ctx.SRP_verify_param_callback = (int (*)(SSL *, void *))fp;
break;
case SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB:
ctx->srp_ctx.srp_Mask |= SSL_kSRP;
ctx->srp_ctx.TLS_ext_srp_username_callback =
(int (*)(SSL *, int *, void *))fp;
break;
case SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB:
ctx->srp_ctx.srp_Mask |= SSL_kSRP;
ctx->srp_ctx.SRP_give_srp_client_pwd_callback =
(char *(*)(SSL *, void *))fp;
break;
#endif
case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB:
{
ctx->not_resumable_session_cb = (int (*)(SSL *, int))fp;
}
break;
default:
return 0;
}
return 1;
}
const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id)
{
SSL_CIPHER c;
const SSL_CIPHER *cp;
c.id = id;
cp = OBJ_bsearch_ssl_cipher_id(&c, tls13_ciphers, TLS13_NUM_CIPHERS);
if (cp != NULL)
return cp;
cp = OBJ_bsearch_ssl_cipher_id(&c, ssl3_ciphers, SSL3_NUM_CIPHERS);
if (cp != NULL)
return cp;
return OBJ_bsearch_ssl_cipher_id(&c, ssl3_scsvs, SSL3_NUM_SCSVS);
}
const SSL_CIPHER *ssl3_get_cipher_by_std_name(const char *stdname)
{
SSL_CIPHER *c = NULL, *tbl;
SSL_CIPHER *alltabs[] = {tls13_ciphers, ssl3_ciphers};
size_t i, j, tblsize[] = {TLS13_NUM_CIPHERS, SSL3_NUM_CIPHERS};
/* this is not efficient, necessary to optimize this? */
for (j = 0; j < OSSL_NELEM(alltabs); j++) {
for (i = 0, tbl = alltabs[j]; i < tblsize[j]; i++, tbl++) {
if (tbl->stdname == NULL)
continue;
if (strcmp(stdname, tbl->stdname) == 0) {
c = tbl;
break;
}
}
}
if (c == NULL) {
tbl = ssl3_scsvs;
for (i = 0; i < SSL3_NUM_SCSVS; i++, tbl++) {
if (strcmp(stdname, tbl->stdname) == 0) {
c = tbl;
break;
}
}
}
return c;
}
/*
* This function needs to check if the ciphers required are actually
* available
*/
const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p)
{
return ssl3_get_cipher_by_id(SSL3_CK_CIPHERSUITE_FLAG
| ((uint32_t)p[0] << 8L)
| (uint32_t)p[1]);
}
int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
{
if ((c->id & 0xff000000) != SSL3_CK_CIPHERSUITE_FLAG) {
*len = 0;
return 1;
}
if (!WPACKET_put_bytes_u16(pkt, c->id & 0xffff))
return 0;
*len = 2;
return 1;
}
/*
* ssl3_choose_cipher - choose a cipher from those offered by the client
* @s: SSL connection
* @clnt: ciphers offered by the client
* @srvr: ciphers enabled on the server?
*
* Returns the selected cipher or NULL when no common ciphers.
*/
const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
STACK_OF(SSL_CIPHER) *srvr)
{
const SSL_CIPHER *c, *ret = NULL;
STACK_OF(SSL_CIPHER) *prio, *allow;
int i, ii, ok, prefer_sha256 = 0;
unsigned long alg_k = 0, alg_a = 0, mask_k = 0, mask_a = 0;
const EVP_MD *mdsha256 = EVP_sha256();
#ifndef OPENSSL_NO_CHACHA
STACK_OF(SSL_CIPHER) *prio_chacha = NULL;
#endif
/* Let's see which ciphers we can support */
/*
* Do not set the compare functions, because this may lead to a
* reordering by "id". We want to keep the original ordering. We may pay
* a price in performance during sk_SSL_CIPHER_find(), but would have to
* pay with the price of sk_SSL_CIPHER_dup().
*/
#ifdef CIPHER_DEBUG
fprintf(stderr, "Server has %d from %p:\n", sk_SSL_CIPHER_num(srvr),
(void *)srvr);
for (i = 0; i < sk_SSL_CIPHER_num(srvr); ++i) {
c = sk_SSL_CIPHER_value(srvr, i);
fprintf(stderr, "%p:%s\n", (void *)c, c->name);
}
fprintf(stderr, "Client sent %d from %p:\n", sk_SSL_CIPHER_num(clnt),
(void *)clnt);
for (i = 0; i < sk_SSL_CIPHER_num(clnt); ++i) {
c = sk_SSL_CIPHER_value(clnt, i);
fprintf(stderr, "%p:%s\n", (void *)c, c->name);
}
#endif
/* SUITE-B takes precedence over server preference and ChaCha priortiy */
if (tls1_suiteb(s)) {
prio = srvr;
allow = clnt;
} else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
prio = srvr;
allow = clnt;
#ifndef OPENSSL_NO_CHACHA
/* If ChaCha20 is at the top of the client preference list,
and there are ChaCha20 ciphers in the server list, then
temporarily prioritize all ChaCha20 ciphers in the servers list. */
if (s->options & SSL_OP_PRIORITIZE_CHACHA && sk_SSL_CIPHER_num(clnt) > 0) {
c = sk_SSL_CIPHER_value(clnt, 0);
if (c->algorithm_enc == SSL_CHACHA20POLY1305) {
/* ChaCha20 is client preferred, check server... */
int num = sk_SSL_CIPHER_num(srvr);
int found = 0;
for (i = 0; i < num; i++) {
c = sk_SSL_CIPHER_value(srvr, i);
if (c->algorithm_enc == SSL_CHACHA20POLY1305) {
found = 1;
break;
}
}
if (found) {
prio_chacha = sk_SSL_CIPHER_new_reserve(NULL, num);
/* if reserve fails, then there's likely a memory issue */
if (prio_chacha != NULL) {
/* Put all ChaCha20 at the top, starting with the one we just found */
sk_SSL_CIPHER_push(prio_chacha, c);
for (i++; i < num; i++) {
c = sk_SSL_CIPHER_value(srvr, i);
if (c->algorithm_enc == SSL_CHACHA20POLY1305)
sk_SSL_CIPHER_push(prio_chacha, c);
}
/* Pull in the rest */
for (i = 0; i < num; i++) {
c = sk_SSL_CIPHER_value(srvr, i);
if (c->algorithm_enc != SSL_CHACHA20POLY1305)
sk_SSL_CIPHER_push(prio_chacha, c);
}
prio = prio_chacha;
}
}
}
}
# endif
} else {
prio = clnt;
allow = srvr;
}
if (SSL_IS_TLS13(s)) {
#ifndef OPENSSL_NO_PSK
int j;
/*
* If we allow "old" style PSK callbacks, and we have no certificate (so
* we're not going to succeed without a PSK anyway), and we're in
* TLSv1.3 then the default hash for a PSK is SHA-256 (as per the
* TLSv1.3 spec). Therefore we should prioritise ciphersuites using
* that.
*/
if (s->psk_server_callback != NULL) {
for (j = 0; j < SSL_PKEY_NUM && !ssl_has_cert(s, j); j++);
if (j == SSL_PKEY_NUM) {
/* There are no certificates */
prefer_sha256 = 1;
}
}
#endif
} else {
tls1_set_cert_validity(s);
ssl_set_masks(s);
}
for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
c = sk_SSL_CIPHER_value(prio, i);
/* Skip ciphers not supported by the protocol version */
if (!SSL_IS_DTLS(s) &&
((s->version < c->min_tls) || (s->version > c->max_tls)))
continue;
if (SSL_IS_DTLS(s) &&
(DTLS_VERSION_LT(s->version, c->min_dtls) ||
DTLS_VERSION_GT(s->version, c->max_dtls)))
continue;
/*
* Since TLS 1.3 ciphersuites can be used with any auth or
* key exchange scheme skip tests.
*/
if (!SSL_IS_TLS13(s)) {
mask_k = s->s3->tmp.mask_k;
mask_a = s->s3->tmp.mask_a;
#ifndef OPENSSL_NO_SRP
if (s->srp_ctx.srp_Mask & SSL_kSRP) {
mask_k |= SSL_kSRP;
mask_a |= SSL_aSRP;
}
#endif
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
#ifndef OPENSSL_NO_PSK
/* with PSK there must be server callback set */
if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL)
continue;
#endif /* OPENSSL_NO_PSK */
ok = (alg_k & mask_k) && (alg_a & mask_a);
#ifdef CIPHER_DEBUG
fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k,
alg_a, mask_k, mask_a, (void *)c, c->name);
#endif
#ifndef OPENSSL_NO_EC
/*
* if we are considering an ECC cipher suite that uses an ephemeral
* EC key check it
*/
if (alg_k & SSL_kECDHE)
ok = ok && tls1_check_ec_tmp_key(s, c->id);
#endif /* OPENSSL_NO_EC */
if (!ok)
continue;
}
ii = sk_SSL_CIPHER_find(allow, c);
if (ii >= 0) {
/* Check security callback permits this cipher */
if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
c->strength_bits, 0, (void *)c))
continue;
#if !defined(OPENSSL_NO_EC)
if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)
&& s->s3->is_probably_safari) {
if (!ret)
ret = sk_SSL_CIPHER_value(allow, ii);
continue;
}
#endif
if (prefer_sha256) {
const SSL_CIPHER *tmp = sk_SSL_CIPHER_value(allow, ii);
if (ssl_md(tmp->algorithm2) == mdsha256) {
ret = tmp;
break;
}
if (ret == NULL)
ret = tmp;
continue;
}
ret = sk_SSL_CIPHER_value(allow, ii);
break;
}
}
#ifndef OPENSSL_NO_CHACHA
sk_SSL_CIPHER_free(prio_chacha);
#endif
return ret;
}
int ssl3_get_req_cert_type(SSL *s, WPACKET *pkt)
{
uint32_t alg_k, alg_a = 0;
/* If we have custom certificate types set, use them */
if (s->cert->ctype)
return WPACKET_memcpy(pkt, s->cert->ctype, s->cert->ctype_len);
/* Get mask of algorithms disabled by signature list */
ssl_set_sig_mask(&alg_a, s, SSL_SECOP_SIGALG_MASK);
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
#ifndef OPENSSL_NO_GOST
if (s->version >= TLS1_VERSION && (alg_k & SSL_kGOST))
return WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN)
&& WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_SIGN)
&& WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_512_SIGN);
#endif
if ((s->version == SSL3_VERSION) && (alg_k & SSL_kDHE)) {
#ifndef OPENSSL_NO_DH
# ifndef OPENSSL_NO_RSA
if (!WPACKET_put_bytes_u8(pkt, SSL3_CT_RSA_EPHEMERAL_DH))
return 0;
# endif
# ifndef OPENSSL_NO_DSA
if (!WPACKET_put_bytes_u8(pkt, SSL3_CT_DSS_EPHEMERAL_DH))
return 0;
# endif
#endif /* !OPENSSL_NO_DH */
}
#ifndef OPENSSL_NO_RSA
if (!(alg_a & SSL_aRSA) && !WPACKET_put_bytes_u8(pkt, SSL3_CT_RSA_SIGN))
return 0;
#endif
#ifndef OPENSSL_NO_DSA
if (!(alg_a & SSL_aDSS) && !WPACKET_put_bytes_u8(pkt, SSL3_CT_DSS_SIGN))
return 0;
#endif
#ifndef OPENSSL_NO_EC
/*
* ECDSA certs can be used with RSA cipher suites too so we don't
* need to check for SSL_kECDH or SSL_kECDHE
*/
if (s->version >= TLS1_VERSION
&& !(alg_a & SSL_aECDSA)
&& !WPACKET_put_bytes_u8(pkt, TLS_CT_ECDSA_SIGN))
return 0;
#endif
return 1;
}
static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len)
{
OPENSSL_free(c->ctype);
c->ctype = NULL;
c->ctype_len = 0;
if (p == NULL || len == 0)
return 1;
if (len > 0xff)
return 0;
c->ctype = OPENSSL_memdup(p, len);
if (c->ctype == NULL)
return 0;
c->ctype_len = len;
return 1;
}
int ssl3_shutdown(SSL *s)
{
int ret;
/*
* Don't do anything much if we have not done the handshake or we don't
* want to send messages :-)
*/
if (s->quiet_shutdown || SSL_in_before(s)) {
s->shutdown = (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
return 1;
}
if (!(s->shutdown & SSL_SENT_SHUTDOWN)) {
s->shutdown |= SSL_SENT_SHUTDOWN;
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY);
/*
* our shutdown alert has been sent now, and if it still needs to be
* written, s->s3->alert_dispatch will be true
*/
if (s->s3->alert_dispatch)
return -1; /* return WANT_WRITE */
} else if (s->s3->alert_dispatch) {
/* resend it if not sent */
ret = s->method->ssl_dispatch_alert(s);
if (ret == -1) {
/*
* we only get to return -1 here the 2nd/Nth invocation, we must
* have already signalled return 0 upon a previous invocation,
* return WANT_WRITE
*/
return ret;
}
} else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) {
size_t readbytes;
/*
* If we are waiting for a close from our peer, we are closed
*/
s->method->ssl_read_bytes(s, 0, NULL, NULL, 0, 0, &readbytes);
if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) {
return -1; /* return WANT_READ */
}
}
if ((s->shutdown == (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) &&
!s->s3->alert_dispatch)
return 1;
else
return 0;
}
int ssl3_write(SSL *s, const void *buf, size_t len, size_t *written)
{
clear_sys_error();
if (s->s3->renegotiate)
ssl3_renegotiate_check(s, 0);
return s->method->ssl_write_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len,
written);
}
static int ssl3_read_internal(SSL *s, void *buf, size_t len, int peek,
size_t *readbytes)
{
int ret;
clear_sys_error();
if (s->s3->renegotiate)
ssl3_renegotiate_check(s, 0);
s->s3->in_read_app_data = 1;
ret =
s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf, len,
peek, readbytes);
if ((ret == -1) && (s->s3->in_read_app_data == 2)) {
/*
* ssl3_read_bytes decided to call s->handshake_func, which called
* ssl3_read_bytes to read handshake data. However, ssl3_read_bytes
* actually found application data and thinks that application data
* makes sense here; so disable handshake processing and try to read
* application data again.
*/
ossl_statem_set_in_handshake(s, 1);
ret =
s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf,
len, peek, readbytes);
ossl_statem_set_in_handshake(s, 0);
} else
s->s3->in_read_app_data = 0;
return ret;
}
int ssl3_read(SSL *s, void *buf, size_t len, size_t *readbytes)
{
return ssl3_read_internal(s, buf, len, 0, readbytes);
}
int ssl3_peek(SSL *s, void *buf, size_t len, size_t *readbytes)
{
return ssl3_read_internal(s, buf, len, 1, readbytes);
}
int ssl3_renegotiate(SSL *s)
{
if (s->handshake_func == NULL)
return 1;
s->s3->renegotiate = 1;
return 1;
}
/*
* Check if we are waiting to do a renegotiation and if so whether now is a
* good time to do it. If |initok| is true then we are being called from inside
* the state machine so ignore the result of SSL_in_init(s). Otherwise we
* should not do a renegotiation if SSL_in_init(s) is true. Returns 1 if we
* should do a renegotiation now and sets up the state machine for it. Otherwise
* returns 0.
*/
int ssl3_renegotiate_check(SSL *s, int initok)
{
int ret = 0;
if (s->s3->renegotiate) {
if (!RECORD_LAYER_read_pending(&s->rlayer)
&& !RECORD_LAYER_write_pending(&s->rlayer)
&& (initok || !SSL_in_init(s))) {
/*
* if we are the server, and we have sent a 'RENEGOTIATE'
* message, we need to set the state machine into the renegotiate
* state.
*/
ossl_statem_set_renegotiate(s);
s->s3->renegotiate = 0;
s->s3->num_renegotiations++;
s->s3->total_renegotiations++;
ret = 1;
}
}
return ret;
}
/*
* If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
* handshake macs if required.
*
* If PSK and using SHA384 for TLS < 1.2 switch to default.
*/
long ssl_get_algorithm2(SSL *s)
{
long alg2;
if (s->s3 == NULL || s->s3->tmp.new_cipher == NULL)
return -1;
alg2 = s->s3->tmp.new_cipher->algorithm2;
if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF) {
if (alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF))
return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
} else if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) {
if (alg2 == (SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384))
return SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF;
}
return alg2;
}
/*
* Fill a ClientRandom or ServerRandom field of length len. Returns <= 0 on
* failure, 1 on success.
*/
int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, size_t len,
DOWNGRADE dgrd)
{
int send_time = 0, ret;
if (len < 4)
return 0;
if (server)
send_time = (s->mode & SSL_MODE_SEND_SERVERHELLO_TIME) != 0;
else
send_time = (s->mode & SSL_MODE_SEND_CLIENTHELLO_TIME) != 0;
if (send_time) {
unsigned long Time = (unsigned long)time(NULL);
unsigned char *p = result;
l2n(Time, p);
ret = RAND_bytes(p, len - 4);
} else {
ret = RAND_bytes(result, len);
}
if (ret > 0) {
if (!ossl_assert(sizeof(tls11downgrade) < len)
|| !ossl_assert(sizeof(tls12downgrade) < len))
return 0;
if (dgrd == DOWNGRADE_TO_1_2)
memcpy(result + len - sizeof(tls12downgrade), tls12downgrade,
sizeof(tls12downgrade));
else if (dgrd == DOWNGRADE_TO_1_1)
memcpy(result + len - sizeof(tls11downgrade), tls11downgrade,
sizeof(tls11downgrade));
}
return ret;
}
int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
int free_pms)
{
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
int ret = 0;
if (alg_k & SSL_PSK) {
#ifndef OPENSSL_NO_PSK
unsigned char *pskpms, *t;
size_t psklen = s->s3->tmp.psklen;
size_t pskpmslen;
/* create PSK premaster_secret */
/* For plain PSK "other_secret" is psklen zeroes */
if (alg_k & SSL_kPSK)
pmslen = psklen;
pskpmslen = 4 + pmslen + psklen;
pskpms = OPENSSL_malloc(pskpmslen);
if (pskpms == NULL)
goto err;
t = pskpms;
s2n(pmslen, t);
if (alg_k & SSL_kPSK)
memset(t, 0, pmslen);
else
memcpy(t, pms, pmslen);
t += pmslen;
s2n(psklen, t);
memcpy(t, s->s3->tmp.psk, psklen);
OPENSSL_clear_free(s->s3->tmp.psk, psklen);
s->s3->tmp.psk = NULL;
if (!s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,pskpms, pskpmslen,
&s->session->master_key_length)) {
OPENSSL_clear_free(pskpms, pskpmslen);
/* SSLfatal() already called */
goto err;
}
OPENSSL_clear_free(pskpms, pskpmslen);
#else
/* Should never happen */
goto err;
#endif
} else {
if (!s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key, pms, pmslen,
&s->session->master_key_length)) {
/* SSLfatal() already called */
goto err;
}
}
ret = 1;
err:
if (pms) {
if (free_pms)
OPENSSL_clear_free(pms, pmslen);
else
OPENSSL_cleanse(pms, pmslen);
}
if (s->server == 0)
s->s3->tmp.pms = NULL;
return ret;
}
/* Generate a private key from parameters */
EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
if (pm == NULL)
return NULL;
pctx = EVP_PKEY_CTX_new(pm, NULL);
if (pctx == NULL)
goto err;
if (EVP_PKEY_keygen_init(pctx) <= 0)
goto err;
if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
err:
EVP_PKEY_CTX_free(pctx);
return pkey;
}
#ifndef OPENSSL_NO_EC
/* Generate a private key from a group ID */
EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id);
uint16_t gtype;
if (ginf == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
ERR_R_INTERNAL_ERROR);
goto err;
}
gtype = ginf->flags & TLS_CURVE_TYPE;
if (gtype == TLS_CURVE_CUSTOM)
pctx = EVP_PKEY_CTX_new_id(ginf->nid, NULL);
else
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
if (pctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_keygen_init(pctx) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
ERR_R_EVP_LIB);
goto err;
}
if (gtype != TLS_CURVE_CUSTOM
&& EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
ERR_R_EVP_LIB);
goto err;
}
if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
ERR_R_EVP_LIB);
EVP_PKEY_free(pkey);
pkey = NULL;
}
err:
EVP_PKEY_CTX_free(pctx);
return pkey;
}
/*
* Generate parameters from a group ID
*/
EVP_PKEY *ssl_generate_param_group(uint16_t id)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id);
if (ginf == NULL)
goto err;
if ((ginf->flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) {
pkey = EVP_PKEY_new();
if (pkey != NULL && EVP_PKEY_set_type(pkey, ginf->nid))
return pkey;
EVP_PKEY_free(pkey);
return NULL;
}
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
if (pctx == NULL)
goto err;
if (EVP_PKEY_paramgen_init(pctx) <= 0)
goto err;
if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0)
goto err;
if (EVP_PKEY_paramgen(pctx, &pkey) <= 0) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
err:
EVP_PKEY_CTX_free(pctx);
return pkey;
}
#endif
/* Derive secrets for ECDH/DH */
int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret)
{
int rv = 0;
unsigned char *pms = NULL;
size_t pmslen = 0;
EVP_PKEY_CTX *pctx;
if (privkey == NULL || pubkey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
ERR_R_INTERNAL_ERROR);
return 0;
}
pctx = EVP_PKEY_CTX_new(privkey, NULL);
if (EVP_PKEY_derive_init(pctx) <= 0
|| EVP_PKEY_derive_set_peer(pctx, pubkey) <= 0
|| EVP_PKEY_derive(pctx, NULL, &pmslen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
ERR_R_INTERNAL_ERROR);
goto err;
}
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_derive(pctx, pms, &pmslen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (gensecret) {
/* SSLfatal() called as appropriate in the below functions */
if (SSL_IS_TLS13(s)) {
/*
* If we are resuming then we already generated the early secret
* when we created the ClientHello, so don't recreate it.
*/
if (!s->hit)
rv = tls13_generate_secret(s, ssl_handshake_md(s), NULL, NULL,
0,
(unsigned char *)&s->early_secret);
else
rv = 1;
rv = rv && tls13_generate_handshake_secret(s, pms, pmslen);
} else {
rv = ssl_generate_master_secret(s, pms, pmslen, 0);
}
} else {
/* Save premaster secret */
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
pms = NULL;
rv = 1;
}
err:
OPENSSL_clear_free(pms, pmslen);
EVP_PKEY_CTX_free(pctx);
return rv;
}
#ifndef OPENSSL_NO_DH
EVP_PKEY *ssl_dh_to_pkey(DH *dh)
{
EVP_PKEY *ret;
if (dh == NULL)
return NULL;
ret = EVP_PKEY_new();
if (EVP_PKEY_set1_DH(ret, dh) <= 0) {
EVP_PKEY_free(ret);
return NULL;
}
return ret;
}
#endif
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 52a4a7eaadd2..33145078963d 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -1,1039 +1,1040 @@
/*
* Copyright 1995-2018 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 <stdio.h>
#include <sys/types.h>
#include "internal/nelem.h"
#include "internal/o_dir.h"
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include "internal/refcount.h"
#include "ssl_locl.h"
#include "ssl_cert_table.h"
#include "internal/thread_once.h"
static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid, void *other,
void *ex);
static CRYPTO_ONCE ssl_x509_store_ctx_once = CRYPTO_ONCE_STATIC_INIT;
static volatile int ssl_x509_store_ctx_idx = -1;
DEFINE_RUN_ONCE_STATIC(ssl_x509_store_ctx_init)
{
ssl_x509_store_ctx_idx = X509_STORE_CTX_get_ex_new_index(0,
"SSL for verify callback",
NULL, NULL, NULL);
return ssl_x509_store_ctx_idx >= 0;
}
int SSL_get_ex_data_X509_STORE_CTX_idx(void)
{
if (!RUN_ONCE(&ssl_x509_store_ctx_once, ssl_x509_store_ctx_init))
return -1;
return ssl_x509_store_ctx_idx;
}
CERT *ssl_cert_new(void)
{
CERT *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->key = &(ret->pkeys[SSL_PKEY_RSA]);
ret->references = 1;
ret->sec_cb = ssl_security_default_callback;
ret->sec_level = OPENSSL_TLS_SECURITY_LEVEL;
ret->sec_ex = NULL;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
return ret;
}
CERT *ssl_cert_dup(CERT *cert)
{
CERT *ret = OPENSSL_zalloc(sizeof(*ret));
int i;
if (ret == NULL) {
SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->references = 1;
ret->key = &ret->pkeys[cert->key - cert->pkeys];
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
#ifndef OPENSSL_NO_DH
if (cert->dh_tmp != NULL) {
ret->dh_tmp = cert->dh_tmp;
EVP_PKEY_up_ref(ret->dh_tmp);
}
ret->dh_tmp_cb = cert->dh_tmp_cb;
ret->dh_tmp_auto = cert->dh_tmp_auto;
#endif
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = cert->pkeys + i;
CERT_PKEY *rpk = ret->pkeys + i;
if (cpk->x509 != NULL) {
rpk->x509 = cpk->x509;
X509_up_ref(rpk->x509);
}
if (cpk->privatekey != NULL) {
rpk->privatekey = cpk->privatekey;
EVP_PKEY_up_ref(cpk->privatekey);
}
if (cpk->chain) {
rpk->chain = X509_chain_up_ref(cpk->chain);
if (!rpk->chain) {
SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (cert->pkeys[i].serverinfo != NULL) {
/* Just copy everything. */
ret->pkeys[i].serverinfo =
OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
if (ret->pkeys[i].serverinfo == NULL) {
SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->pkeys[i].serverinfo_length = cert->pkeys[i].serverinfo_length;
memcpy(ret->pkeys[i].serverinfo,
cert->pkeys[i].serverinfo, cert->pkeys[i].serverinfo_length);
}
}
/* Configured sigalgs copied across */
if (cert->conf_sigalgs) {
ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen
* sizeof(*cert->conf_sigalgs));
if (ret->conf_sigalgs == NULL)
goto err;
memcpy(ret->conf_sigalgs, cert->conf_sigalgs,
cert->conf_sigalgslen * sizeof(*cert->conf_sigalgs));
ret->conf_sigalgslen = cert->conf_sigalgslen;
} else
ret->conf_sigalgs = NULL;
if (cert->client_sigalgs) {
ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen
* sizeof(*cert->client_sigalgs));
if (ret->client_sigalgs == NULL)
goto err;
memcpy(ret->client_sigalgs, cert->client_sigalgs,
cert->client_sigalgslen * sizeof(*cert->client_sigalgs));
ret->client_sigalgslen = cert->client_sigalgslen;
} else
ret->client_sigalgs = NULL;
/* Shared sigalgs also NULL */
ret->shared_sigalgs = NULL;
/* Copy any custom client certificate types */
if (cert->ctype) {
ret->ctype = OPENSSL_memdup(cert->ctype, cert->ctype_len);
if (ret->ctype == NULL)
goto err;
ret->ctype_len = cert->ctype_len;
}
ret->cert_flags = cert->cert_flags;
ret->cert_cb = cert->cert_cb;
ret->cert_cb_arg = cert->cert_cb_arg;
if (cert->verify_store) {
X509_STORE_up_ref(cert->verify_store);
ret->verify_store = cert->verify_store;
}
if (cert->chain_store) {
X509_STORE_up_ref(cert->chain_store);
ret->chain_store = cert->chain_store;
}
ret->sec_cb = cert->sec_cb;
ret->sec_level = cert->sec_level;
ret->sec_ex = cert->sec_ex;
if (!custom_exts_copy(&ret->custext, &cert->custext))
goto err;
#ifndef OPENSSL_NO_PSK
if (cert->psk_identity_hint) {
ret->psk_identity_hint = OPENSSL_strdup(cert->psk_identity_hint);
if (ret->psk_identity_hint == NULL)
goto err;
}
#endif
return ret;
err:
ssl_cert_free(ret);
return NULL;
}
/* Free up and clear all certificates and chains */
void ssl_cert_clear_certs(CERT *c)
{
int i;
if (c == NULL)
return;
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = c->pkeys + i;
X509_free(cpk->x509);
cpk->x509 = NULL;
EVP_PKEY_free(cpk->privatekey);
cpk->privatekey = NULL;
sk_X509_pop_free(cpk->chain, X509_free);
cpk->chain = NULL;
OPENSSL_free(cpk->serverinfo);
cpk->serverinfo = NULL;
cpk->serverinfo_length = 0;
}
}
void ssl_cert_free(CERT *c)
{
int i;
if (c == NULL)
return;
CRYPTO_DOWN_REF(&c->references, &i, c->lock);
REF_PRINT_COUNT("CERT", c);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
#ifndef OPENSSL_NO_DH
EVP_PKEY_free(c->dh_tmp);
#endif
ssl_cert_clear_certs(c);
OPENSSL_free(c->conf_sigalgs);
OPENSSL_free(c->client_sigalgs);
OPENSSL_free(c->shared_sigalgs);
OPENSSL_free(c->ctype);
X509_STORE_free(c->verify_store);
X509_STORE_free(c->chain_store);
custom_exts_free(&c->custext);
#ifndef OPENSSL_NO_PSK
OPENSSL_free(c->psk_identity_hint);
#endif
CRYPTO_THREAD_lock_free(c->lock);
OPENSSL_free(c);
}
int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
{
int i, r;
CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
if (!cpk)
return 0;
for (i = 0; i < sk_X509_num(chain); i++) {
r = ssl_security_cert(s, ctx, sk_X509_value(chain, i), 0, 0);
if (r != 1) {
SSLerr(SSL_F_SSL_CERT_SET0_CHAIN, r);
return 0;
}
}
sk_X509_pop_free(cpk->chain, X509_free);
cpk->chain = chain;
return 1;
}
int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
{
STACK_OF(X509) *dchain;
if (!chain)
return ssl_cert_set0_chain(s, ctx, NULL);
dchain = X509_chain_up_ref(chain);
if (!dchain)
return 0;
if (!ssl_cert_set0_chain(s, ctx, dchain)) {
sk_X509_pop_free(dchain, X509_free);
return 0;
}
return 1;
}
int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
{
int r;
CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
if (!cpk)
return 0;
r = ssl_security_cert(s, ctx, x, 0, 0);
if (r != 1) {
SSLerr(SSL_F_SSL_CERT_ADD0_CHAIN_CERT, r);
return 0;
}
if (!cpk->chain)
cpk->chain = sk_X509_new_null();
if (!cpk->chain || !sk_X509_push(cpk->chain, x))
return 0;
return 1;
}
int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
{
if (!ssl_cert_add0_chain_cert(s, ctx, x))
return 0;
X509_up_ref(x);
return 1;
}
int ssl_cert_select_current(CERT *c, X509 *x)
{
int i;
if (x == NULL)
return 0;
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = c->pkeys + i;
if (cpk->x509 == x && cpk->privatekey) {
c->key = cpk;
return 1;
}
}
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = c->pkeys + i;
if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) {
c->key = cpk;
return 1;
}
}
return 0;
}
int ssl_cert_set_current(CERT *c, long op)
{
int i, idx;
if (!c)
return 0;
if (op == SSL_CERT_SET_FIRST)
idx = 0;
else if (op == SSL_CERT_SET_NEXT) {
idx = (int)(c->key - c->pkeys + 1);
if (idx >= SSL_PKEY_NUM)
return 0;
} else
return 0;
for (i = idx; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = c->pkeys + i;
if (cpk->x509 && cpk->privatekey) {
c->key = cpk;
return 1;
}
}
return 0;
}
void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
{
c->cert_cb = cb;
c->cert_cb_arg = arg;
}
int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
{
X509 *x;
int i = 0;
X509_STORE *verify_store;
X509_STORE_CTX *ctx = NULL;
X509_VERIFY_PARAM *param;
if ((sk == NULL) || (sk_X509_num(sk) == 0))
return 0;
if (s->cert->verify_store)
verify_store = s->cert->verify_store;
else
verify_store = s->ctx->cert_store;
ctx = X509_STORE_CTX_new();
if (ctx == NULL) {
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
return 0;
}
x = sk_X509_value(sk, 0);
if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB);
goto end;
}
param = X509_STORE_CTX_get0_param(ctx);
/*
* XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
* point, for now a single @SECLEVEL sets the same policy for TLS crypto
* and PKI authentication.
*/
X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s));
/* Set suite B flags if needed */
X509_STORE_CTX_set_flags(ctx, tls1_suiteb(s));
if (!X509_STORE_CTX_set_ex_data
(ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s)) {
goto end;
}
/* Verify via DANE if enabled */
if (DANETLS_ENABLED(&s->dane))
X509_STORE_CTX_set0_dane(ctx, &s->dane);
/*
* We need to inherit the verify parameters. These can be determined by
* the context: if its a server it will verify SSL client certificates or
* vice versa.
*/
X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
/*
* Anything non-default in "s->param" should overwrite anything in the ctx.
*/
X509_VERIFY_PARAM_set1(param, s->param);
if (s->verify_callback)
X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback);
if (s->ctx->app_verify_callback != NULL)
i = s->ctx->app_verify_callback(ctx, s->ctx->app_verify_arg);
else
i = X509_verify_cert(ctx);
s->verify_result = X509_STORE_CTX_get_error(ctx);
sk_X509_pop_free(s->verified_chain, X509_free);
s->verified_chain = NULL;
if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
if (s->verified_chain == NULL) {
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
i = 0;
}
}
/* Move peername from the store context params to the SSL handle's */
X509_VERIFY_PARAM_move_peername(s->param, param);
end:
X509_STORE_CTX_free(ctx);
return i;
}
static void set0_CA_list(STACK_OF(X509_NAME) **ca_list,
STACK_OF(X509_NAME) *name_list)
{
sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
*ca_list = name_list;
}
STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk)
{
int i;
const int num = sk_X509_NAME_num(sk);
STACK_OF(X509_NAME) *ret;
X509_NAME *name;
ret = sk_X509_NAME_new_reserve(NULL, num);
if (ret == NULL) {
SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (i = 0; i < num; i++) {
name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
if (name == NULL) {
SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
sk_X509_NAME_pop_free(ret, X509_NAME_free);
return NULL;
}
sk_X509_NAME_push(ret, name); /* Cannot fail after reserve call */
}
return ret;
}
void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
{
set0_CA_list(&s->ca_names, name_list);
}
void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
{
set0_CA_list(&ctx->ca_names, name_list);
}
const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx)
{
return ctx->ca_names;
}
const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s)
{
return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names;
}
void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
{
- SSL_CTX_set0_CA_list(ctx, name_list);
+ set0_CA_list(&ctx->client_ca_names, name_list);
}
STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
{
- return ctx->ca_names;
+ return ctx->client_ca_names;
}
void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
{
- SSL_set0_CA_list(s, name_list);
+ set0_CA_list(&s->client_ca_names, name_list);
}
const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s)
{
return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL;
}
STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
{
if (!s->server)
return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL;
- return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names;
+ return s->client_ca_names != NULL ? s->client_ca_names
+ : s->ctx->client_ca_names;
}
static int add_ca_name(STACK_OF(X509_NAME) **sk, const X509 *x)
{
X509_NAME *name;
if (x == NULL)
return 0;
if (*sk == NULL && ((*sk = sk_X509_NAME_new_null()) == NULL))
return 0;
if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL)
return 0;
if (!sk_X509_NAME_push(*sk, name)) {
X509_NAME_free(name);
return 0;
}
return 1;
}
int SSL_add1_to_CA_list(SSL *ssl, const X509 *x)
{
return add_ca_name(&ssl->ca_names, x);
}
int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x)
{
return add_ca_name(&ctx->ca_names, x);
}
/*
* The following two are older names are to be replaced with
* SSL(_CTX)_add1_to_CA_list
*/
int SSL_add_client_CA(SSL *ssl, X509 *x)
{
- return add_ca_name(&ssl->ca_names, x);
+ return add_ca_name(&ssl->client_ca_names, x);
}
int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
{
- return add_ca_name(&ctx->ca_names, x);
+ return add_ca_name(&ctx->client_ca_names, x);
}
static int xname_cmp(const X509_NAME *a, const X509_NAME *b)
{
unsigned char *abuf = NULL, *bbuf = NULL;
int alen, blen, ret;
/* X509_NAME_cmp() itself casts away constness in this way, so
* assume it's safe:
*/
alen = i2d_X509_NAME((X509_NAME *)a, &abuf);
blen = i2d_X509_NAME((X509_NAME *)b, &bbuf);
if (alen < 0 || blen < 0)
ret = -2;
else if (alen != blen)
ret = alen - blen;
else /* alen == blen */
ret = memcmp(abuf, bbuf, alen);
OPENSSL_free(abuf);
OPENSSL_free(bbuf);
return ret;
}
static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
{
return xname_cmp(*a, *b);
}
static unsigned long xname_hash(const X509_NAME *a)
{
return X509_NAME_hash((X509_NAME *)a);
}
/**
* Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
* it doesn't really have anything to do with clients (except that a common use
* for a stack of CAs is to send it to the client). Actually, it doesn't have
* much to do with CAs, either, since it will load any old cert.
* \param file the file containing one or more certs.
* \return a ::STACK containing the certs.
*/
STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
{
BIO *in = BIO_new(BIO_s_file());
X509 *x = NULL;
X509_NAME *xn = NULL;
STACK_OF(X509_NAME) *ret = NULL;
LHASH_OF(X509_NAME) *name_hash = lh_X509_NAME_new(xname_hash, xname_cmp);
if ((name_hash == NULL) || (in == NULL)) {
SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!BIO_read_filename(in, file))
goto err;
for (;;) {
if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
break;
if (ret == NULL) {
ret = sk_X509_NAME_new_null();
if (ret == NULL) {
SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if ((xn = X509_get_subject_name(x)) == NULL)
goto err;
/* check for duplicates */
xn = X509_NAME_dup(xn);
if (xn == NULL)
goto err;
if (lh_X509_NAME_retrieve(name_hash, xn) != NULL) {
/* Duplicate. */
X509_NAME_free(xn);
xn = NULL;
} else {
lh_X509_NAME_insert(name_hash, xn);
if (!sk_X509_NAME_push(ret, xn))
goto err;
}
}
goto done;
err:
X509_NAME_free(xn);
sk_X509_NAME_pop_free(ret, X509_NAME_free);
ret = NULL;
done:
BIO_free(in);
X509_free(x);
lh_X509_NAME_free(name_hash);
if (ret != NULL)
ERR_clear_error();
return ret;
}
/**
* Add a file of certs to a stack.
* \param stack the stack to add to.
* \param file the file to add from. All certs in this file that are not
* already in the stack will be added.
* \return 1 for success, 0 for failure. Note that in the case of failure some
* certs may have been added to \c stack.
*/
int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
const char *file)
{
BIO *in;
X509 *x = NULL;
X509_NAME *xn = NULL;
int ret = 1;
int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b);
oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
in = BIO_new(BIO_s_file());
if (in == NULL) {
SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!BIO_read_filename(in, file))
goto err;
for (;;) {
if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
break;
if ((xn = X509_get_subject_name(x)) == NULL)
goto err;
xn = X509_NAME_dup(xn);
if (xn == NULL)
goto err;
if (sk_X509_NAME_find(stack, xn) >= 0) {
/* Duplicate. */
X509_NAME_free(xn);
} else if (!sk_X509_NAME_push(stack, xn)) {
X509_NAME_free(xn);
goto err;
}
}
ERR_clear_error();
goto done;
err:
ret = 0;
done:
BIO_free(in);
X509_free(x);
(void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
return ret;
}
/**
* Add a directory of certs to a stack.
* \param stack the stack to append to.
* \param dir the directory to append from. All files in this directory will be
* examined as potential certs. Any that are acceptable to
* SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be
* included.
* \return 1 for success, 0 for failure. Note that in the case of failure some
* certs may have been added to \c stack.
*/
int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
const char *dir)
{
OPENSSL_DIR_CTX *d = NULL;
const char *filename;
int ret = 0;
/* Note that a side effect is that the CAs will be sorted by name */
while ((filename = OPENSSL_DIR_read(&d, dir))) {
char buf[1024];
int r;
if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,
SSL_R_PATH_TOO_LONG);
goto err;
}
#ifdef OPENSSL_SYS_VMS
r = BIO_snprintf(buf, sizeof(buf), "%s%s", dir, filename);
#else
r = BIO_snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
#endif
if (r <= 0 || r >= (int)sizeof(buf))
goto err;
if (!SSL_add_file_cert_subjects_to_stack(stack, buf))
goto err;
}
if (errno) {
SYSerr(SYS_F_OPENDIR, get_last_sys_error());
ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
goto err;
}
ret = 1;
err:
if (d)
OPENSSL_DIR_end(&d);
return ret;
}
/* Build a certificate chain for current certificate */
int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
{
CERT *c = s ? s->cert : ctx->cert;
CERT_PKEY *cpk = c->key;
X509_STORE *chain_store = NULL;
X509_STORE_CTX *xs_ctx = NULL;
STACK_OF(X509) *chain = NULL, *untrusted = NULL;
X509 *x;
int i, rv = 0;
if (!cpk->x509) {
SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
goto err;
}
/* Rearranging and check the chain: add everything to a store */
if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
chain_store = X509_STORE_new();
if (chain_store == NULL)
goto err;
for (i = 0; i < sk_X509_num(cpk->chain); i++) {
x = sk_X509_value(cpk->chain, i);
if (!X509_STORE_add_cert(chain_store, x))
goto err;
}
/* Add EE cert too: it might be self signed */
if (!X509_STORE_add_cert(chain_store, cpk->x509))
goto err;
} else {
if (c->chain_store)
chain_store = c->chain_store;
else if (s)
chain_store = s->ctx->cert_store;
else
chain_store = ctx->cert_store;
if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
untrusted = cpk->chain;
}
xs_ctx = X509_STORE_CTX_new();
if (xs_ctx == NULL) {
SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!X509_STORE_CTX_init(xs_ctx, chain_store, cpk->x509, untrusted)) {
SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
goto err;
}
/* Set suite B flags if needed */
X509_STORE_CTX_set_flags(xs_ctx,
c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
i = X509_verify_cert(xs_ctx);
if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
ERR_clear_error();
i = 1;
rv = 2;
}
if (i > 0)
chain = X509_STORE_CTX_get1_chain(xs_ctx);
if (i <= 0) {
SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
i = X509_STORE_CTX_get_error(xs_ctx);
ERR_add_error_data(2, "Verify error:",
X509_verify_cert_error_string(i));
goto err;
}
/* Remove EE certificate from chain */
x = sk_X509_shift(chain);
X509_free(x);
if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) {
if (sk_X509_num(chain) > 0) {
/* See if last cert is self signed */
x = sk_X509_value(chain, sk_X509_num(chain) - 1);
if (X509_get_extension_flags(x) & EXFLAG_SS) {
x = sk_X509_pop(chain);
X509_free(x);
}
}
}
/*
* Check security level of all CA certificates: EE will have been checked
* already.
*/
for (i = 0; i < sk_X509_num(chain); i++) {
x = sk_X509_value(chain, i);
rv = ssl_security_cert(s, ctx, x, 0, 0);
if (rv != 1) {
SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, rv);
sk_X509_pop_free(chain, X509_free);
rv = 0;
goto err;
}
}
sk_X509_pop_free(cpk->chain, X509_free);
cpk->chain = chain;
if (rv == 0)
rv = 1;
err:
if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
X509_STORE_free(chain_store);
X509_STORE_CTX_free(xs_ctx);
return rv;
}
int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref)
{
X509_STORE **pstore;
if (chain)
pstore = &c->chain_store;
else
pstore = &c->verify_store;
X509_STORE_free(*pstore);
*pstore = store;
if (ref && store)
X509_STORE_up_ref(store);
return 1;
}
static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid, void *other,
void *ex)
{
int level, minbits;
static const int minbits_table[5] = { 80, 112, 128, 192, 256 };
if (ctx)
level = SSL_CTX_get_security_level(ctx);
else
level = SSL_get_security_level(s);
if (level <= 0) {
/*
* No EDH keys weaker than 1024-bits even at level 0, otherwise,
* anything goes.
*/
if (op == SSL_SECOP_TMP_DH && bits < 80)
return 0;
return 1;
}
if (level > 5)
level = 5;
minbits = minbits_table[level - 1];
switch (op) {
case SSL_SECOP_CIPHER_SUPPORTED:
case SSL_SECOP_CIPHER_SHARED:
case SSL_SECOP_CIPHER_CHECK:
{
const SSL_CIPHER *c = other;
/* No ciphers below security level */
if (bits < minbits)
return 0;
/* No unauthenticated ciphersuites */
if (c->algorithm_auth & SSL_aNULL)
return 0;
/* No MD5 mac ciphersuites */
if (c->algorithm_mac & SSL_MD5)
return 0;
/* SHA1 HMAC is 160 bits of security */
if (minbits > 160 && c->algorithm_mac & SSL_SHA1)
return 0;
/* Level 2: no RC4 */
if (level >= 2 && c->algorithm_enc == SSL_RC4)
return 0;
/* Level 3: forward secure ciphersuites only */
- if (level >= 3 && (c->min_tls != TLS1_3_VERSION ||
- !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH))))
+ if (level >= 3 && c->min_tls != TLS1_3_VERSION &&
+ !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)))
return 0;
break;
}
case SSL_SECOP_VERSION:
if (!SSL_IS_DTLS(s)) {
/* SSLv3 not allowed at level 2 */
if (nid <= SSL3_VERSION && level >= 2)
return 0;
/* TLS v1.1 and above only for level 3 */
if (nid <= TLS1_VERSION && level >= 3)
return 0;
/* TLS v1.2 only for level 4 and above */
if (nid <= TLS1_1_VERSION && level >= 4)
return 0;
} else {
/* DTLS v1.2 only for level 4 and above */
if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4)
return 0;
}
break;
case SSL_SECOP_COMPRESSION:
if (level >= 2)
return 0;
break;
case SSL_SECOP_TICKET:
if (level >= 3)
return 0;
break;
default:
if (bits < minbits)
return 0;
}
return 1;
}
int ssl_security(const SSL *s, int op, int bits, int nid, void *other)
{
return s->cert->sec_cb(s, NULL, op, bits, nid, other, s->cert->sec_ex);
}
int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other)
{
return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other,
ctx->cert->sec_ex);
}
int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
{
size_t i;
for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
if (ssl_cert_info[i].nid == nid) {
*pidx = i;
return 1;
}
}
return 0;
}
const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
{
int nid = EVP_PKEY_id(pk);
size_t tmpidx;
if (nid == NID_undef)
return NULL;
if (!ssl_cert_lookup_by_nid(nid, &tmpidx))
return NULL;
if (pidx != NULL)
*pidx = tmpidx;
return &ssl_cert_info[tmpidx];
}
const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx)
{
if (idx >= OSSL_NELEM(ssl_cert_info))
return NULL;
return &ssl_cert_info[idx];
}
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index b60cc79a2f53..14066d0ea451 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1,2161 +1,2161 @@
/*
* Copyright 1995-2018 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 <ctype.h>
#include <openssl/objects.h>
#include <openssl/comp.h>
#include <openssl/engine.h>
#include <openssl/crypto.h>
#include <openssl/conf.h>
#include "internal/nelem.h"
#include "ssl_locl.h"
#include "internal/thread_once.h"
#include "internal/cryptlib.h"
#define SSL_ENC_DES_IDX 0
#define SSL_ENC_3DES_IDX 1
#define SSL_ENC_RC4_IDX 2
#define SSL_ENC_RC2_IDX 3
#define SSL_ENC_IDEA_IDX 4
#define SSL_ENC_NULL_IDX 5
#define SSL_ENC_AES128_IDX 6
#define SSL_ENC_AES256_IDX 7
#define SSL_ENC_CAMELLIA128_IDX 8
#define SSL_ENC_CAMELLIA256_IDX 9
#define SSL_ENC_GOST89_IDX 10
#define SSL_ENC_SEED_IDX 11
#define SSL_ENC_AES128GCM_IDX 12
#define SSL_ENC_AES256GCM_IDX 13
#define SSL_ENC_AES128CCM_IDX 14
#define SSL_ENC_AES256CCM_IDX 15
#define SSL_ENC_AES128CCM8_IDX 16
#define SSL_ENC_AES256CCM8_IDX 17
#define SSL_ENC_GOST8912_IDX 18
#define SSL_ENC_CHACHA_IDX 19
#define SSL_ENC_ARIA128GCM_IDX 20
#define SSL_ENC_ARIA256GCM_IDX 21
#define SSL_ENC_NUM_IDX 22
/* NB: make sure indices in these tables match values above */
typedef struct {
uint32_t mask;
int nid;
} ssl_cipher_table;
/* Table of NIDs for each cipher */
static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
{SSL_DES, NID_des_cbc}, /* SSL_ENC_DES_IDX 0 */
{SSL_3DES, NID_des_ede3_cbc}, /* SSL_ENC_3DES_IDX 1 */
{SSL_RC4, NID_rc4}, /* SSL_ENC_RC4_IDX 2 */
{SSL_RC2, NID_rc2_cbc}, /* SSL_ENC_RC2_IDX 3 */
{SSL_IDEA, NID_idea_cbc}, /* SSL_ENC_IDEA_IDX 4 */
{SSL_eNULL, NID_undef}, /* SSL_ENC_NULL_IDX 5 */
{SSL_AES128, NID_aes_128_cbc}, /* SSL_ENC_AES128_IDX 6 */
{SSL_AES256, NID_aes_256_cbc}, /* SSL_ENC_AES256_IDX 7 */
{SSL_CAMELLIA128, NID_camellia_128_cbc}, /* SSL_ENC_CAMELLIA128_IDX 8 */
{SSL_CAMELLIA256, NID_camellia_256_cbc}, /* SSL_ENC_CAMELLIA256_IDX 9 */
{SSL_eGOST2814789CNT, NID_gost89_cnt}, /* SSL_ENC_GOST89_IDX 10 */
{SSL_SEED, NID_seed_cbc}, /* SSL_ENC_SEED_IDX 11 */
{SSL_AES128GCM, NID_aes_128_gcm}, /* SSL_ENC_AES128GCM_IDX 12 */
{SSL_AES256GCM, NID_aes_256_gcm}, /* SSL_ENC_AES256GCM_IDX 13 */
{SSL_AES128CCM, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM_IDX 14 */
{SSL_AES256CCM, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM_IDX 15 */
{SSL_AES128CCM8, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM8_IDX 16 */
{SSL_AES256CCM8, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM8_IDX 17 */
{SSL_eGOST2814789CNT12, NID_gost89_cnt_12}, /* SSL_ENC_GOST8912_IDX 18 */
{SSL_CHACHA20POLY1305, NID_chacha20_poly1305}, /* SSL_ENC_CHACHA_IDX 19 */
{SSL_ARIA128GCM, NID_aria_128_gcm}, /* SSL_ENC_ARIA128GCM_IDX 20 */
{SSL_ARIA256GCM, NID_aria_256_gcm}, /* SSL_ENC_ARIA256GCM_IDX 21 */
};
static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX];
#define SSL_COMP_NULL_IDX 0
#define SSL_COMP_ZLIB_IDX 1
#define SSL_COMP_NUM_IDX 2
static STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
#ifndef OPENSSL_NO_COMP
static CRYPTO_ONCE ssl_load_builtin_comp_once = CRYPTO_ONCE_STATIC_INIT;
#endif
/*
* Constant SSL_MAX_DIGEST equal to size of digests array should be defined
* in the ssl_locl.h
*/
#define SSL_MD_NUM_IDX SSL_MAX_DIGEST
/* NB: make sure indices in this table matches values above */
static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = {
{SSL_MD5, NID_md5}, /* SSL_MD_MD5_IDX 0 */
{SSL_SHA1, NID_sha1}, /* SSL_MD_SHA1_IDX 1 */
{SSL_GOST94, NID_id_GostR3411_94}, /* SSL_MD_GOST94_IDX 2 */
{SSL_GOST89MAC, NID_id_Gost28147_89_MAC}, /* SSL_MD_GOST89MAC_IDX 3 */
{SSL_SHA256, NID_sha256}, /* SSL_MD_SHA256_IDX 4 */
{SSL_SHA384, NID_sha384}, /* SSL_MD_SHA384_IDX 5 */
{SSL_GOST12_256, NID_id_GostR3411_2012_256}, /* SSL_MD_GOST12_256_IDX 6 */
{SSL_GOST89MAC12, NID_gost_mac_12}, /* SSL_MD_GOST89MAC12_IDX 7 */
{SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */
{0, NID_md5_sha1}, /* SSL_MD_MD5_SHA1_IDX 9 */
{0, NID_sha224}, /* SSL_MD_SHA224_IDX 10 */
{0, NID_sha512} /* SSL_MD_SHA512_IDX 11 */
};
static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
/* *INDENT-OFF* */
static const ssl_cipher_table ssl_cipher_table_kx[] = {
{SSL_kRSA, NID_kx_rsa},
{SSL_kECDHE, NID_kx_ecdhe},
{SSL_kDHE, NID_kx_dhe},
{SSL_kECDHEPSK, NID_kx_ecdhe_psk},
{SSL_kDHEPSK, NID_kx_dhe_psk},
{SSL_kRSAPSK, NID_kx_rsa_psk},
{SSL_kPSK, NID_kx_psk},
{SSL_kSRP, NID_kx_srp},
{SSL_kGOST, NID_kx_gost},
{SSL_kANY, NID_kx_any}
};
static const ssl_cipher_table ssl_cipher_table_auth[] = {
{SSL_aRSA, NID_auth_rsa},
{SSL_aECDSA, NID_auth_ecdsa},
{SSL_aPSK, NID_auth_psk},
{SSL_aDSS, NID_auth_dss},
{SSL_aGOST01, NID_auth_gost01},
{SSL_aGOST12, NID_auth_gost12},
{SSL_aSRP, NID_auth_srp},
{SSL_aNULL, NID_auth_null},
{SSL_aANY, NID_auth_any}
};
/* *INDENT-ON* */
/* Utility function for table lookup */
static int ssl_cipher_info_find(const ssl_cipher_table * table,
size_t table_cnt, uint32_t mask)
{
size_t i;
for (i = 0; i < table_cnt; i++, table++) {
if (table->mask == mask)
return (int)i;
}
return -1;
}
#define ssl_cipher_info_lookup(table, x) \
ssl_cipher_info_find(table, OSSL_NELEM(table), x)
/*
* PKEY_TYPE for GOST89MAC is known in advance, but, because implementation
* is engine-provided, we'll fill it only if corresponding EVP_PKEY_METHOD is
* found
*/
static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = {
/* MD5, SHA, GOST94, MAC89 */
EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
/* SHA256, SHA384, GOST2012_256, MAC89-12 */
EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
/* GOST2012_512 */
EVP_PKEY_HMAC,
};
static size_t ssl_mac_secret_size[SSL_MD_NUM_IDX];
#define CIPHER_ADD 1
#define CIPHER_KILL 2
#define CIPHER_DEL 3
#define CIPHER_ORD 4
#define CIPHER_SPECIAL 5
/*
* Bump the ciphers to the top of the list.
* This rule isn't currently supported by the public cipherstring API.
*/
#define CIPHER_BUMP 6
typedef struct cipher_order_st {
const SSL_CIPHER *cipher;
int active;
int dead;
struct cipher_order_st *next, *prev;
} CIPHER_ORDER;
static const SSL_CIPHER cipher_aliases[] = {
/* "ALL" doesn't include eNULL (must be specifically enabled) */
{0, SSL_TXT_ALL, NULL, 0, 0, 0, ~SSL_eNULL},
/* "COMPLEMENTOFALL" */
{0, SSL_TXT_CMPALL, NULL, 0, 0, 0, SSL_eNULL},
/*
* "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in
* ALL!)
*/
{0, SSL_TXT_CMPDEF, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_NOT_DEFAULT},
/*
* key exchange aliases (some of those using only a single bit here
* combine multiple key exchange algs according to the RFCs, e.g. kDHE
* combines DHE_DSS and DHE_RSA)
*/
{0, SSL_TXT_kRSA, NULL, 0, SSL_kRSA},
{0, SSL_TXT_kEDH, NULL, 0, SSL_kDHE},
{0, SSL_TXT_kDHE, NULL, 0, SSL_kDHE},
{0, SSL_TXT_DH, NULL, 0, SSL_kDHE},
{0, SSL_TXT_kEECDH, NULL, 0, SSL_kECDHE},
{0, SSL_TXT_kECDHE, NULL, 0, SSL_kECDHE},
{0, SSL_TXT_ECDH, NULL, 0, SSL_kECDHE},
{0, SSL_TXT_kPSK, NULL, 0, SSL_kPSK},
{0, SSL_TXT_kRSAPSK, NULL, 0, SSL_kRSAPSK},
{0, SSL_TXT_kECDHEPSK, NULL, 0, SSL_kECDHEPSK},
{0, SSL_TXT_kDHEPSK, NULL, 0, SSL_kDHEPSK},
{0, SSL_TXT_kSRP, NULL, 0, SSL_kSRP},
{0, SSL_TXT_kGOST, NULL, 0, SSL_kGOST},
/* server authentication aliases */
{0, SSL_TXT_aRSA, NULL, 0, 0, SSL_aRSA},
{0, SSL_TXT_aDSS, NULL, 0, 0, SSL_aDSS},
{0, SSL_TXT_DSS, NULL, 0, 0, SSL_aDSS},
{0, SSL_TXT_aNULL, NULL, 0, 0, SSL_aNULL},
{0, SSL_TXT_aECDSA, NULL, 0, 0, SSL_aECDSA},
{0, SSL_TXT_ECDSA, NULL, 0, 0, SSL_aECDSA},
{0, SSL_TXT_aPSK, NULL, 0, 0, SSL_aPSK},
{0, SSL_TXT_aGOST01, NULL, 0, 0, SSL_aGOST01},
{0, SSL_TXT_aGOST12, NULL, 0, 0, SSL_aGOST12},
{0, SSL_TXT_aGOST, NULL, 0, 0, SSL_aGOST01 | SSL_aGOST12},
{0, SSL_TXT_aSRP, NULL, 0, 0, SSL_aSRP},
/* aliases combining key exchange and server authentication */
{0, SSL_TXT_EDH, NULL, 0, SSL_kDHE, ~SSL_aNULL},
{0, SSL_TXT_DHE, NULL, 0, SSL_kDHE, ~SSL_aNULL},
{0, SSL_TXT_EECDH, NULL, 0, SSL_kECDHE, ~SSL_aNULL},
{0, SSL_TXT_ECDHE, NULL, 0, SSL_kECDHE, ~SSL_aNULL},
{0, SSL_TXT_NULL, NULL, 0, 0, 0, SSL_eNULL},
{0, SSL_TXT_RSA, NULL, 0, SSL_kRSA, SSL_aRSA},
{0, SSL_TXT_ADH, NULL, 0, SSL_kDHE, SSL_aNULL},
{0, SSL_TXT_AECDH, NULL, 0, SSL_kECDHE, SSL_aNULL},
{0, SSL_TXT_PSK, NULL, 0, SSL_PSK},
{0, SSL_TXT_SRP, NULL, 0, SSL_kSRP},
/* symmetric encryption aliases */
{0, SSL_TXT_3DES, NULL, 0, 0, 0, SSL_3DES},
{0, SSL_TXT_RC4, NULL, 0, 0, 0, SSL_RC4},
{0, SSL_TXT_RC2, NULL, 0, 0, 0, SSL_RC2},
{0, SSL_TXT_IDEA, NULL, 0, 0, 0, SSL_IDEA},
{0, SSL_TXT_SEED, NULL, 0, 0, 0, SSL_SEED},
{0, SSL_TXT_eNULL, NULL, 0, 0, 0, SSL_eNULL},
{0, SSL_TXT_GOST, NULL, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12},
{0, SSL_TXT_AES128, NULL, 0, 0, 0,
SSL_AES128 | SSL_AES128GCM | SSL_AES128CCM | SSL_AES128CCM8},
{0, SSL_TXT_AES256, NULL, 0, 0, 0,
SSL_AES256 | SSL_AES256GCM | SSL_AES256CCM | SSL_AES256CCM8},
{0, SSL_TXT_AES, NULL, 0, 0, 0, SSL_AES},
{0, SSL_TXT_AES_GCM, NULL, 0, 0, 0, SSL_AES128GCM | SSL_AES256GCM},
{0, SSL_TXT_AES_CCM, NULL, 0, 0, 0,
SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8},
{0, SSL_TXT_AES_CCM_8, NULL, 0, 0, 0, SSL_AES128CCM8 | SSL_AES256CCM8},
{0, SSL_TXT_CAMELLIA128, NULL, 0, 0, 0, SSL_CAMELLIA128},
{0, SSL_TXT_CAMELLIA256, NULL, 0, 0, 0, SSL_CAMELLIA256},
{0, SSL_TXT_CAMELLIA, NULL, 0, 0, 0, SSL_CAMELLIA},
{0, SSL_TXT_CHACHA20, NULL, 0, 0, 0, SSL_CHACHA20},
{0, SSL_TXT_ARIA, NULL, 0, 0, 0, SSL_ARIA},
{0, SSL_TXT_ARIA_GCM, NULL, 0, 0, 0, SSL_ARIA128GCM | SSL_ARIA256GCM},
{0, SSL_TXT_ARIA128, NULL, 0, 0, 0, SSL_ARIA128GCM},
{0, SSL_TXT_ARIA256, NULL, 0, 0, 0, SSL_ARIA256GCM},
/* MAC aliases */
{0, SSL_TXT_MD5, NULL, 0, 0, 0, 0, SSL_MD5},
{0, SSL_TXT_SHA1, NULL, 0, 0, 0, 0, SSL_SHA1},
{0, SSL_TXT_SHA, NULL, 0, 0, 0, 0, SSL_SHA1},
{0, SSL_TXT_GOST94, NULL, 0, 0, 0, 0, SSL_GOST94},
{0, SSL_TXT_GOST89MAC, NULL, 0, 0, 0, 0, SSL_GOST89MAC | SSL_GOST89MAC12},
{0, SSL_TXT_SHA256, NULL, 0, 0, 0, 0, SSL_SHA256},
{0, SSL_TXT_SHA384, NULL, 0, 0, 0, 0, SSL_SHA384},
{0, SSL_TXT_GOST12, NULL, 0, 0, 0, 0, SSL_GOST12_256},
/* protocol version aliases */
{0, SSL_TXT_SSLV3, NULL, 0, 0, 0, 0, 0, SSL3_VERSION},
{0, SSL_TXT_TLSV1, NULL, 0, 0, 0, 0, 0, TLS1_VERSION},
{0, "TLSv1.0", NULL, 0, 0, 0, 0, 0, TLS1_VERSION},
{0, SSL_TXT_TLSV1_2, NULL, 0, 0, 0, 0, 0, TLS1_2_VERSION},
/* strength classes */
{0, SSL_TXT_LOW, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_LOW},
{0, SSL_TXT_MEDIUM, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_MEDIUM},
{0, SSL_TXT_HIGH, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_HIGH},
/* FIPS 140-2 approved ciphersuite */
{0, SSL_TXT_FIPS, NULL, 0, 0, 0, ~SSL_eNULL, 0, 0, 0, 0, 0, SSL_FIPS},
/* "EDH-" aliases to "DHE-" labels (for backward compatibility) */
{0, SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA, NULL, 0,
SSL_kDHE, SSL_aDSS, SSL_3DES, SSL_SHA1, 0, 0, 0, 0, SSL_HIGH | SSL_FIPS},
{0, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA, NULL, 0,
SSL_kDHE, SSL_aRSA, SSL_3DES, SSL_SHA1, 0, 0, 0, 0, SSL_HIGH | SSL_FIPS},
};
/*
* Search for public key algorithm with given name and return its pkey_id if
* it is available. Otherwise return 0
*/
#ifdef OPENSSL_NO_ENGINE
static int get_optional_pkey_id(const char *pkey_name)
{
const EVP_PKEY_ASN1_METHOD *ameth;
int pkey_id = 0;
ameth = EVP_PKEY_asn1_find_str(NULL, pkey_name, -1);
if (ameth && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
ameth) > 0)
return pkey_id;
return 0;
}
#else
static int get_optional_pkey_id(const char *pkey_name)
{
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *tmpeng = NULL;
int pkey_id = 0;
ameth = EVP_PKEY_asn1_find_str(&tmpeng, pkey_name, -1);
if (ameth) {
if (EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
ameth) <= 0)
pkey_id = 0;
}
ENGINE_finish(tmpeng);
return pkey_id;
}
#endif
/* masks of disabled algorithms */
static uint32_t disabled_enc_mask;
static uint32_t disabled_mac_mask;
static uint32_t disabled_mkey_mask;
static uint32_t disabled_auth_mask;
int ssl_load_ciphers(void)
{
size_t i;
const ssl_cipher_table *t;
disabled_enc_mask = 0;
ssl_sort_cipher_list();
for (i = 0, t = ssl_cipher_table_cipher; i < SSL_ENC_NUM_IDX; i++, t++) {
if (t->nid == NID_undef) {
ssl_cipher_methods[i] = NULL;
} else {
const EVP_CIPHER *cipher = EVP_get_cipherbynid(t->nid);
ssl_cipher_methods[i] = cipher;
if (cipher == NULL)
disabled_enc_mask |= t->mask;
}
}
disabled_mac_mask = 0;
for (i = 0, t = ssl_cipher_table_mac; i < SSL_MD_NUM_IDX; i++, t++) {
const EVP_MD *md = EVP_get_digestbynid(t->nid);
ssl_digest_methods[i] = md;
if (md == NULL) {
disabled_mac_mask |= t->mask;
} else {
int tmpsize = EVP_MD_size(md);
if (!ossl_assert(tmpsize >= 0))
return 0;
ssl_mac_secret_size[i] = tmpsize;
}
}
/* Make sure we can access MD5 and SHA1 */
if (!ossl_assert(ssl_digest_methods[SSL_MD_MD5_IDX] != NULL))
return 0;
if (!ossl_assert(ssl_digest_methods[SSL_MD_SHA1_IDX] != NULL))
return 0;
disabled_mkey_mask = 0;
disabled_auth_mask = 0;
#ifdef OPENSSL_NO_RSA
disabled_mkey_mask |= SSL_kRSA | SSL_kRSAPSK;
disabled_auth_mask |= SSL_aRSA;
#endif
#ifdef OPENSSL_NO_DSA
disabled_auth_mask |= SSL_aDSS;
#endif
#ifdef OPENSSL_NO_DH
disabled_mkey_mask |= SSL_kDHE | SSL_kDHEPSK;
#endif
#ifdef OPENSSL_NO_EC
disabled_mkey_mask |= SSL_kECDHE | SSL_kECDHEPSK;
disabled_auth_mask |= SSL_aECDSA;
#endif
#ifdef OPENSSL_NO_PSK
disabled_mkey_mask |= SSL_PSK;
disabled_auth_mask |= SSL_aPSK;
#endif
#ifdef OPENSSL_NO_SRP
disabled_mkey_mask |= SSL_kSRP;
#endif
/*
* Check for presence of GOST 34.10 algorithms, and if they are not
* present, disable appropriate auth and key exchange
*/
ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac");
if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX])
ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX] = 32;
else
disabled_mac_mask |= SSL_GOST89MAC;
ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] =
get_optional_pkey_id("gost-mac-12");
if (ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX])
ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32;
else
disabled_mac_mask |= SSL_GOST89MAC12;
if (!get_optional_pkey_id("gost2001"))
disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12;
if (!get_optional_pkey_id("gost2012_256"))
disabled_auth_mask |= SSL_aGOST12;
if (!get_optional_pkey_id("gost2012_512"))
disabled_auth_mask |= SSL_aGOST12;
/*
* Disable GOST key exchange if no GOST signature algs are available *
*/
if ((disabled_auth_mask & (SSL_aGOST01 | SSL_aGOST12)) ==
(SSL_aGOST01 | SSL_aGOST12))
disabled_mkey_mask |= SSL_kGOST;
return 1;
}
#ifndef OPENSSL_NO_COMP
static int sk_comp_cmp(const SSL_COMP *const *a, const SSL_COMP *const *b)
{
return ((*a)->id - (*b)->id);
}
DEFINE_RUN_ONCE_STATIC(do_load_builtin_compressions)
{
SSL_COMP *comp = NULL;
COMP_METHOD *method = COMP_zlib();
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
ssl_comp_methods = sk_SSL_COMP_new(sk_comp_cmp);
if (COMP_get_type(method) != NID_undef && ssl_comp_methods != NULL) {
comp = OPENSSL_malloc(sizeof(*comp));
if (comp != NULL) {
comp->method = method;
comp->id = SSL_COMP_ZLIB_IDX;
comp->name = COMP_get_name(method);
sk_SSL_COMP_push(ssl_comp_methods, comp);
sk_SSL_COMP_sort(ssl_comp_methods);
}
}
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
return 1;
}
static int load_builtin_compressions(void)
{
return RUN_ONCE(&ssl_load_builtin_comp_once, do_load_builtin_compressions);
}
#endif
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)
{
int i;
const SSL_CIPHER *c;
c = s->cipher;
if (c == NULL)
return 0;
if (comp != NULL) {
SSL_COMP ctmp;
#ifndef OPENSSL_NO_COMP
if (!load_builtin_compressions()) {
/*
* Currently don't care, since a failure only means that
* ssl_comp_methods is NULL, which is perfectly OK
*/
}
#endif
*comp = NULL;
ctmp.id = s->compress_meth;
if (ssl_comp_methods != NULL) {
i = sk_SSL_COMP_find(ssl_comp_methods, &ctmp);
*comp = sk_SSL_COMP_value(ssl_comp_methods, i);
}
/* If were only interested in comp then return success */
if ((enc == NULL) && (md == NULL))
return 1;
}
if ((enc == NULL) || (md == NULL))
return 0;
i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, c->algorithm_enc);
if (i == -1) {
*enc = NULL;
} else {
if (i == SSL_ENC_NULL_IDX)
*enc = EVP_enc_null();
else
*enc = ssl_cipher_methods[i];
}
i = ssl_cipher_info_lookup(ssl_cipher_table_mac, c->algorithm_mac);
if (i == -1) {
*md = NULL;
if (mac_pkey_type != NULL)
*mac_pkey_type = NID_undef;
if (mac_secret_size != NULL)
*mac_secret_size = 0;
if (c->algorithm_mac == SSL_AEAD)
mac_pkey_type = NULL;
} else {
*md = ssl_digest_methods[i];
if (mac_pkey_type != NULL)
*mac_pkey_type = ssl_mac_pkey_id[i];
if (mac_secret_size != NULL)
*mac_secret_size = ssl_mac_secret_size[i];
}
if ((*enc != NULL) &&
(*md != NULL || (EVP_CIPHER_flags(*enc) & EVP_CIPH_FLAG_AEAD_CIPHER))
&& (!mac_pkey_type || *mac_pkey_type != NID_undef)) {
const EVP_CIPHER *evp;
if (use_etm)
return 1;
if (s->ssl_version >> 8 != TLS1_VERSION_MAJOR ||
s->ssl_version < TLS1_VERSION)
return 1;
if (c->algorithm_enc == SSL_RC4 &&
c->algorithm_mac == SSL_MD5 &&
(evp = EVP_get_cipherbyname("RC4-HMAC-MD5")))
*enc = evp, *md = NULL;
else if (c->algorithm_enc == SSL_AES128 &&
c->algorithm_mac == SSL_SHA1 &&
(evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA1")))
*enc = evp, *md = NULL;
else if (c->algorithm_enc == SSL_AES256 &&
c->algorithm_mac == SSL_SHA1 &&
(evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1")))
*enc = evp, *md = NULL;
else if (c->algorithm_enc == SSL_AES128 &&
c->algorithm_mac == SSL_SHA256 &&
(evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA256")))
*enc = evp, *md = NULL;
else if (c->algorithm_enc == SSL_AES256 &&
c->algorithm_mac == SSL_SHA256 &&
(evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA256")))
*enc = evp, *md = NULL;
return 1;
} else {
return 0;
}
}
const EVP_MD *ssl_md(int idx)
{
idx &= SSL_HANDSHAKE_MAC_MASK;
if (idx < 0 || idx >= SSL_MD_NUM_IDX)
return NULL;
return ssl_digest_methods[idx];
}
const EVP_MD *ssl_handshake_md(SSL *s)
{
return ssl_md(ssl_get_algorithm2(s));
}
const EVP_MD *ssl_prf_md(SSL *s)
{
return ssl_md(ssl_get_algorithm2(s) >> TLS1_PRF_DGST_SHIFT);
}
#define ITEM_SEP(a) \
(((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr,
CIPHER_ORDER **tail)
{
if (curr == *tail)
return;
if (curr == *head)
*head = curr->next;
if (curr->prev != NULL)
curr->prev->next = curr->next;
if (curr->next != NULL)
curr->next->prev = curr->prev;
(*tail)->next = curr;
curr->prev = *tail;
curr->next = NULL;
*tail = curr;
}
static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr,
CIPHER_ORDER **tail)
{
if (curr == *head)
return;
if (curr == *tail)
*tail = curr->prev;
if (curr->next != NULL)
curr->next->prev = curr->prev;
if (curr->prev != NULL)
curr->prev->next = curr->next;
(*head)->prev = curr;
curr->next = *head;
curr->prev = NULL;
*head = curr;
}
static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
int num_of_ciphers,
uint32_t disabled_mkey,
uint32_t disabled_auth,
uint32_t disabled_enc,
uint32_t disabled_mac,
CIPHER_ORDER *co_list,
CIPHER_ORDER **head_p,
CIPHER_ORDER **tail_p)
{
int i, co_list_num;
const SSL_CIPHER *c;
/*
* We have num_of_ciphers descriptions compiled in, depending on the
* method selected (SSLv3, TLSv1 etc).
* These will later be sorted in a linked list with at most num
* entries.
*/
/* Get the initial list of ciphers */
co_list_num = 0; /* actual count of ciphers */
for (i = 0; i < num_of_ciphers; i++) {
c = ssl_method->get_cipher(i);
/* drop those that use any of that is not available */
if (c == NULL || !c->valid)
continue;
if ((c->algorithm_mkey & disabled_mkey) ||
(c->algorithm_auth & disabled_auth) ||
(c->algorithm_enc & disabled_enc) ||
(c->algorithm_mac & disabled_mac))
continue;
if (((ssl_method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) == 0) &&
c->min_tls == 0)
continue;
if (((ssl_method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) != 0) &&
c->min_dtls == 0)
continue;
co_list[co_list_num].cipher = c;
co_list[co_list_num].next = NULL;
co_list[co_list_num].prev = NULL;
co_list[co_list_num].active = 0;
co_list_num++;
}
/*
* Prepare linked list from list entries
*/
if (co_list_num > 0) {
co_list[0].prev = NULL;
if (co_list_num > 1) {
co_list[0].next = &co_list[1];
for (i = 1; i < co_list_num - 1; i++) {
co_list[i].prev = &co_list[i - 1];
co_list[i].next = &co_list[i + 1];
}
co_list[co_list_num - 1].prev = &co_list[co_list_num - 2];
}
co_list[co_list_num - 1].next = NULL;
*head_p = &co_list[0];
*tail_p = &co_list[co_list_num - 1];
}
}
static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
int num_of_group_aliases,
uint32_t disabled_mkey,
uint32_t disabled_auth,
uint32_t disabled_enc,
uint32_t disabled_mac,
CIPHER_ORDER *head)
{
CIPHER_ORDER *ciph_curr;
const SSL_CIPHER **ca_curr;
int i;
uint32_t mask_mkey = ~disabled_mkey;
uint32_t mask_auth = ~disabled_auth;
uint32_t mask_enc = ~disabled_enc;
uint32_t mask_mac = ~disabled_mac;
/*
* First, add the real ciphers as already collected
*/
ciph_curr = head;
ca_curr = ca_list;
while (ciph_curr != NULL) {
*ca_curr = ciph_curr->cipher;
ca_curr++;
ciph_curr = ciph_curr->next;
}
/*
* Now we add the available ones from the cipher_aliases[] table.
* They represent either one or more algorithms, some of which
* in any affected category must be supported (set in enabled_mask),
* or represent a cipher strength value (will be added in any case because algorithms=0).
*/
for (i = 0; i < num_of_group_aliases; i++) {
uint32_t algorithm_mkey = cipher_aliases[i].algorithm_mkey;
uint32_t algorithm_auth = cipher_aliases[i].algorithm_auth;
uint32_t algorithm_enc = cipher_aliases[i].algorithm_enc;
uint32_t algorithm_mac = cipher_aliases[i].algorithm_mac;
if (algorithm_mkey)
if ((algorithm_mkey & mask_mkey) == 0)
continue;
if (algorithm_auth)
if ((algorithm_auth & mask_auth) == 0)
continue;
if (algorithm_enc)
if ((algorithm_enc & mask_enc) == 0)
continue;
if (algorithm_mac)
if ((algorithm_mac & mask_mac) == 0)
continue;
*ca_curr = (SSL_CIPHER *)(cipher_aliases + i);
ca_curr++;
}
*ca_curr = NULL; /* end of list */
}
static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
uint32_t alg_auth, uint32_t alg_enc,
uint32_t alg_mac, int min_tls,
uint32_t algo_strength, int rule,
int32_t strength_bits, CIPHER_ORDER **head_p,
CIPHER_ORDER **tail_p)
{
CIPHER_ORDER *head, *tail, *curr, *next, *last;
const SSL_CIPHER *cp;
int reverse = 0;
#ifdef CIPHER_DEBUG
fprintf(stderr,
"Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls,
algo_strength, strength_bits);
#endif
if (rule == CIPHER_DEL || rule == CIPHER_BUMP)
reverse = 1; /* needed to maintain sorting between currently
* deleted ciphers */
head = *head_p;
tail = *tail_p;
if (reverse) {
next = tail;
last = head;
} else {
next = head;
last = tail;
}
curr = NULL;
for (;;) {
if (curr == last)
break;
curr = next;
if (curr == NULL)
break;
next = reverse ? curr->prev : curr->next;
cp = curr->cipher;
/*
* Selection criteria is either the value of strength_bits
* or the algorithms used.
*/
if (strength_bits >= 0) {
if (strength_bits != cp->strength_bits)
continue;
} else {
#ifdef CIPHER_DEBUG
fprintf(stderr,
"\nName: %s:\nAlgo = %08x/%08x/%08x/%08x/%08x Algo_strength = %08x\n",
cp->name, cp->algorithm_mkey, cp->algorithm_auth,
cp->algorithm_enc, cp->algorithm_mac, cp->min_tls,
cp->algo_strength);
#endif
if (cipher_id != 0 && (cipher_id != cp->id))
continue;
if (alg_mkey && !(alg_mkey & cp->algorithm_mkey))
continue;
if (alg_auth && !(alg_auth & cp->algorithm_auth))
continue;
if (alg_enc && !(alg_enc & cp->algorithm_enc))
continue;
if (alg_mac && !(alg_mac & cp->algorithm_mac))
continue;
if (min_tls && (min_tls != cp->min_tls))
continue;
if ((algo_strength & SSL_STRONG_MASK)
&& !(algo_strength & SSL_STRONG_MASK & cp->algo_strength))
continue;
if ((algo_strength & SSL_DEFAULT_MASK)
&& !(algo_strength & SSL_DEFAULT_MASK & cp->algo_strength))
continue;
}
#ifdef CIPHER_DEBUG
fprintf(stderr, "Action = %d\n", rule);
#endif
/* add the cipher if it has not been added yet. */
if (rule == CIPHER_ADD) {
/* reverse == 0 */
if (!curr->active) {
ll_append_tail(&head, curr, &tail);
curr->active = 1;
}
}
/* Move the added cipher to this location */
else if (rule == CIPHER_ORD) {
/* reverse == 0 */
if (curr->active) {
ll_append_tail(&head, curr, &tail);
}
} else if (rule == CIPHER_DEL) {
/* reverse == 1 */
if (curr->active) {
/*
* most recently deleted ciphersuites get best positions for
* any future CIPHER_ADD (note that the CIPHER_DEL loop works
* in reverse to maintain the order)
*/
ll_append_head(&head, curr, &tail);
curr->active = 0;
}
} else if (rule == CIPHER_BUMP) {
if (curr->active)
ll_append_head(&head, curr, &tail);
} else if (rule == CIPHER_KILL) {
/* reverse == 0 */
if (head == curr)
head = curr->next;
else
curr->prev->next = curr->next;
if (tail == curr)
tail = curr->prev;
curr->active = 0;
if (curr->next != NULL)
curr->next->prev = curr->prev;
if (curr->prev != NULL)
curr->prev->next = curr->next;
curr->next = NULL;
curr->prev = NULL;
}
}
*head_p = head;
*tail_p = tail;
}
static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
CIPHER_ORDER **tail_p)
{
int32_t max_strength_bits;
int i, *number_uses;
CIPHER_ORDER *curr;
/*
* This routine sorts the ciphers with descending strength. The sorting
* must keep the pre-sorted sequence, so we apply the normal sorting
* routine as '+' movement to the end of the list.
*/
max_strength_bits = 0;
curr = *head_p;
while (curr != NULL) {
if (curr->active && (curr->cipher->strength_bits > max_strength_bits))
max_strength_bits = curr->cipher->strength_bits;
curr = curr->next;
}
number_uses = OPENSSL_zalloc(sizeof(int) * (max_strength_bits + 1));
if (number_uses == NULL) {
SSLerr(SSL_F_SSL_CIPHER_STRENGTH_SORT, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
* Now find the strength_bits values actually used
*/
curr = *head_p;
while (curr != NULL) {
if (curr->active)
number_uses[curr->cipher->strength_bits]++;
curr = curr->next;
}
/*
* Go through the list of used strength_bits values in descending
* order.
*/
for (i = max_strength_bits; i >= 0; i--)
if (number_uses[i] > 0)
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p,
tail_p);
OPENSSL_free(number_uses);
return 1;
}
static int ssl_cipher_process_rulestr(const char *rule_str,
CIPHER_ORDER **head_p,
CIPHER_ORDER **tail_p,
const SSL_CIPHER **ca_list, CERT *c)
{
uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, algo_strength;
int min_tls;
const char *l, *buf;
int j, multi, found, rule, retval, ok, buflen;
uint32_t cipher_id = 0;
char ch;
retval = 1;
l = rule_str;
for ( ; ; ) {
ch = *l;
if (ch == '\0')
break; /* done */
if (ch == '-') {
rule = CIPHER_DEL;
l++;
} else if (ch == '+') {
rule = CIPHER_ORD;
l++;
} else if (ch == '!') {
rule = CIPHER_KILL;
l++;
} else if (ch == '@') {
rule = CIPHER_SPECIAL;
l++;
} else {
rule = CIPHER_ADD;
}
if (ITEM_SEP(ch)) {
l++;
continue;
}
alg_mkey = 0;
alg_auth = 0;
alg_enc = 0;
alg_mac = 0;
min_tls = 0;
algo_strength = 0;
for (;;) {
ch = *l;
buf = l;
buflen = 0;
#ifndef CHARSET_EBCDIC
while (((ch >= 'A') && (ch <= 'Z')) ||
((ch >= '0') && (ch <= '9')) ||
((ch >= 'a') && (ch <= 'z')) ||
(ch == '-') || (ch == '.') || (ch == '='))
#else
while (isalnum((unsigned char)ch) || (ch == '-') || (ch == '.')
|| (ch == '='))
#endif
{
ch = *(++l);
buflen++;
}
if (buflen == 0) {
/*
* We hit something we cannot deal with,
* it is no command or separator nor
* alphanumeric, so we call this an error.
*/
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
retval = found = 0;
l++;
break;
}
if (rule == CIPHER_SPECIAL) {
found = 0; /* unused -- avoid compiler warning */
break; /* special treatment */
}
/* check for multi-part specification */
if (ch == '+') {
multi = 1;
l++;
} else {
multi = 0;
}
/*
* Now search for the cipher alias in the ca_list. Be careful
* with the strncmp, because the "buflen" limitation
* will make the rule "ADH:SOME" and the cipher
* "ADH-MY-CIPHER" look like a match for buflen=3.
* So additionally check whether the cipher name found
* has the correct length. We can save a strlen() call:
* just checking for the '\0' at the right place is
* sufficient, we have to strncmp() anyway. (We cannot
* use strcmp(), because buf is not '\0' terminated.)
*/
j = found = 0;
cipher_id = 0;
while (ca_list[j]) {
if (strncmp(buf, ca_list[j]->name, buflen) == 0
&& (ca_list[j]->name[buflen] == '\0')) {
found = 1;
break;
} else
j++;
}
if (!found)
break; /* ignore this entry */
if (ca_list[j]->algorithm_mkey) {
if (alg_mkey) {
alg_mkey &= ca_list[j]->algorithm_mkey;
if (!alg_mkey) {
found = 0;
break;
}
} else {
alg_mkey = ca_list[j]->algorithm_mkey;
}
}
if (ca_list[j]->algorithm_auth) {
if (alg_auth) {
alg_auth &= ca_list[j]->algorithm_auth;
if (!alg_auth) {
found = 0;
break;
}
} else {
alg_auth = ca_list[j]->algorithm_auth;
}
}
if (ca_list[j]->algorithm_enc) {
if (alg_enc) {
alg_enc &= ca_list[j]->algorithm_enc;
if (!alg_enc) {
found = 0;
break;
}
} else {
alg_enc = ca_list[j]->algorithm_enc;
}
}
if (ca_list[j]->algorithm_mac) {
if (alg_mac) {
alg_mac &= ca_list[j]->algorithm_mac;
if (!alg_mac) {
found = 0;
break;
}
} else {
alg_mac = ca_list[j]->algorithm_mac;
}
}
if (ca_list[j]->algo_strength & SSL_STRONG_MASK) {
if (algo_strength & SSL_STRONG_MASK) {
algo_strength &=
(ca_list[j]->algo_strength & SSL_STRONG_MASK) |
~SSL_STRONG_MASK;
if (!(algo_strength & SSL_STRONG_MASK)) {
found = 0;
break;
}
} else {
algo_strength = ca_list[j]->algo_strength & SSL_STRONG_MASK;
}
}
if (ca_list[j]->algo_strength & SSL_DEFAULT_MASK) {
if (algo_strength & SSL_DEFAULT_MASK) {
algo_strength &=
(ca_list[j]->algo_strength & SSL_DEFAULT_MASK) |
~SSL_DEFAULT_MASK;
if (!(algo_strength & SSL_DEFAULT_MASK)) {
found = 0;
break;
}
} else {
algo_strength |=
ca_list[j]->algo_strength & SSL_DEFAULT_MASK;
}
}
if (ca_list[j]->valid) {
/*
* explicit ciphersuite found; its protocol version does not
* become part of the search pattern!
*/
cipher_id = ca_list[j]->id;
} else {
/*
* not an explicit ciphersuite; only in this case, the
* protocol version is considered part of the search pattern
*/
if (ca_list[j]->min_tls) {
if (min_tls != 0 && min_tls != ca_list[j]->min_tls) {
found = 0;
break;
} else {
min_tls = ca_list[j]->min_tls;
}
}
}
if (!multi)
break;
}
/*
* Ok, we have the rule, now apply it
*/
if (rule == CIPHER_SPECIAL) { /* special command */
ok = 0;
if ((buflen == 8) && strncmp(buf, "STRENGTH", 8) == 0) {
ok = ssl_cipher_strength_sort(head_p, tail_p);
} else if (buflen == 10 && strncmp(buf, "SECLEVEL=", 9) == 0) {
int level = buf[9] - '0';
if (level < 0 || level > 5) {
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
SSL_R_INVALID_COMMAND);
} else {
c->sec_level = level;
ok = 1;
}
} else {
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
}
if (ok == 0)
retval = 0;
/*
* We do not support any "multi" options
* together with "@", so throw away the
* rest of the command, if any left, until
* end or ':' is found.
*/
while ((*l != '\0') && !ITEM_SEP(*l))
l++;
} else if (found) {
ssl_cipher_apply_rule(cipher_id,
alg_mkey, alg_auth, alg_enc, alg_mac,
min_tls, algo_strength, rule, -1, head_p,
tail_p);
} else {
while ((*l != '\0') && !ITEM_SEP(*l))
l++;
}
if (*l == '\0')
break; /* done */
}
return retval;
}
#ifndef OPENSSL_NO_EC
static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
const char **prule_str)
{
unsigned int suiteb_flags = 0, suiteb_comb2 = 0;
if (strncmp(*prule_str, "SUITEB128ONLY", 13) == 0) {
suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS_ONLY;
} else if (strncmp(*prule_str, "SUITEB128C2", 11) == 0) {
suiteb_comb2 = 1;
suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS;
} else if (strncmp(*prule_str, "SUITEB128", 9) == 0) {
suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS;
} else if (strncmp(*prule_str, "SUITEB192", 9) == 0) {
suiteb_flags = SSL_CERT_FLAG_SUITEB_192_LOS;
}
if (suiteb_flags) {
c->cert_flags &= ~SSL_CERT_FLAG_SUITEB_128_LOS;
c->cert_flags |= suiteb_flags;
} else {
suiteb_flags = c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS;
}
if (!suiteb_flags)
return 1;
/* Check version: if TLS 1.2 ciphers allowed we can use Suite B */
if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)) {
SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE);
return 0;
}
# ifndef OPENSSL_NO_EC
switch (suiteb_flags) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
if (suiteb_comb2)
*prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384";
else
*prule_str =
"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384";
break;
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*prule_str = "ECDHE-ECDSA-AES128-GCM-SHA256";
break;
case SSL_CERT_FLAG_SUITEB_192_LOS:
*prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384";
break;
}
return 1;
# else
SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE);
return 0;
# endif
}
#endif
static int ciphersuite_cb(const char *elem, int len, void *arg)
{
STACK_OF(SSL_CIPHER) *ciphersuites = (STACK_OF(SSL_CIPHER) *)arg;
const SSL_CIPHER *cipher;
/* Arbitrary sized temp buffer for the cipher name. Should be big enough */
char name[80];
if (len > (int)(sizeof(name) - 1)) {
SSLerr(SSL_F_CIPHERSUITE_CB, SSL_R_NO_CIPHER_MATCH);
return 0;
}
memcpy(name, elem, len);
name[len] = '\0';
cipher = ssl3_get_cipher_by_std_name(name);
if (cipher == NULL) {
SSLerr(SSL_F_CIPHERSUITE_CB, SSL_R_NO_CIPHER_MATCH);
return 0;
}
if (!sk_SSL_CIPHER_push(ciphersuites, cipher)) {
SSLerr(SSL_F_CIPHERSUITE_CB, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
-int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str)
+static __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str)
{
STACK_OF(SSL_CIPHER) *newciphers = sk_SSL_CIPHER_new_null();
if (newciphers == NULL)
return 0;
/* Parse the list. We explicitly allow an empty list */
if (*str != '\0'
&& !CONF_parse_list(str, ':', 1, ciphersuite_cb, newciphers)) {
sk_SSL_CIPHER_free(newciphers);
return 0;
}
sk_SSL_CIPHER_free(*currciphers);
*currciphers = newciphers;
return 1;
}
static int update_cipher_list_by_id(STACK_OF(SSL_CIPHER) **cipher_list_by_id,
STACK_OF(SSL_CIPHER) *cipherstack)
{
STACK_OF(SSL_CIPHER) *tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack);
if (tmp_cipher_list == NULL) {
return 0;
}
sk_SSL_CIPHER_free(*cipher_list_by_id);
*cipher_list_by_id = tmp_cipher_list;
(void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id, ssl_cipher_ptr_id_cmp);
sk_SSL_CIPHER_sort(*cipher_list_by_id);
return 1;
}
static int update_cipher_list(STACK_OF(SSL_CIPHER) **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites)
{
int i;
STACK_OF(SSL_CIPHER) *tmp_cipher_list = sk_SSL_CIPHER_dup(*cipher_list);
if (tmp_cipher_list == NULL)
return 0;
/*
* Delete any existing TLSv1.3 ciphersuites. These are always first in the
* list.
*/
while (sk_SSL_CIPHER_num(tmp_cipher_list) > 0
&& sk_SSL_CIPHER_value(tmp_cipher_list, 0)->min_tls
== TLS1_3_VERSION)
sk_SSL_CIPHER_delete(tmp_cipher_list, 0);
/* Insert the new TLSv1.3 ciphersuites */
for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++)
sk_SSL_CIPHER_insert(tmp_cipher_list,
sk_SSL_CIPHER_value(tls13_ciphersuites, i), i);
if (!update_cipher_list_by_id(cipher_list_by_id, tmp_cipher_list))
return 0;
sk_SSL_CIPHER_free(*cipher_list);
*cipher_list = tmp_cipher_list;
return 1;
}
int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str)
{
int ret = set_ciphersuites(&(ctx->tls13_ciphersuites), str);
if (ret && ctx->cipher_list != NULL) {
/* We already have a cipher_list, so we need to update it */
return update_cipher_list(&ctx->cipher_list, &ctx->cipher_list_by_id,
ctx->tls13_ciphersuites);
}
return ret;
}
int SSL_set_ciphersuites(SSL *s, const char *str)
{
int ret = set_ciphersuites(&(s->tls13_ciphersuites), str);
if (ret && s->cipher_list != NULL) {
/* We already have a cipher_list, so we need to update it */
return update_cipher_list(&s->cipher_list, &s->cipher_list_by_id,
s->tls13_ciphersuites);
}
return ret;
}
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)
{
int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i;
uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
STACK_OF(SSL_CIPHER) *cipherstack;
const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
const SSL_CIPHER **ca_list = NULL;
/*
* Return with error if nothing to do.
*/
if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL)
return NULL;
#ifndef OPENSSL_NO_EC
if (!check_suiteb_cipher_list(ssl_method, c, &rule_str))
return NULL;
#endif
/*
* To reduce the work to do we only want to process the compiled
* in algorithms, so we first get the mask of disabled ciphers.
*/
disabled_mkey = disabled_mkey_mask;
disabled_auth = disabled_auth_mask;
disabled_enc = disabled_enc_mask;
disabled_mac = disabled_mac_mask;
/*
* Now we have to collect the available ciphers from the compiled
* in ciphers. We cannot get more than the number compiled in, so
* it is used for allocation.
*/
num_of_ciphers = ssl_method->num_ciphers();
co_list = OPENSSL_malloc(sizeof(*co_list) * num_of_ciphers);
if (co_list == NULL) {
SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
return NULL; /* Failure */
}
ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers,
disabled_mkey, disabled_auth, disabled_enc,
disabled_mac, co_list, &head, &tail);
/* Now arrange all ciphers by preference. */
/*
* Everything else being equal, prefer ephemeral ECDH over other key
* exchange mechanisms.
* For consistency, prefer ECDSA over RSA (though this only matters if the
* server has both certificates, and is using the DEFAULT, or a client
* preference).
*/
ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD,
-1, &head, &tail);
ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head,
&tail);
ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head,
&tail);
/* Within each strength group, we prefer GCM over CHACHA... */
ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1,
&head, &tail);
ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1,
&head, &tail);
/*
* ...and generally, our preferred cipher is AES.
* Note that AEADs will be bumped to take preference after sorting by
* strength.
*/
ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD,
-1, &head, &tail);
/* Temporarily enable everything else for sorting */
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
/* Low priority for MD5 */
ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head,
&tail);
/*
* Move anonymous ciphers to the end. Usually, these will remain
* disabled. (For applications that allow them, they aren't too bad, but
* we prefer authenticated ciphers.)
*/
ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
&tail);
ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
&tail);
ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
&tail);
/* RC4 is sort-of broken -- move to the end */
ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head,
&tail);
/*
* Now sort by symmetric encryption strength. The above ordering remains
* in force within each class
*/
if (!ssl_cipher_strength_sort(&head, &tail)) {
OPENSSL_free(co_list);
return NULL;
}
/*
* Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs.
* TODO(openssl-team): is there an easier way to accomplish all this?
*/
ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1,
&head, &tail);
/*
* Irrespective of strength, enforce the following order:
* (EC)DHE + AEAD > (EC)DHE > rest of AEAD > rest.
* Within each group, ciphers remain sorted by strength and previous
* preference, i.e.,
* 1) ECDHE > DHE
* 2) GCM > CHACHA
* 3) AES > rest
* 4) TLS 1.2 > legacy
*
* Because we now bump ciphers to the top of the list, we proceed in
* reverse order of preference.
*/
ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1,
&head, &tail);
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, 0, 0, 0,
CIPHER_BUMP, -1, &head, &tail);
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0,
CIPHER_BUMP, -1, &head, &tail);
/* Now disable everything (maintaining the ordering!) */
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
/*
* We also need cipher aliases for selecting based on the rule_str.
* There might be two types of entries in the rule_str: 1) names
* of ciphers themselves 2) aliases for groups of ciphers.
* For 1) we need the available ciphers and for 2) the cipher
* groups of cipher_aliases added together in one list (otherwise
* we would be happy with just the cipher_aliases table).
*/
num_of_group_aliases = OSSL_NELEM(cipher_aliases);
num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max);
if (ca_list == NULL) {
OPENSSL_free(co_list);
SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
return NULL; /* Failure */
}
ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
disabled_mkey, disabled_auth, disabled_enc,
disabled_mac, head);
/*
* If the rule_string begins with DEFAULT, apply the default rule
* before using the (possibly available) additional rules.
*/
ok = 1;
rule_p = rule_str;
if (strncmp(rule_str, "DEFAULT", 7) == 0) {
ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST,
&head, &tail, ca_list, c);
rule_p += 7;
if (*rule_p == ':')
rule_p++;
}
if (ok && (strlen(rule_p) > 0))
ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list, c);
OPENSSL_free(ca_list); /* Not needed anymore */
if (!ok) { /* Rule processing failure */
OPENSSL_free(co_list);
return NULL;
}
/*
* Allocate new "cipherstack" for the result, return with error
* if we cannot get one.
*/
if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) {
OPENSSL_free(co_list);
return NULL;
}
/* Add TLSv1.3 ciphers first - we always prefer those if possible */
for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) {
if (!sk_SSL_CIPHER_push(cipherstack,
sk_SSL_CIPHER_value(tls13_ciphersuites, i))) {
sk_SSL_CIPHER_free(cipherstack);
return NULL;
}
}
/*
* The cipher selection for the list is done. The ciphers are added
* to the resulting precedence to the STACK_OF(SSL_CIPHER).
*/
for (curr = head; curr != NULL; curr = curr->next) {
if (curr->active) {
if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
OPENSSL_free(co_list);
sk_SSL_CIPHER_free(cipherstack);
return NULL;
}
#ifdef CIPHER_DEBUG
fprintf(stderr, "<%s>\n", curr->cipher->name);
#endif
}
}
OPENSSL_free(co_list); /* Not needed any longer */
if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) {
sk_SSL_CIPHER_free(cipherstack);
return NULL;
}
sk_SSL_CIPHER_free(*cipher_list);
*cipher_list = cipherstack;
return cipherstack;
}
char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
{
const char *ver;
const char *kx, *au, *enc, *mac;
uint32_t alg_mkey, alg_auth, alg_enc, alg_mac;
static const char *format = "%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n";
if (buf == NULL) {
len = 128;
if ((buf = OPENSSL_malloc(len)) == NULL) {
SSLerr(SSL_F_SSL_CIPHER_DESCRIPTION, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else if (len < 128) {
return NULL;
}
alg_mkey = cipher->algorithm_mkey;
alg_auth = cipher->algorithm_auth;
alg_enc = cipher->algorithm_enc;
alg_mac = cipher->algorithm_mac;
ver = ssl_protocol_to_string(cipher->min_tls);
switch (alg_mkey) {
case SSL_kRSA:
kx = "RSA";
break;
case SSL_kDHE:
kx = "DH";
break;
case SSL_kECDHE:
kx = "ECDH";
break;
case SSL_kPSK:
kx = "PSK";
break;
case SSL_kRSAPSK:
kx = "RSAPSK";
break;
case SSL_kECDHEPSK:
kx = "ECDHEPSK";
break;
case SSL_kDHEPSK:
kx = "DHEPSK";
break;
case SSL_kSRP:
kx = "SRP";
break;
case SSL_kGOST:
kx = "GOST";
break;
case SSL_kANY:
kx = "any";
break;
default:
kx = "unknown";
}
switch (alg_auth) {
case SSL_aRSA:
au = "RSA";
break;
case SSL_aDSS:
au = "DSS";
break;
case SSL_aNULL:
au = "None";
break;
case SSL_aECDSA:
au = "ECDSA";
break;
case SSL_aPSK:
au = "PSK";
break;
case SSL_aSRP:
au = "SRP";
break;
case SSL_aGOST01:
au = "GOST01";
break;
/* New GOST ciphersuites have both SSL_aGOST12 and SSL_aGOST01 bits */
case (SSL_aGOST12 | SSL_aGOST01):
au = "GOST12";
break;
case SSL_aANY:
au = "any";
break;
default:
au = "unknown";
break;
}
switch (alg_enc) {
case SSL_DES:
enc = "DES(56)";
break;
case SSL_3DES:
enc = "3DES(168)";
break;
case SSL_RC4:
enc = "RC4(128)";
break;
case SSL_RC2:
enc = "RC2(128)";
break;
case SSL_IDEA:
enc = "IDEA(128)";
break;
case SSL_eNULL:
enc = "None";
break;
case SSL_AES128:
enc = "AES(128)";
break;
case SSL_AES256:
enc = "AES(256)";
break;
case SSL_AES128GCM:
enc = "AESGCM(128)";
break;
case SSL_AES256GCM:
enc = "AESGCM(256)";
break;
case SSL_AES128CCM:
enc = "AESCCM(128)";
break;
case SSL_AES256CCM:
enc = "AESCCM(256)";
break;
case SSL_AES128CCM8:
enc = "AESCCM8(128)";
break;
case SSL_AES256CCM8:
enc = "AESCCM8(256)";
break;
case SSL_CAMELLIA128:
enc = "Camellia(128)";
break;
case SSL_CAMELLIA256:
enc = "Camellia(256)";
break;
case SSL_ARIA128GCM:
enc = "ARIAGCM(128)";
break;
case SSL_ARIA256GCM:
enc = "ARIAGCM(256)";
break;
case SSL_SEED:
enc = "SEED(128)";
break;
case SSL_eGOST2814789CNT:
case SSL_eGOST2814789CNT12:
enc = "GOST89(256)";
break;
case SSL_CHACHA20POLY1305:
enc = "CHACHA20/POLY1305(256)";
break;
default:
enc = "unknown";
break;
}
switch (alg_mac) {
case SSL_MD5:
mac = "MD5";
break;
case SSL_SHA1:
mac = "SHA1";
break;
case SSL_SHA256:
mac = "SHA256";
break;
case SSL_SHA384:
mac = "SHA384";
break;
case SSL_AEAD:
mac = "AEAD";
break;
case SSL_GOST89MAC:
case SSL_GOST89MAC12:
mac = "GOST89";
break;
case SSL_GOST94:
mac = "GOST94";
break;
case SSL_GOST12_256:
case SSL_GOST12_512:
mac = "GOST2012";
break;
default:
mac = "unknown";
break;
}
BIO_snprintf(buf, len, format, cipher->name, ver, kx, au, enc, mac);
return buf;
}
const char *SSL_CIPHER_get_version(const SSL_CIPHER *c)
{
if (c == NULL)
return "(NONE)";
/*
* Backwards-compatibility crutch. In almost all contexts we report TLS
* 1.0 as "TLSv1", but for ciphers we report "TLSv1.0".
*/
if (c->min_tls == TLS1_VERSION)
return "TLSv1.0";
return ssl_protocol_to_string(c->min_tls);
}
/* return the actual cipher being used */
const char *SSL_CIPHER_get_name(const SSL_CIPHER *c)
{
if (c != NULL)
return c->name;
return "(NONE)";
}
/* return the actual cipher being used in RFC standard name */
const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c)
{
if (c != NULL)
return c->stdname;
return "(NONE)";
}
/* return the OpenSSL name based on given RFC standard name */
const char *OPENSSL_cipher_name(const char *stdname)
{
const SSL_CIPHER *c;
if (stdname == NULL)
return "(NONE)";
c = ssl3_get_cipher_by_std_name(stdname);
return SSL_CIPHER_get_name(c);
}
/* number of bits for symmetric cipher */
int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits)
{
int ret = 0;
if (c != NULL) {
if (alg_bits != NULL)
*alg_bits = (int)c->alg_bits;
ret = (int)c->strength_bits;
}
return ret;
}
uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c)
{
return c->id;
}
uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c)
{
return c->id & 0xFFFF;
}
SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n)
{
SSL_COMP *ctmp;
int i, nn;
if ((n == 0) || (sk == NULL))
return NULL;
nn = sk_SSL_COMP_num(sk);
for (i = 0; i < nn; i++) {
ctmp = sk_SSL_COMP_value(sk, i);
if (ctmp->id == n)
return ctmp;
}
return NULL;
}
#ifdef OPENSSL_NO_COMP
STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
{
return NULL;
}
STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
*meths)
{
return meths;
}
int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
{
return 1;
}
#else
STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
{
load_builtin_compressions();
return ssl_comp_methods;
}
STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
*meths)
{
STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods;
ssl_comp_methods = meths;
return old_meths;
}
static void cmeth_free(SSL_COMP *cm)
{
OPENSSL_free(cm);
}
void ssl_comp_free_compression_methods_int(void)
{
STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods;
ssl_comp_methods = NULL;
sk_SSL_COMP_pop_free(old_meths, cmeth_free);
}
int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
{
SSL_COMP *comp;
if (cm == NULL || COMP_get_type(cm) == NID_undef)
return 1;
/*-
* According to draft-ietf-tls-compression-04.txt, the
* compression number ranges should be the following:
*
* 0 to 63: methods defined by the IETF
* 64 to 192: external party methods assigned by IANA
* 193 to 255: reserved for private use
*/
if (id < 193 || id > 255) {
SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,
SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE);
return 1;
}
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
comp = OPENSSL_malloc(sizeof(*comp));
if (comp == NULL) {
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
return 1;
}
comp->id = id;
comp->method = cm;
load_builtin_compressions();
if (ssl_comp_methods && sk_SSL_COMP_find(ssl_comp_methods, comp) >= 0) {
OPENSSL_free(comp);
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,
SSL_R_DUPLICATE_COMPRESSION_ID);
return 1;
}
if (ssl_comp_methods == NULL || !sk_SSL_COMP_push(ssl_comp_methods, comp)) {
OPENSSL_free(comp);
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
return 1;
}
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
return 0;
}
#endif
const char *SSL_COMP_get_name(const COMP_METHOD *comp)
{
#ifndef OPENSSL_NO_COMP
return comp ? COMP_get_name(comp) : NULL;
#else
return NULL;
#endif
}
const char *SSL_COMP_get0_name(const SSL_COMP *comp)
{
#ifndef OPENSSL_NO_COMP
return comp->name;
#else
return NULL;
#endif
}
int SSL_COMP_get_id(const SSL_COMP *comp)
{
#ifndef OPENSSL_NO_COMP
return comp->id;
#else
return -1;
#endif
}
const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl, const unsigned char *ptr,
int all)
{
const SSL_CIPHER *c = ssl->method->get_cipher_by_char(ptr);
if (c == NULL || (!all && c->valid == 0))
return NULL;
return c;
}
const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr)
{
return ssl->method->get_cipher_by_char(ptr);
}
int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c)
{
int i;
if (c == NULL)
return NID_undef;
i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, c->algorithm_enc);
if (i == -1)
return NID_undef;
return ssl_cipher_table_cipher[i].nid;
}
int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c)
{
int i = ssl_cipher_info_lookup(ssl_cipher_table_mac, c->algorithm_mac);
if (i == -1)
return NID_undef;
return ssl_cipher_table_mac[i].nid;
}
int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c)
{
int i = ssl_cipher_info_lookup(ssl_cipher_table_kx, c->algorithm_mkey);
if (i == -1)
return NID_undef;
return ssl_cipher_table_kx[i].nid;
}
int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c)
{
int i = ssl_cipher_info_lookup(ssl_cipher_table_auth, c->algorithm_auth);
if (i == -1)
return NID_undef;
return ssl_cipher_table_auth[i].nid;
}
const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c)
{
int idx = c->algorithm2 & SSL_HANDSHAKE_MAC_MASK;
if (idx < 0 || idx >= SSL_MD_NUM_IDX)
return NULL;
return ssl_digest_methods[idx];
}
int SSL_CIPHER_is_aead(const SSL_CIPHER *c)
{
return (c->algorithm_mac & SSL_AEAD) ? 1 : 0;
}
int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
size_t *int_overhead, size_t *blocksize,
size_t *ext_overhead)
{
size_t mac = 0, in = 0, blk = 0, out = 0;
/* Some hard-coded numbers for the CCM/Poly1305 MAC overhead
* because there are no handy #defines for those. */
if (c->algorithm_enc & (SSL_AESGCM | SSL_ARIAGCM)) {
out = EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
} else if (c->algorithm_enc & (SSL_AES128CCM | SSL_AES256CCM)) {
out = EVP_CCM_TLS_EXPLICIT_IV_LEN + 16;
} else if (c->algorithm_enc & (SSL_AES128CCM8 | SSL_AES256CCM8)) {
out = EVP_CCM_TLS_EXPLICIT_IV_LEN + 8;
} else if (c->algorithm_enc & SSL_CHACHA20POLY1305) {
out = 16;
} else if (c->algorithm_mac & SSL_AEAD) {
/* We're supposed to have handled all the AEAD modes above */
return 0;
} else {
/* Non-AEAD modes. Calculate MAC/cipher overhead separately */
int digest_nid = SSL_CIPHER_get_digest_nid(c);
const EVP_MD *e_md = EVP_get_digestbynid(digest_nid);
if (e_md == NULL)
return 0;
mac = EVP_MD_size(e_md);
if (c->algorithm_enc != SSL_eNULL) {
int cipher_nid = SSL_CIPHER_get_cipher_nid(c);
const EVP_CIPHER *e_ciph = EVP_get_cipherbynid(cipher_nid);
/* If it wasn't AEAD or SSL_eNULL, we expect it to be a
known CBC cipher. */
if (e_ciph == NULL ||
EVP_CIPHER_mode(e_ciph) != EVP_CIPH_CBC_MODE)
return 0;
in = 1; /* padding length byte */
out = EVP_CIPHER_iv_length(e_ciph);
blk = EVP_CIPHER_block_size(e_ciph);
}
}
*mac_overhead = mac;
*int_overhead = in;
*blocksize = blk;
*ext_overhead = out;
return 1;
}
int ssl_cert_is_disabled(size_t idx)
{
const SSL_CERT_LOOKUP *cl = ssl_cert_lookup_by_idx(idx);
if (cl == NULL || (cl->amask & disabled_auth_mask) != 0)
return 1;
return 0;
}
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index d75158e30c4f..61a0ea2cc974 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1,5531 +1,5561 @@
/*
* Copyright 1995-2018 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(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(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;
}
/** 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 (sk_SSL_CIPHER_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 (sk_SSL_CIPHER_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(SSL_CTX *ctx)
{
return ctx->method;
}
const SSL_METHOD *SSL_get_ssl_method(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);
}
-SSL *SSL_dup(SSL *s)
+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 (s->ca_names != NULL) {
- if ((sk = sk_X509_NAME_dup(s->ca_names)) == NULL)
- goto err;
- ret->ca_names = sk;
- for (i = 0; i < sk_X509_NAME_num(sk); i++) {
- xn = sk_X509_NAME_value(sk, i);
- if (sk_X509_NAME_set(sk, i, X509_NAME_dup(xn)) == NULL) {
- X509_NAME_free(xn);
- goto err;
- }
- }
- }
+ 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(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(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(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(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(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(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)
{
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 ((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;
+ 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;
+ 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_free(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 e8819e7a2838..70e5a1740f9c 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1,2654 +1,2668 @@
/*
* Copyright 1995-2018 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));
};
-# define TLS13_MAX_RESUMPTION_PSK_LENGTH 64
+/*
+ * 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.
+ * 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 */
/* Count of how many KeyUpdate messages we have received */
unsigned int key_update_count;
/* 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;
- /* for server side, keep the list of CA_dn we can use */
+ /*
+ * 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;
} 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 */
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 int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str);
__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);
__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 8422161dc103..63e61c6184ac 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -1,1691 +1,1693 @@
/*
* Copyright 2016-2018 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
*/
TLSEXT_TYPE_cryptopro_bug,
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) {
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_counter(&s->session_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 = SSL_get0_CA_list(s);
+ 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, pkt)) {
+ 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)) {
/* 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 = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
- if (hdatalen <= 0) {
+ 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 4b5e6fe2b87f..ab4dbf67131e 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -1,1988 +1,1991 @@
/*
* Copyright 2016-2018 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;
+ 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_get_ciphers(s);
+ 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)
- return 1;
+ || c->min_tls >= TLS1_3_VERSION) {
+ ret = 1;
+ break;
+ }
}
- return 0;
+ 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;
/*
* 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);
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;
}
}
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) {
/*
* 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) {
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);
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;
#endif
return 1;
}
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index d75f9ea03608..f76c0e48034b 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -1,969 +1,970 @@
/*
* Copyright 2015-2018 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 <openssl/rand.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
#include <assert.h>
/*
* This file implements the SSL/TLS/DTLS state machines.
*
* There are two primary state machines:
*
* 1) Message flow state machine
* 2) Handshake state machine
*
* The Message flow state machine controls the reading and sending of messages
* including handling of non-blocking IO events, flushing of the underlying
* write BIO, handling unexpected messages, etc. It is itself broken into two
* separate sub-state machines which control reading and writing respectively.
*
* The Handshake state machine keeps track of the current SSL/TLS handshake
* state. Transitions of the handshake state are the result of events that
* occur within the Message flow state machine.
*
* Overall it looks like this:
*
* --------------------------------------------- -------------------
* | | | |
* | Message flow state machine | | |
* | | | |
* | -------------------- -------------------- | Transition | Handshake state |
* | | MSG_FLOW_READING | | MSG_FLOW_WRITING | | Event | machine |
* | | sub-state | | sub-state | |----------->| |
* | | machine for | | machine for | | | |
* | | reading messages | | writing messages | | | |
* | -------------------- -------------------- | | |
* | | | |
* --------------------------------------------- -------------------
*
*/
/* Sub state machine return values */
typedef enum {
/* Something bad happened or NBIO */
SUB_STATE_ERROR,
/* Sub state finished go to the next sub state */
SUB_STATE_FINISHED,
/* Sub state finished and handshake was completed */
SUB_STATE_END_HANDSHAKE
} SUB_STATE_RETURN;
static int state_machine(SSL *s, int server);
static void init_read_state_machine(SSL *s);
static SUB_STATE_RETURN read_state_machine(SSL *s);
static void init_write_state_machine(SSL *s);
static SUB_STATE_RETURN write_state_machine(SSL *s);
OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl)
{
return ssl->statem.hand_state;
}
int SSL_in_init(const SSL *s)
{
return s->statem.in_init;
}
int SSL_is_init_finished(const SSL *s)
{
return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK);
}
int SSL_in_before(const SSL *s)
{
/*
* Historically being "in before" meant before anything had happened. In the
* current code though we remain in the "before" state for a while after we
* have started the handshake process (e.g. as a server waiting for the
* first message to arrive). There "in before" is taken to mean "in before"
* and not started any handshake process yet.
*/
return (s->statem.hand_state == TLS_ST_BEFORE)
&& (s->statem.state == MSG_FLOW_UNINITED);
}
/*
* Clear the state machine state and reset back to MSG_FLOW_UNINITED
*/
void ossl_statem_clear(SSL *s)
{
s->statem.state = MSG_FLOW_UNINITED;
s->statem.hand_state = TLS_ST_BEFORE;
s->statem.in_init = 1;
s->statem.no_cert_verify = 0;
}
/*
* Set the state machine up ready for a renegotiation handshake
*/
void ossl_statem_set_renegotiate(SSL *s)
{
s->statem.in_init = 1;
s->statem.request_state = TLS_ST_SW_HELLO_REQ;
}
/*
* Put the state machine into an error state and send an alert if appropriate.
* This is a permanent error for the current connection.
*/
void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
int line)
{
+ ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
/* We shouldn't call SSLfatal() twice. Once is enough */
- assert(s->statem.state != MSG_FLOW_ERROR);
+ if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR)
+ return;
s->statem.in_init = 1;
s->statem.state = MSG_FLOW_ERROR;
- ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
if (al != SSL_AD_NO_ALERT
&& s->statem.enc_write_state != ENC_WRITE_STATE_INVALID)
ssl3_send_alert(s, SSL3_AL_FATAL, al);
}
/*
* This macro should only be called if we are already expecting to be in
* a fatal error state. We verify that we are, and set it if not (this would
* indicate a bug).
*/
#define check_fatal(s, f) \
do { \
if (!ossl_assert((s)->statem.in_init \
&& (s)->statem.state == MSG_FLOW_ERROR)) \
SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \
SSL_R_MISSING_FATAL); \
} while (0)
/*
* Discover whether the current connection is in the error state.
*
* Valid return values are:
* 1: Yes
* 0: No
*/
int ossl_statem_in_error(const SSL *s)
{
if (s->statem.state == MSG_FLOW_ERROR)
return 1;
return 0;
}
void ossl_statem_set_in_init(SSL *s, int init)
{
s->statem.in_init = init;
}
int ossl_statem_get_in_handshake(SSL *s)
{
return s->statem.in_handshake;
}
void ossl_statem_set_in_handshake(SSL *s, int inhand)
{
if (inhand)
s->statem.in_handshake++;
else
s->statem.in_handshake--;
}
/* Are we in a sensible state to skip over unreadable early data? */
int ossl_statem_skip_early_data(SSL *s)
{
if (s->ext.early_data != SSL_EARLY_DATA_REJECTED)
return 0;
if (!s->server
|| s->statem.hand_state != TLS_ST_EARLY_DATA
|| s->hello_retry_request == SSL_HRR_COMPLETE)
return 0;
return 1;
}
/*
* Called when we are in SSL_read*(), SSL_write*(), or SSL_accept()
* /SSL_connect()/SSL_do_handshake(). Used to test whether we are in an early
* data state and whether we should attempt to move the handshake on if so.
* |sending| is 1 if we are attempting to send data (SSL_write*()), 0 if we are
* attempting to read data (SSL_read*()), or -1 if we are in SSL_do_handshake()
* or similar.
*/
void ossl_statem_check_finish_init(SSL *s, int sending)
{
if (sending == -1) {
if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
|| s->statem.hand_state == TLS_ST_EARLY_DATA) {
ossl_statem_set_in_init(s, 1);
if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
/*
* SSL_connect() or SSL_do_handshake() has been called directly.
* We don't allow any more writing of early data.
*/
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
}
}
} else if (!s->server) {
if ((sending && (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
|| s->statem.hand_state == TLS_ST_EARLY_DATA)
&& s->early_data_state != SSL_EARLY_DATA_WRITING)
|| (!sending && s->statem.hand_state == TLS_ST_EARLY_DATA)) {
ossl_statem_set_in_init(s, 1);
/*
* SSL_write() has been called directly. We don't allow any more
* writing of early data.
*/
if (sending && s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
}
} else {
if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING
&& s->statem.hand_state == TLS_ST_EARLY_DATA)
ossl_statem_set_in_init(s, 1);
}
}
void ossl_statem_set_hello_verify_done(SSL *s)
{
s->statem.state = MSG_FLOW_UNINITED;
s->statem.in_init = 1;
/*
* This will get reset (briefly) back to TLS_ST_BEFORE when we enter
* state_machine() because |state| is MSG_FLOW_UNINITED, but until then any
* calls to SSL_in_before() will return false. Also calls to
* SSL_state_string() and SSL_state_string_long() will return something
* sensible.
*/
s->statem.hand_state = TLS_ST_SR_CLNT_HELLO;
}
int ossl_statem_connect(SSL *s)
{
return state_machine(s, 0);
}
int ossl_statem_accept(SSL *s)
{
return state_machine(s, 1);
}
typedef void (*info_cb) (const SSL *, int, int);
static info_cb get_callback(SSL *s)
{
if (s->info_callback != NULL)
return s->info_callback;
else if (s->ctx->info_callback != NULL)
return s->ctx->info_callback;
return NULL;
}
/*
* The main message flow state machine. We start in the MSG_FLOW_UNINITED or
* MSG_FLOW_FINISHED state and finish in MSG_FLOW_FINISHED. Valid states and
* transitions are as follows:
*
* MSG_FLOW_UNINITED MSG_FLOW_FINISHED
* | |
* +-----------------------+
* v
* MSG_FLOW_WRITING <---> MSG_FLOW_READING
* |
* V
* MSG_FLOW_FINISHED
* |
* V
* [SUCCESS]
*
* We may exit at any point due to an error or NBIO event. If an NBIO event
* occurs then we restart at the point we left off when we are recalled.
* MSG_FLOW_WRITING and MSG_FLOW_READING have sub-state machines associated with them.
*
* In addition to the above there is also the MSG_FLOW_ERROR state. We can move
* into that state at any point in the event that an irrecoverable error occurs.
*
* Valid return values are:
* 1: Success
* <=0: NBIO or error
*/
static int state_machine(SSL *s, int server)
{
BUF_MEM *buf = NULL;
void (*cb) (const SSL *ssl, int type, int val) = NULL;
OSSL_STATEM *st = &s->statem;
int ret = -1;
int ssret;
if (st->state == MSG_FLOW_ERROR) {
/* Shouldn't have been called if we're already in the error state */
return -1;
}
ERR_clear_error();
clear_sys_error();
cb = get_callback(s);
st->in_handshake++;
if (!SSL_in_init(s) || SSL_in_before(s)) {
/*
* If we are stateless then we already called SSL_clear() - don't do
* it again and clear the STATELESS flag itself.
*/
if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s))
return -1;
}
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
/*
* Notify SCTP BIO socket to enter handshake mode and prevent stream
* identifier other than 0.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
st->in_handshake, NULL);
}
#endif
/* Initialise state machine */
if (st->state == MSG_FLOW_UNINITED
|| st->state == MSG_FLOW_FINISHED) {
if (st->state == MSG_FLOW_UNINITED) {
st->hand_state = TLS_ST_BEFORE;
st->request_state = TLS_ST_BEFORE;
}
s->server = server;
if (cb != NULL)
cb(s, SSL_CB_HANDSHAKE_START, 1);
/*
* Fatal errors in this block don't send an alert because we have
* failed to even initialise properly. Sending an alert is probably
* doomed to failure.
*/
if (SSL_IS_DTLS(s)) {
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
(server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
} else {
if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
}
if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
if (s->init_buf == NULL) {
if ((buf = BUF_MEM_new()) == NULL) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
s->init_buf = buf;
buf = NULL;
}
if (!ssl3_setup_buffers(s)) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
s->init_num = 0;
/*
* Should have been reset by tls_process_finished, too.
*/
s->s3->change_cipher_spec = 0;
/*
* Ok, we now need to push on a buffering BIO ...but not with
* SCTP
*/
#ifndef OPENSSL_NO_SCTP
if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
#endif
if (!ssl_init_wbio_buffer(s)) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
if ((SSL_in_before(s))
|| s->renegotiate) {
if (!tls_setup_handshake(s)) {
/* SSLfatal() already called */
goto end;
}
if (SSL_IS_FIRST_HANDSHAKE(s))
st->read_state_first_init = 1;
}
st->state = MSG_FLOW_WRITING;
init_write_state_machine(s);
}
while (st->state != MSG_FLOW_FINISHED) {
if (st->state == MSG_FLOW_READING) {
ssret = read_state_machine(s);
if (ssret == SUB_STATE_FINISHED) {
st->state = MSG_FLOW_WRITING;
init_write_state_machine(s);
} else {
/* NBIO or error */
goto end;
}
} else if (st->state == MSG_FLOW_WRITING) {
ssret = write_state_machine(s);
if (ssret == SUB_STATE_FINISHED) {
st->state = MSG_FLOW_READING;
init_read_state_machine(s);
} else if (ssret == SUB_STATE_END_HANDSHAKE) {
st->state = MSG_FLOW_FINISHED;
} else {
/* NBIO or error */
goto end;
}
} else {
/* Error */
check_fatal(s, SSL_F_STATE_MACHINE);
SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
goto end;
}
}
ret = 1;
end:
st->in_handshake--;
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
/*
* Notify SCTP BIO socket to leave handshake mode and allow stream
* identifier other than 0.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
st->in_handshake, NULL);
}
#endif
BUF_MEM_free(buf);
if (cb != NULL) {
if (server)
cb(s, SSL_CB_ACCEPT_EXIT, ret);
else
cb(s, SSL_CB_CONNECT_EXIT, ret);
}
return ret;
}
/*
* Initialise the MSG_FLOW_READING sub-state machine
*/
static void init_read_state_machine(SSL *s)
{
OSSL_STATEM *st = &s->statem;
st->read_state = READ_STATE_HEADER;
}
static int grow_init_buf(SSL *s, size_t size) {
size_t msg_offset = (char *)s->init_msg - s->init_buf->data;
if (!BUF_MEM_grow_clean(s->init_buf, (int)size))
return 0;
if (size < msg_offset)
return 0;
s->init_msg = s->init_buf->data + msg_offset;
return 1;
}
/*
* This function implements the sub-state machine when the message flow is in
* MSG_FLOW_READING. The valid sub-states and transitions are:
*
* READ_STATE_HEADER <--+<-------------+
* | | |
* v | |
* READ_STATE_BODY -----+-->READ_STATE_POST_PROCESS
* | |
* +----------------------------+
* v
* [SUB_STATE_FINISHED]
*
* READ_STATE_HEADER has the responsibility for reading in the message header
* and transitioning the state of the handshake state machine.
*
* READ_STATE_BODY reads in the rest of the message and then subsequently
* processes it.
*
* READ_STATE_POST_PROCESS is an optional step that may occur if some post
* processing activity performed on the message may block.
*
* Any of the above states could result in an NBIO event occurring in which case
* control returns to the calling application. When this function is recalled we
* will resume in the same state where we left off.
*/
static SUB_STATE_RETURN read_state_machine(SSL *s)
{
OSSL_STATEM *st = &s->statem;
int ret, mt;
size_t len = 0;
int (*transition) (SSL *s, int mt);
PACKET pkt;
MSG_PROCESS_RETURN(*process_message) (SSL *s, PACKET *pkt);
WORK_STATE(*post_process_message) (SSL *s, WORK_STATE wst);
size_t (*max_message_size) (SSL *s);
void (*cb) (const SSL *ssl, int type, int val) = NULL;
cb = get_callback(s);
if (s->server) {
transition = ossl_statem_server_read_transition;
process_message = ossl_statem_server_process_message;
max_message_size = ossl_statem_server_max_message_size;
post_process_message = ossl_statem_server_post_process_message;
} else {
transition = ossl_statem_client_read_transition;
process_message = ossl_statem_client_process_message;
max_message_size = ossl_statem_client_max_message_size;
post_process_message = ossl_statem_client_post_process_message;
}
if (st->read_state_first_init) {
s->first_packet = 1;
st->read_state_first_init = 0;
}
while (1) {
switch (st->read_state) {
case READ_STATE_HEADER:
/* Get the state the peer wants to move to */
if (SSL_IS_DTLS(s)) {
/*
* In DTLS we get the whole message in one go - header and body
*/
ret = dtls_get_message(s, &mt, &len);
} else {
ret = tls_get_message_header(s, &mt);
}
if (ret == 0) {
/* Could be non-blocking IO */
return SUB_STATE_ERROR;
}
if (cb != NULL) {
/* Notify callback of an impending state change */
if (s->server)
cb(s, SSL_CB_ACCEPT_LOOP, 1);
else
cb(s, SSL_CB_CONNECT_LOOP, 1);
}
/*
* Validate that we are allowed to move to the new state and move
* to that state if so
*/
if (!transition(s, mt))
return SUB_STATE_ERROR;
if (s->s3->tmp.message_size > max_message_size(s)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
SSL_R_EXCESSIVE_MESSAGE_SIZE);
return SUB_STATE_ERROR;
}
/* dtls_get_message already did this */
if (!SSL_IS_DTLS(s)
&& s->s3->tmp.message_size > 0
&& !grow_init_buf(s, s->s3->tmp.message_size
+ SSL3_HM_HEADER_LENGTH)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
ERR_R_BUF_LIB);
return SUB_STATE_ERROR;
}
st->read_state = READ_STATE_BODY;
/* Fall through */
case READ_STATE_BODY:
if (!SSL_IS_DTLS(s)) {
/* We already got this above for DTLS */
ret = tls_get_message_body(s, &len);
if (ret == 0) {
/* Could be non-blocking IO */
return SUB_STATE_ERROR;
}
}
s->first_packet = 0;
if (!PACKET_buf_init(&pkt, s->init_msg, len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
ret = process_message(s, &pkt);
/* Discard the packet data */
s->init_num = 0;
switch (ret) {
case MSG_PROCESS_ERROR:
check_fatal(s, SSL_F_READ_STATE_MACHINE);
return SUB_STATE_ERROR;
case MSG_PROCESS_FINISHED_READING:
if (SSL_IS_DTLS(s)) {
dtls1_stop_timer(s);
}
return SUB_STATE_FINISHED;
case MSG_PROCESS_CONTINUE_PROCESSING:
st->read_state = READ_STATE_POST_PROCESS;
st->read_state_work = WORK_MORE_A;
break;
default:
st->read_state = READ_STATE_HEADER;
break;
}
break;
case READ_STATE_POST_PROCESS:
st->read_state_work = post_process_message(s, st->read_state_work);
switch (st->read_state_work) {
case WORK_ERROR:
check_fatal(s, SSL_F_READ_STATE_MACHINE);
/* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
case WORK_MORE_C:
return SUB_STATE_ERROR;
case WORK_FINISHED_CONTINUE:
st->read_state = READ_STATE_HEADER;
break;
case WORK_FINISHED_STOP:
if (SSL_IS_DTLS(s)) {
dtls1_stop_timer(s);
}
return SUB_STATE_FINISHED;
}
break;
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
}
}
/*
* Send a previously constructed message to the peer.
*/
static int statem_do_write(SSL *s)
{
OSSL_STATEM *st = &s->statem;
if (st->hand_state == TLS_ST_CW_CHANGE
|| st->hand_state == TLS_ST_SW_CHANGE) {
if (SSL_IS_DTLS(s))
return dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
else
return ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
} else {
return ssl_do_write(s);
}
}
/*
* Initialise the MSG_FLOW_WRITING sub-state machine
*/
static void init_write_state_machine(SSL *s)
{
OSSL_STATEM *st = &s->statem;
st->write_state = WRITE_STATE_TRANSITION;
}
/*
* This function implements the sub-state machine when the message flow is in
* MSG_FLOW_WRITING. The valid sub-states and transitions are:
*
* +-> WRITE_STATE_TRANSITION ------> [SUB_STATE_FINISHED]
* | |
* | v
* | WRITE_STATE_PRE_WORK -----> [SUB_STATE_END_HANDSHAKE]
* | |
* | v
* | WRITE_STATE_SEND
* | |
* | v
* | WRITE_STATE_POST_WORK
* | |
* +-------------+
*
* WRITE_STATE_TRANSITION transitions the state of the handshake state machine
* WRITE_STATE_PRE_WORK performs any work necessary to prepare the later
* sending of the message. This could result in an NBIO event occurring in
* which case control returns to the calling application. When this function
* is recalled we will resume in the same state where we left off.
*
* WRITE_STATE_SEND sends the message and performs any work to be done after
* sending.
*
* WRITE_STATE_POST_WORK performs any work necessary after the sending of the
* message has been completed. As for WRITE_STATE_PRE_WORK this could also
* result in an NBIO event.
*/
static SUB_STATE_RETURN write_state_machine(SSL *s)
{
OSSL_STATEM *st = &s->statem;
int ret;
WRITE_TRAN(*transition) (SSL *s);
WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst);
WORK_STATE(*post_work) (SSL *s, WORK_STATE wst);
int (*get_construct_message_f) (SSL *s, WPACKET *pkt,
int (**confunc) (SSL *s, WPACKET *pkt),
int *mt);
void (*cb) (const SSL *ssl, int type, int val) = NULL;
int (*confunc) (SSL *s, WPACKET *pkt);
int mt;
WPACKET pkt;
cb = get_callback(s);
if (s->server) {
transition = ossl_statem_server_write_transition;
pre_work = ossl_statem_server_pre_work;
post_work = ossl_statem_server_post_work;
get_construct_message_f = ossl_statem_server_construct_message;
} else {
transition = ossl_statem_client_write_transition;
pre_work = ossl_statem_client_pre_work;
post_work = ossl_statem_client_post_work;
get_construct_message_f = ossl_statem_client_construct_message;
}
while (1) {
switch (st->write_state) {
case WRITE_STATE_TRANSITION:
if (cb != NULL) {
/* Notify callback of an impending state change */
if (s->server)
cb(s, SSL_CB_ACCEPT_LOOP, 1);
else
cb(s, SSL_CB_CONNECT_LOOP, 1);
}
switch (transition(s)) {
case WRITE_TRAN_CONTINUE:
st->write_state = WRITE_STATE_PRE_WORK;
st->write_state_work = WORK_MORE_A;
break;
case WRITE_TRAN_FINISHED:
return SUB_STATE_FINISHED;
break;
case WRITE_TRAN_ERROR:
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
return SUB_STATE_ERROR;
}
break;
case WRITE_STATE_PRE_WORK:
switch (st->write_state_work = pre_work(s, st->write_state_work)) {
case WORK_ERROR:
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
/* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
case WORK_MORE_C:
return SUB_STATE_ERROR;
case WORK_FINISHED_CONTINUE:
st->write_state = WRITE_STATE_SEND;
break;
case WORK_FINISHED_STOP:
return SUB_STATE_END_HANDSHAKE;
}
if (!get_construct_message_f(s, &pkt, &confunc, &mt)) {
/* SSLfatal() already called */
return SUB_STATE_ERROR;
}
if (mt == SSL3_MT_DUMMY) {
/* Skip construction and sending. This isn't a "real" state */
st->write_state = WRITE_STATE_POST_WORK;
st->write_state_work = WORK_MORE_A;
break;
}
if (!WPACKET_init(&pkt, s->init_buf)
|| !ssl_set_handshake_header(s, &pkt, mt)) {
WPACKET_cleanup(&pkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
if (confunc != NULL && !confunc(s, &pkt)) {
WPACKET_cleanup(&pkt);
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
return SUB_STATE_ERROR;
}
if (!ssl_close_construct_packet(s, &pkt, mt)
|| !WPACKET_finish(&pkt)) {
WPACKET_cleanup(&pkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
/* Fall through */
case WRITE_STATE_SEND:
if (SSL_IS_DTLS(s) && st->use_timer) {
dtls1_start_timer(s);
}
ret = statem_do_write(s);
if (ret <= 0) {
return SUB_STATE_ERROR;
}
st->write_state = WRITE_STATE_POST_WORK;
st->write_state_work = WORK_MORE_A;
/* Fall through */
case WRITE_STATE_POST_WORK:
switch (st->write_state_work = post_work(s, st->write_state_work)) {
case WORK_ERROR:
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
/* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
case WORK_MORE_C:
return SUB_STATE_ERROR;
case WORK_FINISHED_CONTINUE:
st->write_state = WRITE_STATE_TRANSITION;
break;
case WORK_FINISHED_STOP:
return SUB_STATE_END_HANDSHAKE;
}
break;
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
}
}
/*
* Flush the write BIO
*/
int statem_flush(SSL *s)
{
s->rwstate = SSL_WRITING;
if (BIO_flush(s->wbio) <= 0) {
return 0;
}
s->rwstate = SSL_NOTHING;
return 1;
}
/*
* Called by the record layer to determine whether application data is
* allowed to be received in the current handshake state or not.
*
* Return values are:
* 1: Yes (application data allowed)
* 0: No (application data not allowed)
*/
int ossl_statem_app_data_allowed(SSL *s)
{
OSSL_STATEM *st = &s->statem;
if (st->state == MSG_FLOW_UNINITED)
return 0;
if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0))
return 0;
if (s->server) {
/*
* If we're a server and we haven't got as far as writing our
* ServerHello yet then we allow app data
*/
if (st->hand_state == TLS_ST_BEFORE
|| st->hand_state == TLS_ST_SR_CLNT_HELLO)
return 1;
} else {
/*
* If we're a client and we haven't read the ServerHello yet then we
* allow app data
*/
if (st->hand_state == TLS_ST_CW_CLNT_HELLO)
return 1;
}
return 0;
}
/*
* This function returns 1 if TLS exporter is ready to export keying
* material, or 0 if otherwise.
*/
int ossl_statem_export_allowed(SSL *s)
{
return s->s3->previous_server_finished_len != 0
&& s->statem.hand_state != TLS_ST_SW_FINISHED;
}
/*
* Return 1 if early TLS exporter is ready to export keying material,
* or 0 if otherwise.
*/
int ossl_statem_export_early_allowed(SSL *s)
{
/*
* The early exporter secret is only present on the server if we
* have accepted early_data. It is present on the client as long
* as we have sent early_data.
*/
return s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
|| (!s->server && s->ext.early_data != SSL_EARLY_DATA_NOT_SENT);
}
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 8c658da8990d..0a11b88183e3 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1,3833 +1,3845 @@
/*
* Copyright 1995-2018 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;
if (!WPACKET_set_max_size(pkt, SSL3_RT_MAX_PLAIN_LENGTH)) {
/* Should not happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
return 0;
}
/* 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)) {
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)];
/*
* 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));
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey),
labelbuffer,
sizeof(labelbuffer), 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", 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)) {
/* 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)];
/*
* 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));
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
sizeof(labelbuffer), 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_lib.c b/ssl/statem/statem_lib.c
index 508bb88767a7..4324896f500a 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -1,2374 +1,2421 @@
/*
* Copyright 1995-2018 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 <limits.h>
#include <string.h>
#include <stdio.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
/*
* Map error codes to TLS/SSL alart types.
*/
typedef struct x509err2alert_st {
int x509err;
int alert;
} X509ERR2ALERT;
/* Fixed value used in the ServerHello random field to identify an HRR */
const unsigned char hrrrandom[] = {
0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02,
0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
};
/*
* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
* SSL3_RT_CHANGE_CIPHER_SPEC)
*/
int ssl3_do_write(SSL *s, int type)
{
int ret;
size_t written = 0;
ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
s->init_num, &written);
if (ret < 0)
return -1;
if (type == SSL3_RT_HANDSHAKE)
/*
* should not be done for 'Hello Request's, but in that case we'll
* ignore the result anyway
* TLS1.3 KeyUpdate and NewSessionTicket do not need to be added
*/
if (!SSL_IS_TLS13(s) || (s->statem.hand_state != TLS_ST_SW_SESSION_TICKET
&& s->statem.hand_state != TLS_ST_CW_KEY_UPDATE
&& s->statem.hand_state != TLS_ST_SW_KEY_UPDATE))
if (!ssl3_finish_mac(s,
(unsigned char *)&s->init_buf->data[s->init_off],
written))
return -1;
if (written == s->init_num) {
if (s->msg_callback)
s->msg_callback(1, s->version, type, s->init_buf->data,
(size_t)(s->init_off + s->init_num), s,
s->msg_callback_arg);
return 1;
}
s->init_off += written;
s->init_num -= written;
return 0;
}
int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
{
size_t msglen;
if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
|| !WPACKET_get_length(pkt, &msglen)
|| msglen > INT_MAX)
return 0;
s->init_num = (int)msglen;
s->init_off = 0;
return 1;
}
int tls_setup_handshake(SSL *s)
{
if (!ssl3_init_finished_mac(s)) {
/* SSLfatal() already called */
return 0;
}
/* Reset any extension flags */
memset(s->ext.extflags, 0, sizeof(s->ext.extflags));
if (s->server) {
STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(s);
int i, ver_min, ver_max, ok = 0;
/*
* Sanity check that the maximum version we accept has ciphers
* enabled. For clients we do this check during construction of the
* ClientHello.
*/
if (ssl_get_min_max_version(s, &ver_min, &ver_max, NULL) != 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE,
ERR_R_INTERNAL_ERROR);
return 0;
}
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
if (SSL_IS_DTLS(s)) {
if (DTLS_VERSION_GE(ver_max, c->min_dtls) &&
DTLS_VERSION_LE(ver_max, c->max_dtls))
ok = 1;
} else if (ver_max >= c->min_tls && ver_max <= c->max_tls) {
ok = 1;
}
if (ok)
break;
}
if (!ok) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
SSL_R_NO_CIPHERS_AVAILABLE);
ERR_add_error_data(1, "No ciphers enabled for max supported "
"SSL/TLS version");
return 0;
}
if (SSL_IS_FIRST_HANDSHAKE(s)) {
/* N.B. s->session_ctx == s->ctx here */
tsan_counter(&s->session_ctx->stats.sess_accept);
} else {
/* N.B. s->ctx may not equal s->session_ctx */
tsan_counter(&s->ctx->stats.sess_accept_renegotiate);
s->s3->tmp.cert_request = 0;
}
} else {
if (SSL_IS_FIRST_HANDSHAKE(s))
tsan_counter(&s->session_ctx->stats.sess_connect);
else
tsan_counter(&s->session_ctx->stats.sess_connect_renegotiate);
/* mark client_random uninitialized */
memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
s->hit = 0;
s->s3->tmp.cert_req = 0;
if (SSL_IS_DTLS(s))
s->statem.use_timer = 1;
}
return 1;
}
/*
* Size of the to-be-signed TLS13 data, without the hash size itself:
* 64 bytes of value 32, 33 context bytes, 1 byte separator
*/
#define TLS13_TBS_START_SIZE 64
#define TLS13_TBS_PREAMBLE_SIZE (TLS13_TBS_START_SIZE + 33 + 1)
static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
void **hdata, size_t *hdatalen)
{
static const char *servercontext = "TLS 1.3, server CertificateVerify";
static const char *clientcontext = "TLS 1.3, client CertificateVerify";
if (SSL_IS_TLS13(s)) {
size_t hashlen;
/* Set the first 64 bytes of to-be-signed data to octet 32 */
memset(tls13tbs, 32, TLS13_TBS_START_SIZE);
/* This copies the 33 bytes of context plus the 0 separator byte */
if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
|| s->statem.hand_state == TLS_ST_SW_CERT_VRFY)
strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, servercontext);
else
strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, clientcontext);
/*
* If we're currently reading then we need to use the saved handshake
* hash value. We can't use the current handshake hash state because
* that includes the CertVerify itself.
*/
if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
|| s->statem.hand_state == TLS_ST_SR_CERT_VRFY) {
memcpy(tls13tbs + TLS13_TBS_PREAMBLE_SIZE, s->cert_verify_hash,
s->cert_verify_hash_len);
hashlen = s->cert_verify_hash_len;
} else if (!ssl_handshake_hash(s, tls13tbs + TLS13_TBS_PREAMBLE_SIZE,
EVP_MAX_MD_SIZE, &hashlen)) {
/* SSLfatal() already called */
return 0;
}
*hdata = tls13tbs;
*hdatalen = TLS13_TBS_PREAMBLE_SIZE + hashlen;
} else {
size_t retlen;
+ long retlen_l;
- retlen = BIO_get_mem_data(s->s3->handshake_buffer, hdata);
- if (retlen <= 0) {
+ retlen = retlen_l = BIO_get_mem_data(s->s3->handshake_buffer, hdata);
+ if (retlen_l <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA,
ERR_R_INTERNAL_ERROR);
return 0;
}
*hdatalen = retlen;
}
return 1;
}
int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
{
EVP_PKEY *pkey = NULL;
const EVP_MD *md = NULL;
EVP_MD_CTX *mctx = NULL;
EVP_PKEY_CTX *pctx = NULL;
size_t hdatalen = 0, siglen = 0;
void *hdata;
unsigned char *sig = NULL;
unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
if (lu == NULL || s->s3->tmp.cert == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
}
pkey = s->s3->tmp.cert->privatekey;
if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
}
mctx = EVP_MD_CTX_new();
if (mctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_MALLOC_FAILURE);
goto err;
}
/* Get the data to be signed */
if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
/* SSLfatal() already called */
goto err;
}
if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
}
siglen = EVP_PKEY_size(pkey);
sig = OPENSSL_malloc(siglen);
if (sig == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_EVP_LIB);
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_CERT_VERIFY,
ERR_R_EVP_LIB);
goto err;
}
}
if (s->version == SSL3_VERSION) {
if (EVP_DigestSignUpdate(mctx, hdata, hdatalen) <= 0
|| !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
(int)s->session->master_key_length,
s->session->master_key)
|| EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_EVP_LIB);
goto err;
}
} else if (EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_EVP_LIB);
goto err;
}
#ifndef OPENSSL_NO_GOST
{
int pktype = lu->sig;
if (pktype == NID_id_GostR3410_2001
|| pktype == NID_id_GostR3410_2012_256
|| pktype == NID_id_GostR3410_2012_512)
BUF_reverse(sig, NULL, siglen);
}
#endif
if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Digest cached records and discard handshake buffer */
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
goto err;
}
OPENSSL_free(sig);
EVP_MD_CTX_free(mctx);
return 1;
err:
OPENSSL_free(sig);
EVP_MD_CTX_free(mctx);
return 0;
}
MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
{
EVP_PKEY *pkey = NULL;
const unsigned char *data;
#ifndef OPENSSL_NO_GOST
unsigned char *gost_data = NULL;
#endif
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
int j;
unsigned int len;
X509 *peer;
const EVP_MD *md = NULL;
size_t hdatalen = 0;
void *hdata;
unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
EVP_PKEY_CTX *pctx = NULL;
if (mctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
ERR_R_MALLOC_FAILURE);
goto err;
}
peer = s->session->peer;
pkey = X509_get0_pubkey(peer);
if (pkey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY,
SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
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_CERT_VERIFY,
SSL_R_BAD_PACKET);
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_CERT_VERIFY,
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_CERT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
}
#ifdef SSL_DEBUG
if (SSL_USE_SIGALGS(s))
fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
#endif
/* Check for broken implementations of GOST ciphersuites */
/*
* If key is GOST and len is exactly 64 or 128, it is signature without
* length field (CryptoPro implementations at least till TLS 1.2)
*/
#ifndef OPENSSL_NO_GOST
if (!SSL_USE_SIGALGS(s)
&& ((PACKET_remaining(pkt) == 64
&& (EVP_PKEY_id(pkey) == NID_id_GostR3410_2001
|| EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_256))
|| (PACKET_remaining(pkt) == 128
&& EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_512))) {
len = PACKET_remaining(pkt);
} else
#endif
if (!PACKET_get_net_2(pkt, &len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
SSL_R_LENGTH_MISMATCH);
goto err;
}
j = EVP_PKEY_size(pkey);
if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
|| (PACKET_remaining(pkt) == 0)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
SSL_R_WRONG_SIGNATURE_SIZE);
goto err;
}
if (!PACKET_get_bytes(pkt, &data, len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
/* SSLfatal() already called */
goto err;
}
#ifdef SSL_DEBUG
fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
#endif
if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
ERR_R_EVP_LIB);
goto err;
}
#ifndef OPENSSL_NO_GOST
{
int pktype = EVP_PKEY_id(pkey);
if (pktype == NID_id_GostR3410_2001
|| pktype == NID_id_GostR3410_2012_256
|| pktype == NID_id_GostR3410_2012_512) {
if ((gost_data = OPENSSL_malloc(len)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
goto err;
}
BUF_reverse(gost_data, data, len);
data = gost_data;
}
}
#endif
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_CERT_VERIFY,
ERR_R_EVP_LIB);
goto err;
}
}
if (s->version == SSL3_VERSION) {
if (EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0
|| !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
(int)s->session->master_key_length,
s->session->master_key)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
ERR_R_EVP_LIB);
goto err;
}
if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
SSL_R_BAD_SIGNATURE);
goto err;
}
} else {
j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen);
if (j <= 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
SSL_R_BAD_SIGNATURE);
goto err;
}
}
- ret = MSG_PROCESS_CONTINUE_READING;
+ /*
+ * In TLSv1.3 on the client side we make sure we prepare the client
+ * certificate after the CertVerify instead of when we get the
+ * CertificateRequest. This is because in TLSv1.3 the CertificateRequest
+ * comes *before* the Certificate message. In TLSv1.2 it comes after. We
+ * want to make sure that SSL_get_peer_certificate() will return the actual
+ * server certificate from the client_cert_cb callback.
+ */
+ if (!s->server && SSL_IS_TLS13(s) && s->s3->tmp.cert_req == 1)
+ ret = MSG_PROCESS_CONTINUE_PROCESSING;
+ else
+ ret = MSG_PROCESS_CONTINUE_READING;
err:
BIO_free(s->s3->handshake_buffer);
s->s3->handshake_buffer = NULL;
EVP_MD_CTX_free(mctx);
#ifndef OPENSSL_NO_GOST
OPENSSL_free(gost_data);
#endif
return ret;
}
int tls_construct_finished(SSL *s, WPACKET *pkt)
{
size_t finish_md_len;
const char *sender;
size_t slen;
/* This is a real handshake so make sure we clean it up at the end */
if (!s->server && s->post_handshake_auth != SSL_PHA_REQUESTED)
s->statem.cleanuphand = 1;
/*
* We only change the keys if we didn't already do this when we sent the
* client certificate
*/
if (SSL_IS_TLS13(s)
&& !s->server
&& s->s3->tmp.cert_req == 0
&& (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {;
/* SSLfatal() already called */
return 0;
}
if (s->server) {
sender = s->method->ssl3_enc->server_finished_label;
slen = s->method->ssl3_enc->server_finished_label_len;
} else {
sender = s->method->ssl3_enc->client_finished_label;
slen = s->method->ssl3_enc->client_finished_label_len;
}
finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
sender, slen,
s->s3->tmp.finish_md);
if (finish_md_len == 0) {
/* SSLfatal() already called */
return 0;
}
s->s3->tmp.finish_md_len = finish_md_len;
if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, finish_md_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* Log the master secret, if logging is enabled. We don't log it for
* TLSv1.3: there's a different key schedule for that.
*/
if (!SSL_IS_TLS13(s) && !ssl_log_secret(s, MASTER_SECRET_LABEL,
s->session->master_key,
s->session->master_key_length)) {
/* SSLfatal() already called */
return 0;
}
/*
* Copy the finished so we can use it for renegotiation checks
*/
if (!ossl_assert(finish_md_len <= EVP_MAX_MD_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!s->server) {
memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md,
finish_md_len);
s->s3->previous_client_finished_len = finish_md_len;
} else {
memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md,
finish_md_len);
s->s3->previous_server_finished_len = finish_md_len;
}
return 1;
}
int tls_construct_key_update(SSL *s, WPACKET *pkt)
{
if (!WPACKET_put_bytes_u8(pkt, s->key_update)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->key_update = SSL_KEY_UPDATE_NONE;
return 1;
}
MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
{
unsigned int updatetype;
s->key_update_count++;
if (s->key_update_count > MAX_KEY_UPDATE_MESSAGES) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
SSL_R_TOO_MANY_KEY_UPDATES);
return MSG_PROCESS_ERROR;
}
/*
* A KeyUpdate 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_KEY_UPDATE,
SSL_R_NOT_ON_RECORD_BOUNDARY);
return MSG_PROCESS_ERROR;
}
if (!PACKET_get_1(pkt, &updatetype)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE,
SSL_R_BAD_KEY_UPDATE);
return MSG_PROCESS_ERROR;
}
/*
* There are only two defined key update types. Fail if we get a value we
* didn't recognise.
*/
if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
&& updatetype != SSL_KEY_UPDATE_REQUESTED) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
SSL_R_BAD_KEY_UPDATE);
return MSG_PROCESS_ERROR;
}
/*
* If we get a request for us to update our sending keys too then, we need
* to additionally send a KeyUpdate message. However that message should
* not also request an update (otherwise we get into an infinite loop). We
* ignore a request for us to update our sending keys too if we already
* sent close_notify.
*/
if (updatetype == SSL_KEY_UPDATE_REQUESTED
&& (s->shutdown & SSL_SENT_SHUTDOWN) == 0)
s->key_update = SSL_KEY_UPDATE_NOT_REQUESTED;
if (!tls13_update_key(s, 0)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
return MSG_PROCESS_FINISHED_READING;
}
/*
* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
* to far.
*/
int ssl3_take_mac(SSL *s)
{
const char *sender;
size_t slen;
if (!s->server) {
sender = s->method->ssl3_enc->server_finished_label;
slen = s->method->ssl3_enc->server_finished_label_len;
} else {
sender = s->method->ssl3_enc->client_finished_label;
slen = s->method->ssl3_enc->client_finished_label_len;
}
s->s3->tmp.peer_finish_md_len =
s->method->ssl3_enc->final_finish_mac(s, sender, slen,
s->s3->tmp.peer_finish_md);
if (s->s3->tmp.peer_finish_md_len == 0) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
{
size_t remain;
remain = PACKET_remaining(pkt);
/*
* 'Change Cipher Spec' is just a single byte, which should already have
* been consumed by ssl_get_message() so there should be no bytes left,
* unless we're using DTLS1_BAD_VER, which has an extra 2 bytes
*/
if (SSL_IS_DTLS(s)) {
if ((s->version == DTLS1_BAD_VER
&& remain != DTLS1_CCS_HEADER_LENGTH + 1)
|| (s->version != DTLS1_BAD_VER
&& remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
SSL_R_BAD_CHANGE_CIPHER_SPEC);
return MSG_PROCESS_ERROR;
}
} else {
if (remain != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
SSL_R_BAD_CHANGE_CIPHER_SPEC);
return MSG_PROCESS_ERROR;
}
}
/* Check we have a cipher to change to */
if (s->s3->tmp.new_cipher == NULL) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
return MSG_PROCESS_ERROR;
}
s->s3->change_cipher_spec = 1;
if (!ssl3_do_change_cipher_spec(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
if (SSL_IS_DTLS(s)) {
dtls1_reset_seq_numbers(s, SSL3_CC_READ);
if (s->version == DTLS1_BAD_VER)
s->d1->handshake_read_seq++;
#ifndef OPENSSL_NO_SCTP
/*
* Remember that a CCS has been received, so that an old key of
* SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no
* SCTP is used
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
#endif
}
return MSG_PROCESS_CONTINUE_READING;
}
MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
{
size_t md_len;
/* This is a real handshake so make sure we clean it up at the end */
if (s->server) {
/*
* 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 (s->post_handshake_auth != SSL_PHA_REQUESTED)
s->statem.cleanuphand = 1;
if (SSL_IS_TLS13(s) && !tls13_save_handshake_digest_for_pha(s)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
}
/*
* In TLSv1.3 a Finished message signals a key change so the end of the
* message must be 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_PROCESS_FINISHED,
SSL_R_NOT_ON_RECORD_BOUNDARY);
return MSG_PROCESS_ERROR;
}
/* If this occurs, we have missed a message */
if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
SSL_R_GOT_A_FIN_BEFORE_A_CCS);
return MSG_PROCESS_ERROR;
}
s->s3->change_cipher_spec = 0;
md_len = s->s3->tmp.peer_finish_md_len;
if (md_len != PACKET_remaining(pkt)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_FINISHED,
SSL_R_BAD_DIGEST_LENGTH);
return MSG_PROCESS_ERROR;
}
if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md,
md_len) != 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_FINISHED,
SSL_R_DIGEST_CHECK_FAILED);
return MSG_PROCESS_ERROR;
}
/*
* Copy the finished so we can use it for renegotiation checks
*/
if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_FINISHED,
ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
if (s->server) {
memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md,
md_len);
s->s3->previous_client_finished_len = md_len;
} else {
memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md,
md_len);
s->s3->previous_server_finished_len = md_len;
}
/*
* In TLS1.3 we also have to change cipher state and do any final processing
* of the initial server flight (if we are a client)
*/
if (SSL_IS_TLS13(s)) {
if (s->server) {
if (s->post_handshake_auth != SSL_PHA_REQUESTED &&
!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
} else {
if (!s->method->ssl3_enc->generate_master_secret(s,
s->master_secret, s->handshake_secret, 0,
&s->session->master_key_length)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
if (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
if (!tls_process_initial_server_flight(s)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
}
}
return MSG_PROCESS_FINISHED_READING;
}
int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
{
if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
/* Add a certificate to the WPACKET */
static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain)
{
int len;
unsigned char *outbytes;
len = i2d_X509(x, NULL);
if (len < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
ERR_R_BUF_LIB);
return 0;
}
if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes)
|| i2d_X509(x, &outbytes) != len) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (SSL_IS_TLS13(s)
&& !tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_CERTIFICATE, x,
chain)) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
/* Add certificate chain to provided WPACKET */
static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
{
int i, chain_count;
X509 *x;
STACK_OF(X509) *extra_certs;
STACK_OF(X509) *chain = NULL;
X509_STORE *chain_store;
if (cpk == NULL || cpk->x509 == NULL)
return 1;
x = cpk->x509;
/*
* If we have a certificate specific chain use it, else use parent ctx.
*/
if (cpk->chain != NULL)
extra_certs = cpk->chain;
else
extra_certs = s->ctx->extra_certs;
if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
chain_store = NULL;
else if (s->cert->chain_store)
chain_store = s->cert->chain_store;
else
chain_store = s->ctx->cert_store;
if (chain_store != NULL) {
X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
if (xs_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
ERR_R_MALLOC_FAILURE);
return 0;
}
if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
X509_STORE_CTX_free(xs_ctx);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
ERR_R_X509_LIB);
return 0;
}
/*
* It is valid for the chain not to be complete (because normally we
* don't include the root cert in the chain). Therefore we deliberately
* ignore the error return from this call. We're not actually verifying
* the cert - we're just building as much of the chain as we can
*/
(void)X509_verify_cert(xs_ctx);
/* Don't leave errors in the queue */
ERR_clear_error();
chain = X509_STORE_CTX_get0_chain(xs_ctx);
i = ssl_security_cert_chain(s, chain, NULL, 0);
if (i != 1) {
#if 0
/* Dummy error calls so mkerr generates them */
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
#endif
X509_STORE_CTX_free(xs_ctx);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
return 0;
}
chain_count = sk_X509_num(chain);
for (i = 0; i < chain_count; i++) {
x = sk_X509_value(chain, i);
if (!ssl_add_cert_to_wpacket(s, pkt, x, i)) {
/* SSLfatal() already called */
X509_STORE_CTX_free(xs_ctx);
return 0;
}
}
X509_STORE_CTX_free(xs_ctx);
} else {
i = ssl_security_cert_chain(s, extra_certs, x, 0);
if (i != 1) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
return 0;
}
if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) {
/* SSLfatal() already called */
return 0;
}
for (i = 0; i < sk_X509_num(extra_certs); i++) {
x = sk_X509_value(extra_certs, i);
if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1)) {
/* SSLfatal() already called */
return 0;
}
}
}
return 1;
}
unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
{
if (!WPACKET_start_sub_packet_u24(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!ssl_add_cert_chain(s, pkt, cpk))
return 0;
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
/*
* Tidy up after the end of a handshake. In the case of SCTP this may result
* in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is
* freed up as well.
*/
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
{
void (*cb) (const SSL *ssl, int type, int val) = NULL;
if (clearbufs) {
if (!SSL_IS_DTLS(s)) {
/*
* We don't do this in DTLS because we may still need the init_buf
* in case there are any unexpected retransmits
*/
BUF_MEM_free(s->init_buf);
s->init_buf = NULL;
}
if (!ssl_free_wbio_buffer(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_FINISH_HANDSHAKE,
ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
s->init_num = 0;
}
if (SSL_IS_TLS13(s) && !s->server
&& s->post_handshake_auth == SSL_PHA_REQUESTED)
s->post_handshake_auth = SSL_PHA_EXT_SENT;
/*
* Only set if there was a Finished message and this isn't after a TLSv1.3
* post handshake exchange
*/
if (s->statem.cleanuphand) {
/* skipped if we just sent a HelloRequest */
s->renegotiate = 0;
s->new_session = 0;
s->statem.cleanuphand = 0;
s->ext.ticket_expected = 0;
ssl3_cleanup_key_block(s);
if (s->server) {
/*
* In TLSv1.3 we update the cache as part of constructing the
* NewSessionTicket
*/
if (!SSL_IS_TLS13(s))
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
/* N.B. s->ctx may not equal s->session_ctx */
tsan_counter(&s->ctx->stats.sess_accept_good);
s->handshake_func = ossl_statem_accept;
if (SSL_IS_DTLS(s) && !s->hit) {
/*
* We are finishing after the client. We start the timer going
* in case there are any retransmits of our final flight
* required.
*/
dtls1_start_timer(s);
}
} else {
if (SSL_IS_TLS13(s)) {
/*
* We encourage applications to only use TLSv1.3 tickets once,
* so we remove this one from the cache.
*/
if ((s->session_ctx->session_cache_mode
& SSL_SESS_CACHE_CLIENT) != 0)
SSL_CTX_remove_session(s->session_ctx, s->session);
} else {
/*
* In TLSv1.3 we update the cache as part of processing the
* NewSessionTicket
*/
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
}
if (s->hit)
tsan_counter(&s->session_ctx->stats.sess_hit);
s->handshake_func = ossl_statem_connect;
tsan_counter(&s->session_ctx->stats.sess_connect_good);
if (SSL_IS_DTLS(s) && s->hit) {
/*
* We are finishing after the server. We start the timer going
* in case there are any retransmits of our final flight
* required.
*/
dtls1_start_timer(s);
}
}
if (SSL_IS_DTLS(s)) {
/* done with handshaking */
s->d1->handshake_read_seq = 0;
s->d1->handshake_write_seq = 0;
s->d1->next_handshake_write_seq = 0;
dtls1_clear_received_buffer(s);
}
}
if (s->info_callback != NULL)
cb = s->info_callback;
else if (s->ctx->info_callback != NULL)
cb = s->ctx->info_callback;
/* The callback may expect us to not be in init at handshake done */
ossl_statem_set_in_init(s, 0);
if (cb != NULL)
cb(s, SSL_CB_HANDSHAKE_DONE, 1);
if (!stop) {
/* If we've got more work to do we go back into init */
ossl_statem_set_in_init(s, 1);
return WORK_FINISHED_CONTINUE;
}
return WORK_FINISHED_STOP;
}
int tls_get_message_header(SSL *s, int *mt)
{
/* s->init_num < SSL3_HM_HEADER_LENGTH */
int skip_message, i, recvd_type;
unsigned char *p;
size_t l, readbytes;
p = (unsigned char *)s->init_buf->data;
do {
while (s->init_num < SSL3_HM_HEADER_LENGTH) {
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
&p[s->init_num],
SSL3_HM_HEADER_LENGTH - s->init_num,
0, &readbytes);
if (i <= 0) {
s->rwstate = SSL_READING;
return 0;
}
if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
/*
* A ChangeCipherSpec must be a single byte and may not occur
* in the middle of a handshake message.
*/
if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_TLS_GET_MESSAGE_HEADER,
SSL_R_BAD_CHANGE_CIPHER_SPEC);
return 0;
}
if (s->statem.hand_state == TLS_ST_BEFORE
&& (s->s3->flags & TLS1_FLAGS_STATELESS) != 0) {
/*
* We are stateless and we received a CCS. Probably this is
* from a client between the first and second ClientHellos.
* We should ignore this, but return an error because we do
* not return success until we see the second ClientHello
* with a valid cookie.
*/
return 0;
}
s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
s->init_num = readbytes - 1;
s->init_msg = s->init_buf->data;
s->s3->tmp.message_size = readbytes;
return 1;
} else if (recvd_type != SSL3_RT_HANDSHAKE) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_TLS_GET_MESSAGE_HEADER,
SSL_R_CCS_RECEIVED_EARLY);
return 0;
}
s->init_num += readbytes;
}
skip_message = 0;
if (!s->server)
if (s->statem.hand_state != TLS_ST_OK
&& p[0] == SSL3_MT_HELLO_REQUEST)
/*
* The server may always send 'Hello Request' messages --
* we are doing a handshake anyway now, so ignore them if
* their format is correct. Does not count for 'Finished'
* MAC.
*/
if (p[1] == 0 && p[2] == 0 && p[3] == 0) {
s->init_num = 0;
skip_message = 1;
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
p, SSL3_HM_HEADER_LENGTH, s,
s->msg_callback_arg);
}
} while (skip_message);
/* s->init_num == SSL3_HM_HEADER_LENGTH */
*mt = *p;
s->s3->tmp.message_type = *(p++);
if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
/*
* Only happens with SSLv3+ in an SSLv2 backward compatible
* ClientHello
*
* Total message size is the remaining record bytes to read
* plus the SSL3_HM_HEADER_LENGTH bytes that we already read
*/
l = RECORD_LAYER_get_rrec_length(&s->rlayer)
+ SSL3_HM_HEADER_LENGTH;
s->s3->tmp.message_size = l;
s->init_msg = s->init_buf->data;
s->init_num = SSL3_HM_HEADER_LENGTH;
} else {
n2l3(p, l);
/* BUF_MEM_grow takes an 'int' parameter */
if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_GET_MESSAGE_HEADER,
SSL_R_EXCESSIVE_MESSAGE_SIZE);
return 0;
}
s->s3->tmp.message_size = l;
s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
s->init_num = 0;
}
return 1;
}
int tls_get_message_body(SSL *s, size_t *len)
{
size_t n, readbytes;
unsigned char *p;
int i;
if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) {
/* We've already read everything in */
*len = (unsigned long)s->init_num;
return 1;
}
p = s->init_msg;
n = s->s3->tmp.message_size - s->init_num;
while (n > 0) {
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
&p[s->init_num], n, 0, &readbytes);
if (i <= 0) {
s->rwstate = SSL_READING;
*len = 0;
return 0;
}
s->init_num += readbytes;
n -= readbytes;
}
/*
* If receiving Finished, record MAC of prior handshake messages for
* Finished verification.
*/
if (*(s->init_buf->data) == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
/* SSLfatal() already called */
*len = 0;
return 0;
}
/* Feed this message into MAC computation. */
if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
s->init_num)) {
/* SSLfatal() already called */
*len = 0;
return 0;
}
if (s->msg_callback)
s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data,
(size_t)s->init_num, s, s->msg_callback_arg);
} else {
/*
* We defer feeding in the HRR until later. We'll do it as part of
* processing the message
* The TLsv1.3 handshake transcript stops at the ClientFinished
* message.
*/
#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
/* KeyUpdate and NewSessionTicket do not need to be added */
if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET
&& s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) {
if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO
|| s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
|| memcmp(hrrrandom,
s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
SSL3_RANDOM_SIZE) != 0) {
if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
s->init_num + SSL3_HM_HEADER_LENGTH)) {
/* SSLfatal() already called */
*len = 0;
return 0;
}
}
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
(size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s,
s->msg_callback_arg);
}
*len = s->init_num;
return 1;
}
static const X509ERR2ALERT x509table[] = {
{X509_V_ERR_APPLICATION_VERIFICATION, SSL_AD_HANDSHAKE_FAILURE},
{X509_V_ERR_CA_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_CA_MD_TOO_WEAK, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_CERT_CHAIN_TOO_LONG, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_CERT_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED},
{X509_V_ERR_CERT_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_CERT_REJECTED, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_CERT_REVOKED, SSL_AD_CERTIFICATE_REVOKED},
{X509_V_ERR_CERT_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR},
{X509_V_ERR_CERT_UNTRUSTED, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_CRL_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED},
{X509_V_ERR_CRL_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_CRL_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR},
{X509_V_ERR_DANE_NO_MATCH, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_EE_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_EMAIL_MISMATCH, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_HOSTNAME_MISMATCH, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_INVALID_CA, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_INVALID_CALL, SSL_AD_INTERNAL_ERROR},
{X509_V_ERR_INVALID_PURPOSE, SSL_AD_UNSUPPORTED_CERTIFICATE},
{X509_V_ERR_IP_ADDRESS_MISMATCH, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_OUT_OF_MEM, SSL_AD_INTERNAL_ERROR},
{X509_V_ERR_PATH_LENGTH_EXCEEDED, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_STORE_LOOKUP, SSL_AD_INTERNAL_ERROR},
{X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_UNABLE_TO_GET_CRL, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, SSL_AD_UNKNOWN_CA},
{X509_V_ERR_UNSPECIFIED, SSL_AD_INTERNAL_ERROR},
/* Last entry; return this if we don't find the value above. */
{X509_V_OK, SSL_AD_CERTIFICATE_UNKNOWN}
};
int ssl_x509err2alert(int x509err)
{
const X509ERR2ALERT *tp;
for (tp = x509table; tp->x509err != X509_V_OK; ++tp)
if (tp->x509err == x509err)
break;
return tp->alert;
}
int ssl_allow_compression(SSL *s)
{
if (s->options & SSL_OP_NO_COMPRESSION)
return 0;
return ssl_security(s, SSL_SECOP_COMPRESSION, 0, 0, NULL);
}
static int version_cmp(const SSL *s, int a, int b)
{
int dtls = SSL_IS_DTLS(s);
if (a == b)
return 0;
if (!dtls)
return a < b ? -1 : 1;
return DTLS_VERSION_LT(a, b) ? -1 : 1;
}
typedef struct {
int version;
const SSL_METHOD *(*cmeth) (void);
const SSL_METHOD *(*smeth) (void);
} version_info;
#if TLS_MAX_VERSION != TLS1_3_VERSION
# error Code needs update for TLS_method() support beyond TLS1_3_VERSION.
#endif
/* Must be in order high to low */
static const version_info tls_version_table[] = {
#ifndef OPENSSL_NO_TLS1_3
{TLS1_3_VERSION, tlsv1_3_client_method, tlsv1_3_server_method},
#else
{TLS1_3_VERSION, NULL, NULL},
#endif
#ifndef OPENSSL_NO_TLS1_2
{TLS1_2_VERSION, tlsv1_2_client_method, tlsv1_2_server_method},
#else
{TLS1_2_VERSION, NULL, NULL},
#endif
#ifndef OPENSSL_NO_TLS1_1
{TLS1_1_VERSION, tlsv1_1_client_method, tlsv1_1_server_method},
#else
{TLS1_1_VERSION, NULL, NULL},
#endif
#ifndef OPENSSL_NO_TLS1
{TLS1_VERSION, tlsv1_client_method, tlsv1_server_method},
#else
{TLS1_VERSION, NULL, NULL},
#endif
#ifndef OPENSSL_NO_SSL3
{SSL3_VERSION, sslv3_client_method, sslv3_server_method},
#else
{SSL3_VERSION, NULL, NULL},
#endif
{0, NULL, NULL},
};
#if DTLS_MAX_VERSION != DTLS1_2_VERSION
# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION.
#endif
/* Must be in order high to low */
static const version_info dtls_version_table[] = {
#ifndef OPENSSL_NO_DTLS1_2
{DTLS1_2_VERSION, dtlsv1_2_client_method, dtlsv1_2_server_method},
#else
{DTLS1_2_VERSION, NULL, NULL},
#endif
#ifndef OPENSSL_NO_DTLS1
{DTLS1_VERSION, dtlsv1_client_method, dtlsv1_server_method},
{DTLS1_BAD_VER, dtls_bad_ver_client_method, NULL},
#else
{DTLS1_VERSION, NULL, NULL},
{DTLS1_BAD_VER, NULL, NULL},
#endif
{0, NULL, NULL},
};
/*
* ssl_method_error - Check whether an SSL_METHOD is enabled.
*
* @s: The SSL handle for the candidate method
* @method: the intended method.
*
* Returns 0 on success, or an SSL error reason on failure.
*/
static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
{
int version = method->version;
if ((s->min_proto_version != 0 &&
version_cmp(s, version, s->min_proto_version) < 0) ||
ssl_security(s, SSL_SECOP_VERSION, 0, version, NULL) == 0)
return SSL_R_VERSION_TOO_LOW;
if (s->max_proto_version != 0 &&
version_cmp(s, version, s->max_proto_version) > 0)
return SSL_R_VERSION_TOO_HIGH;
if ((s->options & method->mask) != 0)
return SSL_R_UNSUPPORTED_PROTOCOL;
if ((method->flags & SSL_METHOD_NO_SUITEB) != 0 && tls1_suiteb(s))
return SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE;
return 0;
}
/*
* Only called by servers. Returns 1 if the server has a TLSv1.3 capable
* certificate type, or has PSK or a certificate callback configured. Otherwise
* returns 0.
*/
static int is_tls13_capable(const SSL *s)
{
int i;
+#ifndef OPENSSL_NO_EC
+ int curve;
+ EC_KEY *eckey;
+#endif
#ifndef OPENSSL_NO_PSK
if (s->psk_server_callback != NULL)
return 1;
#endif
if (s->psk_find_session_cb != NULL || s->cert->cert_cb != NULL)
return 1;
for (i = 0; i < SSL_PKEY_NUM; i++) {
/* Skip over certs disallowed for TLSv1.3 */
switch (i) {
case SSL_PKEY_DSA_SIGN:
case SSL_PKEY_GOST01:
case SSL_PKEY_GOST12_256:
case SSL_PKEY_GOST12_512:
continue;
default:
break;
}
- if (ssl_has_cert(s, i))
+ if (!ssl_has_cert(s, i))
+ continue;
+#ifndef OPENSSL_NO_EC
+ if (i != SSL_PKEY_ECC)
+ return 1;
+ /*
+ * Prior to TLSv1.3 sig algs allowed any curve to be used. TLSv1.3 is
+ * more restrictive so check that our sig algs are consistent with this
+ * EC cert. See section 4.2.3 of RFC8446.
+ */
+ eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
+ if (eckey == NULL)
+ continue;
+ curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+ if (tls_check_sigalg_curve(s, curve))
return 1;
+#else
+ return 1;
+#endif
}
return 0;
}
/*
* ssl_version_supported - Check that the specified `version` is supported by
* `SSL *` instance
*
* @s: The SSL handle for the candidate method
* @version: Protocol version to test against
*
* Returns 1 when supported, otherwise 0
*/
int ssl_version_supported(const SSL *s, int version, const SSL_METHOD **meth)
{
const version_info *vent;
const version_info *table;
switch (s->method->version) {
default:
/* Version should match method version for non-ANY method */
return version_cmp(s, version, s->version) == 0;
case TLS_ANY_VERSION:
table = tls_version_table;
break;
case DTLS_ANY_VERSION:
table = dtls_version_table;
break;
}
for (vent = table;
vent->version != 0 && version_cmp(s, version, vent->version) <= 0;
++vent) {
if (vent->cmeth != NULL
&& version_cmp(s, version, vent->version) == 0
&& ssl_method_error(s, vent->cmeth()) == 0
&& (!s->server
|| version != TLS1_3_VERSION
|| is_tls13_capable(s))) {
if (meth != NULL)
*meth = vent->cmeth();
return 1;
}
}
return 0;
}
/*
* ssl_check_version_downgrade - In response to RFC7507 SCSV version
* fallback indication from a client check whether we're using the highest
* supported protocol version.
*
* @s server SSL handle.
*
* Returns 1 when using the highest enabled version, 0 otherwise.
*/
int ssl_check_version_downgrade(SSL *s)
{
const version_info *vent;
const version_info *table;
/*
* Check that the current protocol is the highest enabled version
* (according to s->ctx->method, as version negotiation may have changed
* s->method).
*/
if (s->version == s->ctx->method->version)
return 1;
/*
* Apparently we're using a version-flexible SSL_METHOD (not at its
* highest protocol version).
*/
if (s->ctx->method->version == TLS_method()->version)
table = tls_version_table;
else if (s->ctx->method->version == DTLS_method()->version)
table = dtls_version_table;
else {
/* Unexpected state; fail closed. */
return 0;
}
for (vent = table; vent->version != 0; ++vent) {
if (vent->smeth != NULL && ssl_method_error(s, vent->smeth()) == 0)
return s->version == vent->version;
}
return 0;
}
/*
* ssl_set_version_bound - set an upper or lower bound on the supported (D)TLS
* protocols, provided the initial (D)TLS method is version-flexible. This
* function sanity-checks the proposed value and makes sure the method is
* version-flexible, then sets the limit if all is well.
*
* @method_version: The version of the current SSL_METHOD.
* @version: the intended limit.
* @bound: pointer to limit to be updated.
*
* Returns 1 on success, 0 on failure.
*/
int ssl_set_version_bound(int method_version, int version, int *bound)
{
if (version == 0) {
*bound = version;
return 1;
}
/*-
* Restrict TLS methods to TLS protocol versions.
* Restrict DTLS methods to DTLS protocol versions.
* Note, DTLS version numbers are decreasing, use comparison macros.
*
* Note that for both lower-bounds we use explicit versions, not
* (D)TLS_MIN_VERSION. This is because we don't want to break user
* configurations. If the MIN (supported) version ever rises, the user's
* "floor" remains valid even if no longer available. We don't expect the
* MAX ceiling to ever get lower, so making that variable makes sense.
*/
switch (method_version) {
default:
/*
* XXX For fixed version methods, should we always fail and not set any
* bounds, always succeed and not set any bounds, or set the bounds and
* arrange to fail later if they are not met? At present fixed-version
* methods are not subject to controls that disable individual protocol
* versions.
*/
return 0;
case TLS_ANY_VERSION:
if (version < SSL3_VERSION || version > TLS_MAX_VERSION)
return 0;
break;
case DTLS_ANY_VERSION:
if (DTLS_VERSION_GT(version, DTLS_MAX_VERSION) ||
DTLS_VERSION_LT(version, DTLS1_BAD_VER))
return 0;
break;
}
*bound = version;
return 1;
}
static void check_for_downgrade(SSL *s, int vers, DOWNGRADE *dgrd)
{
if (vers == TLS1_2_VERSION
&& ssl_version_supported(s, TLS1_3_VERSION, NULL)) {
*dgrd = DOWNGRADE_TO_1_2;
} else if (!SSL_IS_DTLS(s)
&& vers < TLS1_2_VERSION
/*
* We need to ensure that a server that disables TLSv1.2
* (creating a hole between TLSv1.3 and TLSv1.1) can still
* complete handshakes with clients that support TLSv1.2 and
* below. Therefore we do not enable the sentinel if TLSv1.3 is
* enabled and TLSv1.2 is not.
*/
&& ssl_version_supported(s, TLS1_2_VERSION, NULL)) {
*dgrd = DOWNGRADE_TO_1_1;
} else {
*dgrd = DOWNGRADE_NONE;
}
}
/*
* ssl_choose_server_version - Choose server (D)TLS version. Called when the
* client HELLO is received to select the final server protocol version and
* the version specific method.
*
* @s: server SSL handle.
*
* Returns 0 on success or an SSL error reason number on failure.
*/
int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
{
/*-
* With version-flexible methods we have an initial state with:
*
* s->method->version == (D)TLS_ANY_VERSION,
* s->version == (D)TLS_MAX_VERSION.
*
* So we detect version-flexible methods via the method version, not the
* handle version.
*/
int server_version = s->method->version;
int client_version = hello->legacy_version;
const version_info *vent;
const version_info *table;
int disabled = 0;
RAW_EXTENSION *suppversions;
s->client_version = client_version;
switch (server_version) {
default:
if (!SSL_IS_TLS13(s)) {
if (version_cmp(s, client_version, s->version) < 0)
return SSL_R_WRONG_SSL_VERSION;
*dgrd = DOWNGRADE_NONE;
/*
* If this SSL handle is not from a version flexible method we don't
* (and never did) check min/max FIPS or Suite B constraints. Hope
* that's OK. It is up to the caller to not choose fixed protocol
* versions they don't want. If not, then easy to fix, just return
* ssl_method_error(s, s->method)
*/
return 0;
}
/*
* Fall through if we are TLSv1.3 already (this means we must be after
* a HelloRetryRequest
*/
/* fall thru */
case TLS_ANY_VERSION:
table = tls_version_table;
break;
case DTLS_ANY_VERSION:
table = dtls_version_table;
break;
}
suppversions = &hello->pre_proc_exts[TLSEXT_IDX_supported_versions];
/* If we did an HRR then supported versions is mandatory */
if (!suppversions->present && s->hello_retry_request != SSL_HRR_NONE)
return SSL_R_UNSUPPORTED_PROTOCOL;
if (suppversions->present && !SSL_IS_DTLS(s)) {
unsigned int candidate_vers = 0;
unsigned int best_vers = 0;
const SSL_METHOD *best_method = NULL;
PACKET versionslist;
suppversions->parsed = 1;
if (!PACKET_as_length_prefixed_1(&suppversions->data, &versionslist)) {
/* Trailing or invalid data? */
return SSL_R_LENGTH_MISMATCH;
}
/*
* The TLSv1.3 spec says the client MUST set this to TLS1_2_VERSION.
* The spec only requires servers to check that it isn't SSLv3:
* "Any endpoint receiving a Hello message with
* ClientHello.legacy_version or ServerHello.legacy_version set to
* 0x0300 MUST abort the handshake with a "protocol_version" alert."
* We are slightly stricter and require that it isn't SSLv3 or lower.
* We tolerate TLSv1 and TLSv1.1.
*/
if (client_version <= SSL3_VERSION)
return SSL_R_BAD_LEGACY_VERSION;
while (PACKET_get_net_2(&versionslist, &candidate_vers)) {
if (version_cmp(s, candidate_vers, best_vers) <= 0)
continue;
if (ssl_version_supported(s, candidate_vers, &best_method))
best_vers = candidate_vers;
}
if (PACKET_remaining(&versionslist) != 0) {
/* Trailing data? */
return SSL_R_LENGTH_MISMATCH;
}
if (best_vers > 0) {
if (s->hello_retry_request != SSL_HRR_NONE) {
/*
* This is after a HelloRetryRequest so we better check that we
* negotiated TLSv1.3
*/
if (best_vers != TLS1_3_VERSION)
return SSL_R_UNSUPPORTED_PROTOCOL;
return 0;
}
check_for_downgrade(s, best_vers, dgrd);
s->version = best_vers;
s->method = best_method;
return 0;
}
return SSL_R_UNSUPPORTED_PROTOCOL;
}
/*
* If the supported versions extension isn't present, then the highest
* version we can negotiate is TLSv1.2
*/
if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0)
client_version = TLS1_2_VERSION;
/*
* No supported versions extension, so we just use the version supplied in
* the ClientHello.
*/
for (vent = table; vent->version != 0; ++vent) {
const SSL_METHOD *method;
if (vent->smeth == NULL ||
version_cmp(s, client_version, vent->version) < 0)
continue;
method = vent->smeth();
if (ssl_method_error(s, method) == 0) {
check_for_downgrade(s, vent->version, dgrd);
s->version = vent->version;
s->method = method;
return 0;
}
disabled = 1;
}
return disabled ? SSL_R_UNSUPPORTED_PROTOCOL : SSL_R_VERSION_TOO_LOW;
}
/*
* ssl_choose_client_version - Choose client (D)TLS version. Called when the
* server HELLO is received to select the final client protocol version and
* the version specific method.
*
* @s: client SSL handle.
* @version: The proposed version from the server's HELLO.
* @extensions: The extensions received
*
* Returns 1 on success or 0 on error.
*/
int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
{
const version_info *vent;
const version_info *table;
int ret, ver_min, ver_max, real_max, origv;
origv = s->version;
s->version = version;
/* This will overwrite s->version if the extension is present */
if (!tls_parse_extension(s, TLSEXT_IDX_supported_versions,
SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_SERVER_HELLO, extensions,
NULL, 0)) {
s->version = origv;
return 0;
}
if (s->hello_retry_request != SSL_HRR_NONE
&& s->version != TLS1_3_VERSION) {
s->version = origv;
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
SSL_R_WRONG_SSL_VERSION);
return 0;
}
switch (s->method->version) {
default:
if (s->version != s->method->version) {
s->version = origv;
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
SSL_R_WRONG_SSL_VERSION);
return 0;
}
/*
* If this SSL handle is not from a version flexible method we don't
* (and never did) check min/max, FIPS or Suite B constraints. Hope
* that's OK. It is up to the caller to not choose fixed protocol
* versions they don't want. If not, then easy to fix, just return
* ssl_method_error(s, s->method)
*/
return 1;
case TLS_ANY_VERSION:
table = tls_version_table;
break;
case DTLS_ANY_VERSION:
table = dtls_version_table;
break;
}
ret = ssl_get_min_max_version(s, &ver_min, &ver_max, &real_max);
if (ret != 0) {
s->version = origv;
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_F_SSL_CHOOSE_CLIENT_VERSION, ret);
return 0;
}
if (SSL_IS_DTLS(s) ? DTLS_VERSION_LT(s->version, ver_min)
: s->version < ver_min) {
s->version = origv;
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
return 0;
} else if (SSL_IS_DTLS(s) ? DTLS_VERSION_GT(s->version, ver_max)
: s->version > ver_max) {
s->version = origv;
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
return 0;
}
if ((s->mode & SSL_MODE_SEND_FALLBACK_SCSV) == 0)
real_max = ver_max;
/* Check for downgrades */
if (s->version == TLS1_2_VERSION && real_max > s->version) {
if (memcmp(tls12downgrade,
s->s3->server_random + SSL3_RANDOM_SIZE
- sizeof(tls12downgrade),
sizeof(tls12downgrade)) == 0) {
s->version = origv;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
SSL_R_INAPPROPRIATE_FALLBACK);
return 0;
}
} else if (!SSL_IS_DTLS(s)
&& s->version < TLS1_2_VERSION
&& real_max > s->version) {
if (memcmp(tls11downgrade,
s->s3->server_random + SSL3_RANDOM_SIZE
- sizeof(tls11downgrade),
sizeof(tls11downgrade)) == 0) {
s->version = origv;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
SSL_R_INAPPROPRIATE_FALLBACK);
return 0;
}
}
for (vent = table; vent->version != 0; ++vent) {
if (vent->cmeth == NULL || s->version != vent->version)
continue;
s->method = vent->cmeth();
return 1;
}
s->version = origv;
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
SSL_R_UNSUPPORTED_PROTOCOL);
return 0;
}
/*
* ssl_get_min_max_version - get minimum and maximum protocol version
* @s: The SSL connection
* @min_version: The minimum supported version
* @max_version: The maximum supported version
* @real_max: The highest version below the lowest compile time version hole
* where that hole lies above at least one run-time enabled
* protocol.
*
* Work out what version we should be using for the initial ClientHello if the
* version is initially (D)TLS_ANY_VERSION. We apply any explicit SSL_OP_NO_xxx
* options, the MinProtocol and MaxProtocol configuration commands, any Suite B
* constraints and any floor imposed by the security level here,
* so we don't advertise the wrong protocol version to only reject the outcome later.
*
* Computing the right floor matters. If, e.g., TLS 1.0 and 1.2 are enabled,
* TLS 1.1 is disabled, but the security level, Suite-B and/or MinProtocol
* only allow TLS 1.2, we want to advertise TLS1.2, *not* TLS1.
*
* Returns 0 on success or an SSL error reason number on failure. On failure
* min_version and max_version will also be set to 0.
*/
int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version,
int *real_max)
{
int version, tmp_real_max;
int hole;
const SSL_METHOD *single = NULL;
const SSL_METHOD *method;
const version_info *table;
const version_info *vent;
switch (s->method->version) {
default:
/*
* If this SSL handle is not from a version flexible method we don't
* (and never did) check min/max FIPS or Suite B constraints. Hope
* that's OK. It is up to the caller to not choose fixed protocol
* versions they don't want. If not, then easy to fix, just return
* ssl_method_error(s, s->method)
*/
*min_version = *max_version = s->version;
/*
* Providing a real_max only makes sense where we're using a version
* flexible method.
*/
if (!ossl_assert(real_max == NULL))
return ERR_R_INTERNAL_ERROR;
return 0;
case TLS_ANY_VERSION:
table = tls_version_table;
break;
case DTLS_ANY_VERSION:
table = dtls_version_table;
break;
}
/*
* SSL_OP_NO_X disables all protocols above X *if* there are some protocols
* below X enabled. This is required in order to maintain the "version
* capability" vector contiguous. Any versions with a NULL client method
* (protocol version client is disabled at compile-time) is also a "hole".
*
* Our initial state is hole == 1, version == 0. That is, versions above
* the first version in the method table are disabled (a "hole" above
* the valid protocol entries) and we don't have a selected version yet.
*
* Whenever "hole == 1", and we hit an enabled method, its version becomes
* the selected version, and the method becomes a candidate "single"
* method. We're no longer in a hole, so "hole" becomes 0.
*
* If "hole == 0" and we hit an enabled method, then "single" is cleared,
* as we support a contiguous range of at least two methods. If we hit
* a disabled method, then hole becomes true again, but nothing else
* changes yet, because all the remaining methods may be disabled too.
* If we again hit an enabled method after the new hole, it becomes
* selected, as we start from scratch.
*/
*min_version = version = 0;
hole = 1;
if (real_max != NULL)
*real_max = 0;
tmp_real_max = 0;
for (vent = table; vent->version != 0; ++vent) {
/*
* A table entry with a NULL client method is still a hole in the
* "version capability" vector.
*/
if (vent->cmeth == NULL) {
hole = 1;
tmp_real_max = 0;
continue;
}
method = vent->cmeth();
if (hole == 1 && tmp_real_max == 0)
tmp_real_max = vent->version;
if (ssl_method_error(s, method) != 0) {
hole = 1;
} else if (!hole) {
single = NULL;
*min_version = method->version;
} else {
if (real_max != NULL && tmp_real_max != 0)
*real_max = tmp_real_max;
version = (single = method)->version;
*min_version = version;
hole = 0;
}
}
*max_version = version;
/* Fail if everything is disabled */
if (version == 0)
return SSL_R_NO_PROTOCOLS_AVAILABLE;
return 0;
}
/*
* ssl_set_client_hello_version - Work out what version we should be using for
* the initial ClientHello.legacy_version field.
*
* @s: client SSL handle.
*
* Returns 0 on success or an SSL error reason number on failure.
*/
int ssl_set_client_hello_version(SSL *s)
{
int ver_min, ver_max, ret;
/*
* In a renegotiation we always send the same client_version that we sent
* last time, regardless of which version we eventually negotiated.
*/
if (!SSL_IS_FIRST_HANDSHAKE(s))
return 0;
ret = ssl_get_min_max_version(s, &ver_min, &ver_max, NULL);
if (ret != 0)
return ret;
s->version = ver_max;
/* TLS1.3 always uses TLS1.2 in the legacy_version field */
if (!SSL_IS_DTLS(s) && ver_max > TLS1_2_VERSION)
ver_max = TLS1_2_VERSION;
s->client_version = ver_max;
return 0;
}
/*
* Checks a list of |groups| to determine if the |group_id| is in it. If it is
* and |checkallow| is 1 then additionally check if the group is allowed to be
* used. Returns 1 if the group is in the list (and allowed if |checkallow| is
* 1) or 0 otherwise.
*/
#ifndef OPENSSL_NO_EC
int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
size_t num_groups, int checkallow)
{
size_t i;
if (groups == NULL || num_groups == 0)
return 0;
for (i = 0; i < num_groups; i++) {
uint16_t group = groups[i];
if (group_id == group
&& (!checkallow
|| tls_curve_allowed(s, group, SSL_SECOP_CURVE_CHECK))) {
return 1;
}
}
return 0;
}
#endif
/* Replace ClientHello1 in the transcript hash with a synthetic message */
int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
size_t hashlen, const unsigned char *hrr,
size_t hrrlen)
{
unsigned char hashvaltmp[EVP_MAX_MD_SIZE];
unsigned char msghdr[SSL3_HM_HEADER_LENGTH];
memset(msghdr, 0, sizeof(msghdr));
if (hashval == NULL) {
hashval = hashvaltmp;
hashlen = 0;
/* Get the hash of the initial ClientHello */
if (!ssl3_digest_cached_records(s, 0)
|| !ssl_handshake_hash(s, hashvaltmp, sizeof(hashvaltmp),
&hashlen)) {
/* SSLfatal() already called */
return 0;
}
}
/* Reinitialise the transcript hash */
if (!ssl3_init_finished_mac(s)) {
/* SSLfatal() already called */
return 0;
}
/* Inject the synthetic message_hash message */
msghdr[0] = SSL3_MT_MESSAGE_HASH;
msghdr[SSL3_HM_HEADER_LENGTH - 1] = (unsigned char)hashlen;
if (!ssl3_finish_mac(s, msghdr, SSL3_HM_HEADER_LENGTH)
|| !ssl3_finish_mac(s, hashval, hashlen)) {
/* SSLfatal() already called */
return 0;
}
/*
* Now re-inject the HRR and current message if appropriate (we just deleted
* it when we reinitialised the transcript hash above). Only necessary after
* receiving a ClientHello2 with a cookie.
*/
if (hrr != NULL
&& (!ssl3_finish_mac(s, hrr, hrrlen)
|| !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
s->s3->tmp.message_size
+ SSL3_HM_HEADER_LENGTH))) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
{
return X509_NAME_cmp(*a, *b);
}
int parse_ca_names(SSL *s, PACKET *pkt)
{
STACK_OF(X509_NAME) *ca_sk = sk_X509_NAME_new(ca_dn_cmp);
X509_NAME *xn = NULL;
PACKET cadns;
if (ca_sk == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
ERR_R_MALLOC_FAILURE);
goto err;
}
/* get the CA RDNs */
if (!PACKET_get_length_prefixed_2(pkt, &cadns)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,SSL_F_PARSE_CA_NAMES,
SSL_R_LENGTH_MISMATCH);
goto err;
}
while (PACKET_remaining(&cadns)) {
const unsigned char *namestart, *namebytes;
unsigned int name_len;
if (!PACKET_get_net_2(&cadns, &name_len)
|| !PACKET_get_bytes(&cadns, &namebytes, name_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
SSL_R_LENGTH_MISMATCH);
goto err;
}
namestart = namebytes;
if ((xn = d2i_X509_NAME(NULL, &namebytes, name_len)) == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
ERR_R_ASN1_LIB);
goto err;
}
if (namebytes != (namestart + name_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
SSL_R_CA_DN_LENGTH_MISMATCH);
goto err;
}
if (!sk_X509_NAME_push(ca_sk, xn)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
ERR_R_MALLOC_FAILURE);
goto err;
}
xn = NULL;
}
sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
s->s3->tmp.peer_ca_names = ca_sk;
return 1;
err:
sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
X509_NAME_free(xn);
return 0;
}
-int construct_ca_names(SSL *s, WPACKET *pkt)
+const STACK_OF(X509_NAME) *get_ca_names(SSL *s)
{
- const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s);
+ const STACK_OF(X509_NAME) *ca_sk = NULL;;
+
+ if (s->server) {
+ ca_sk = SSL_get_client_CA_list(s);
+ if (ca_sk != NULL && sk_X509_NAME_num(ca_sk) == 0)
+ ca_sk = NULL;
+ }
+
+ if (ca_sk == NULL)
+ ca_sk = SSL_get0_CA_list(s);
+ return ca_sk;
+}
+
+int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt)
+{
/* Start sub-packet for client CA list */
if (!WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (ca_sk != NULL) {
int i;
for (i = 0; i < sk_X509_NAME_num(ca_sk); i++) {
unsigned char *namebytes;
X509_NAME *name = sk_X509_NAME_value(ca_sk, i);
int namelen;
if (name == NULL
|| (namelen = i2d_X509_NAME(name, NULL)) < 0
|| !WPACKET_sub_allocate_bytes_u16(pkt, namelen,
&namebytes)
|| i2d_X509_NAME(name, &namebytes) != namelen) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
}
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
/* Create a buffer containing data to be signed for server key exchange */
size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
const void *param, size_t paramlen)
{
size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen;
unsigned char *tbs = OPENSSL_malloc(tbslen);
if (tbs == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS,
ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE);
memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE);
memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen);
*ptbs = tbs;
return tbslen;
}
/*
* Saves the current handshake digest for Post-Handshake Auth,
* Done after ClientFinished is processed, done exactly once
*/
int tls13_save_handshake_digest_for_pha(SSL *s)
{
if (s->pha_dgst == NULL) {
if (!ssl3_digest_cached_records(s, 1))
/* SSLfatal() already called */
return 0;
s->pha_dgst = EVP_MD_CTX_new();
if (s->pha_dgst == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!EVP_MD_CTX_copy_ex(s->pha_dgst,
s->s3->handshake_dgst)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
/*
* Restores the Post-Handshake Auth handshake digest
* Done just before sending/processing the Cert Request
*/
int tls13_restore_handshake_digest_for_pha(SSL *s)
{
if (s->pha_dgst == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!EVP_MD_CTX_copy_ex(s->s3->handshake_dgst,
s->pha_dgst)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h
index 25e56e4e8ddf..6b8cf37faa01 100644
--- a/ssl/statem/statem_locl.h
+++ b/ssl/statem/statem_locl.h
@@ -1,422 +1,423 @@
/*
* Copyright 2015-2018 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
*/
/*****************************************************************************
* *
* The following definitions are PRIVATE to the state machine. They should *
* NOT be used outside of the state machine. *
* *
*****************************************************************************/
/* Max message length definitions */
/* The spec allows for a longer length than this, but we limit it */
#define HELLO_VERIFY_REQUEST_MAX_LENGTH 258
#define END_OF_EARLY_DATA_MAX_LENGTH 0
#define SERVER_HELLO_MAX_LENGTH 20000
#define HELLO_RETRY_REQUEST_MAX_LENGTH 20000
#define ENCRYPTED_EXTENSIONS_MAX_LENGTH 20000
#define SERVER_KEY_EXCH_MAX_LENGTH 102400
#define SERVER_HELLO_DONE_MAX_LENGTH 0
#define KEY_UPDATE_MAX_LENGTH 1
#define CCS_MAX_LENGTH 1
/* Max should actually be 36 but we are generous */
#define FINISHED_MAX_LENGTH 64
/* The maximum number of incoming KeyUpdate messages we will accept */
#define MAX_KEY_UPDATE_MESSAGES 32
/* Dummy message type */
#define SSL3_MT_DUMMY -1
extern const unsigned char hrrrandom[];
/* Message processing return codes */
typedef enum {
/* Something bad happened */
MSG_PROCESS_ERROR,
/* We've finished reading - swap to writing */
MSG_PROCESS_FINISHED_READING,
/*
* We've completed the main processing of this message but there is some
* post processing to be done.
*/
MSG_PROCESS_CONTINUE_PROCESSING,
/* We've finished this message - read the next message */
MSG_PROCESS_CONTINUE_READING
} MSG_PROCESS_RETURN;
typedef int (*confunc_f) (SSL *s, WPACKET *pkt);
int ssl3_take_mac(SSL *s);
int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
size_t num_groups, int checkallow);
int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
size_t hashlen, const unsigned char *hrr,
size_t hrrlen);
int parse_ca_names(SSL *s, PACKET *pkt);
-int construct_ca_names(SSL *s, WPACKET *pkt);
+const STACK_OF(X509_NAME) *get_ca_names(SSL *s);
+int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt);
size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
const void *param, size_t paramlen);
/*
* TLS/DTLS client state machine functions
*/
int ossl_statem_client_read_transition(SSL *s, int mt);
WRITE_TRAN ossl_statem_client_write_transition(SSL *s);
WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst);
WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst);
int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
confunc_f *confunc, int *mt);
size_t ossl_statem_client_max_message_size(SSL *s);
MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt);
WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst);
/*
* TLS/DTLS server state machine functions
*/
int ossl_statem_server_read_transition(SSL *s, int mt);
WRITE_TRAN ossl_statem_server_write_transition(SSL *s);
WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst);
WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst);
int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
confunc_f *confunc,int *mt);
size_t ossl_statem_server_max_message_size(SSL *s);
MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt);
WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst);
/* Functions for getting new message data */
__owur int tls_get_message_header(SSL *s, int *mt);
__owur int tls_get_message_body(SSL *s, size_t *len);
__owur int dtls_get_message(SSL *s, int *mt, size_t *len);
/* Message construction and processing functions */
__owur int tls_process_initial_server_flight(SSL *s);
__owur MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt);
__owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
__owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
__owur int tls_construct_finished(SSL *s, WPACKET *pkt);
__owur int tls_construct_key_update(SSL *s, WPACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt);
__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs,
int stop);
__owur WORK_STATE dtls_wait_for_dry(SSL *s);
/* some client-only functions */
__owur int tls_construct_client_hello(SSL *s, WPACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt);
__owur int tls_process_cert_status_body(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt);
__owur int tls_construct_cert_verify(SSL *s, WPACKET *pkt);
__owur WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst);
__owur int tls_construct_client_certificate(SSL *s, WPACKET *pkt);
__owur int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
__owur int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt);
__owur int tls_client_key_exchange_post_work(SSL *s);
__owur int tls_construct_cert_status_body(SSL *s, WPACKET *pkt);
__owur int tls_construct_cert_status(SSL *s, WPACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt);
__owur int ssl3_check_cert_and_algorithm(SSL *s);
#ifndef OPENSSL_NO_NEXTPROTONEG
__owur int tls_construct_next_proto(SSL *s, WPACKET *pkt);
#endif
__owur MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt);
__owur int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt);
/* some server-only functions */
__owur MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt);
__owur WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst);
__owur int tls_construct_server_hello(SSL *s, WPACKET *pkt);
__owur int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt);
__owur int tls_construct_server_certificate(SSL *s, WPACKET *pkt);
__owur int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt);
__owur int tls_construct_certificate_request(SSL *s, WPACKET *pkt);
__owur int tls_construct_server_done(SSL *s, WPACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt);
__owur WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst);
__owur MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt);
#ifndef OPENSSL_NO_NEXTPROTONEG
__owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
#endif
__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt);
/* Extension processing */
typedef enum ext_return_en {
EXT_RETURN_FAIL,
EXT_RETURN_SENT,
EXT_RETURN_NOT_SENT
} EXT_RETURN;
__owur int tls_validate_all_contexts(SSL *s, unsigned int thisctx,
RAW_EXTENSION *exts);
__owur int extension_is_relevant(SSL *s, unsigned int extctx,
unsigned int thisctx);
__owur int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
RAW_EXTENSION **res, size_t *len, int init);
__owur int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
RAW_EXTENSION *exts, X509 *x, size_t chainidx);
__owur int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
X509 *x, size_t chainidx, int fin);
__owur int should_add_extension(SSL *s, unsigned int extctx,
unsigned int thisctx, int max_version);
__owur int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
__owur 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);
/* Server Extension processing */
int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_SRP
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#endif
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_EC
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidxl);
#endif
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#ifndef OPENSSL_NO_OCSP
int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#endif
int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#ifndef OPENSSL_NO_SRTP
int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#endif
int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_ctos_post_handshake_auth(SSL *, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
#endif
EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
#ifndef OPENSSL_NO_OCSP
EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
#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);
#endif
EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_SRTP
EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#endif
EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
/*
* Not in public headers as this is not an official extension. Only used when
* SSL_OP_CRYPTOPRO_TLSEXT_BUG is set.
*/
#define TLSEXT_TYPE_cryptopro_bug 0xfde8
EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
/* Client Extension processing */
EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_SRP
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#endif
#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
#endif
EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
#ifndef OPENSSL_NO_OCSP
EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#endif
EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_SRTP
EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#endif
EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_CT
EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#endif
EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_EC
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#endif
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_OCSP
int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#endif
#ifndef OPENSSL_NO_CT
int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#endif
int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#ifndef OPENSSL_NO_SRTP
int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#endif
int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
int tls_handle_alpn(SSL *s);
int tls13_save_handshake_digest_for_pha(SSL *s);
int tls13_restore_handshake_digest_for_pha(SSL *s);
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 346b1e398916..e7c11c4bea4d 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1,4269 +1,4279 @@
/*
* Copyright 1995-2018 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
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)];
/*
* 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));
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
sizeof(labelbuffer), 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)
+ 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
- if (!tls1_set_server_sigalgs(s)) {
- /* SSLfatal() already called */
- goto 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 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 && 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 (!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 (rv < 0) {
- s->rwstate = SSL_X509_LOOKUP;
- return WORK_MORE_B;
+ if (!tls1_set_server_sigalgs(s)) {
+ /* SSLfatal already called */
+ goto err;
}
- s->rwstate = SSL_NOTHING;
}
/* 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, pkt)) {
+ 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)];
/*
* 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));
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
sizeof(labelbuffer), 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);
void (*cb) (const SSL *ssl, int type, int val) = NULL;
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 (s->info_callback != NULL)
cb = s->info_callback;
else if (s->ctx->info_callback != NULL)
cb = s->ctx->info_callback;
if (cb != NULL) {
/*
* We don't start and stop the handshake in between each ticket when
* sending more than one - but it should appear that way to the info
* callback.
*/
if (s->sent_tickets != 0) {
ossl_statem_set_in_init(s, 0);
cb(s, SSL_CB_HANDSHAKE_DONE, 1);
ossl_statem_set_in_init(s, 1);
}
cb(s, SSL_CB_HANDSHAKE_START, 1);
}
/*
* 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)) {
/* 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;
}
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 156497988a62..fc41ed90e710 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1,2732 +1,2777 @@
/*
* Copyright 1995-2018 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 <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/ocsp.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include "internal/nelem.h"
#include "ssl_locl.h"
#include <openssl/ct.h>
SSL3_ENC_METHOD const TLSv1_enc_data = {
tls1_enc,
tls1_mac,
tls1_setup_key_block,
tls1_generate_master_secret,
tls1_change_cipher_state,
tls1_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
0,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
SSL3_ENC_METHOD const TLSv1_1_enc_data = {
tls1_enc,
tls1_mac,
tls1_setup_key_block,
tls1_generate_master_secret,
tls1_change_cipher_state,
tls1_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
SSL_ENC_FLAG_EXPLICIT_IV,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
SSL3_ENC_METHOD const TLSv1_2_enc_data = {
tls1_enc,
tls1_mac,
tls1_setup_key_block,
tls1_generate_master_secret,
tls1_change_cipher_state,
tls1_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF
| SSL_ENC_FLAG_TLS1_2_CIPHERS,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
SSL3_ENC_METHOD const TLSv1_3_enc_data = {
tls13_enc,
tls1_mac,
tls13_setup_key_block,
tls13_generate_master_secret,
tls13_change_cipher_state,
tls13_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls13_alert_code,
tls13_export_keying_material,
SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
long tls1_default_timeout(void)
{
/*
* 2 hours, the 24 hours mentioned in the TLSv1 spec is way too long for
* http, the cache would over fill
*/
return (60 * 60 * 2);
}
int tls1_new(SSL *s)
{
if (!ssl3_new(s))
return 0;
if (!s->method->ssl_clear(s))
return 0;
return 1;
}
void tls1_free(SSL *s)
{
OPENSSL_free(s->ext.session_ticket);
ssl3_free(s);
}
int tls1_clear(SSL *s)
{
if (!ssl3_clear(s))
return 0;
if (s->method->version == TLS_ANY_VERSION)
s->version = TLS_MAX_VERSION;
else
s->version = s->method->version;
return 1;
}
#ifndef OPENSSL_NO_EC
/*
* Table of curve information.
* Do not delete entries or reorder this array! It is used as a lookup
* table: the index of each entry is one less than the TLS curve id.
*/
static const TLS_GROUP_INFO nid_list[] = {
{NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */
{NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */
{NID_sect163r2, 80, TLS_CURVE_CHAR2}, /* sect163r2 (3) */
{NID_sect193r1, 80, TLS_CURVE_CHAR2}, /* sect193r1 (4) */
{NID_sect193r2, 80, TLS_CURVE_CHAR2}, /* sect193r2 (5) */
{NID_sect233k1, 112, TLS_CURVE_CHAR2}, /* sect233k1 (6) */
{NID_sect233r1, 112, TLS_CURVE_CHAR2}, /* sect233r1 (7) */
{NID_sect239k1, 112, TLS_CURVE_CHAR2}, /* sect239k1 (8) */
{NID_sect283k1, 128, TLS_CURVE_CHAR2}, /* sect283k1 (9) */
{NID_sect283r1, 128, TLS_CURVE_CHAR2}, /* sect283r1 (10) */
{NID_sect409k1, 192, TLS_CURVE_CHAR2}, /* sect409k1 (11) */
{NID_sect409r1, 192, TLS_CURVE_CHAR2}, /* sect409r1 (12) */
{NID_sect571k1, 256, TLS_CURVE_CHAR2}, /* sect571k1 (13) */
{NID_sect571r1, 256, TLS_CURVE_CHAR2}, /* sect571r1 (14) */
{NID_secp160k1, 80, TLS_CURVE_PRIME}, /* secp160k1 (15) */
{NID_secp160r1, 80, TLS_CURVE_PRIME}, /* secp160r1 (16) */
{NID_secp160r2, 80, TLS_CURVE_PRIME}, /* secp160r2 (17) */
{NID_secp192k1, 80, TLS_CURVE_PRIME}, /* secp192k1 (18) */
{NID_X9_62_prime192v1, 80, TLS_CURVE_PRIME}, /* secp192r1 (19) */
{NID_secp224k1, 112, TLS_CURVE_PRIME}, /* secp224k1 (20) */
{NID_secp224r1, 112, TLS_CURVE_PRIME}, /* secp224r1 (21) */
{NID_secp256k1, 128, TLS_CURVE_PRIME}, /* secp256k1 (22) */
{NID_X9_62_prime256v1, 128, TLS_CURVE_PRIME}, /* secp256r1 (23) */
{NID_secp384r1, 192, TLS_CURVE_PRIME}, /* secp384r1 (24) */
{NID_secp521r1, 256, TLS_CURVE_PRIME}, /* secp521r1 (25) */
{NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */
{NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */
{NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */
{EVP_PKEY_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */
{EVP_PKEY_X448, 224, TLS_CURVE_CUSTOM}, /* X448 (30) */
};
static const unsigned char ecformats_default[] = {
TLSEXT_ECPOINTFORMAT_uncompressed,
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime,
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
};
/* The default curves */
static const uint16_t eccurves_default[] = {
29, /* X25519 (29) */
23, /* secp256r1 (23) */
30, /* X448 (30) */
25, /* secp521r1 (25) */
24, /* secp384r1 (24) */
};
static const uint16_t suiteb_curves[] = {
TLSEXT_curve_P_256,
TLSEXT_curve_P_384
};
const TLS_GROUP_INFO *tls1_group_id_lookup(uint16_t group_id)
{
/* ECC curves from RFC 4492 and RFC 7027 */
if (group_id < 1 || group_id > OSSL_NELEM(nid_list))
return NULL;
return &nid_list[group_id - 1];
}
static uint16_t tls1_nid2group_id(int nid)
{
size_t i;
for (i = 0; i < OSSL_NELEM(nid_list); i++) {
if (nid_list[i].nid == nid)
return (uint16_t)(i + 1);
}
return 0;
}
/*
* Set *pgroups to the supported groups list and *pgroupslen to
* the number of groups supported.
*/
void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups,
size_t *pgroupslen)
{
/* For Suite B mode only include P-256, P-384 */
switch (tls1_suiteb(s)) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
*pgroups = suiteb_curves;
*pgroupslen = OSSL_NELEM(suiteb_curves);
break;
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*pgroups = suiteb_curves;
*pgroupslen = 1;
break;
case SSL_CERT_FLAG_SUITEB_192_LOS:
*pgroups = suiteb_curves + 1;
*pgroupslen = 1;
break;
default:
if (s->ext.supportedgroups == NULL) {
*pgroups = eccurves_default;
*pgroupslen = OSSL_NELEM(eccurves_default);
} else {
*pgroups = s->ext.supportedgroups;
*pgroupslen = s->ext.supportedgroups_len;
}
break;
}
}
/* See if curve is allowed by security callback */
int tls_curve_allowed(SSL *s, uint16_t curve, int op)
{
const TLS_GROUP_INFO *cinfo = tls1_group_id_lookup(curve);
unsigned char ctmp[2];
if (cinfo == NULL)
return 0;
# ifdef OPENSSL_NO_EC2M
if (cinfo->flags & TLS_CURVE_CHAR2)
return 0;
# endif
ctmp[0] = curve >> 8;
ctmp[1] = curve & 0xff;
return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)ctmp);
}
/* Return 1 if "id" is in "list" */
static int tls1_in_list(uint16_t id, const uint16_t *list, size_t listlen)
{
size_t i;
for (i = 0; i < listlen; i++)
if (list[i] == id)
return 1;
return 0;
}
/*-
* For nmatch >= 0, return the id of the |nmatch|th shared group or 0
* if there is no match.
* For nmatch == -1, return number of matches
* For nmatch == -2, return the id of the group to use for
* a tmp key, or 0 if there is no match.
*/
uint16_t tls1_shared_group(SSL *s, int nmatch)
{
const uint16_t *pref, *supp;
size_t num_pref, num_supp, i;
int k;
/* Can't do anything on client side */
if (s->server == 0)
return 0;
if (nmatch == -2) {
if (tls1_suiteb(s)) {
/*
* For Suite B ciphersuite determines curve: we already know
* these are acceptable due to previous checks.
*/
unsigned long cid = s->s3->tmp.new_cipher->id;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
return TLSEXT_curve_P_256;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
return TLSEXT_curve_P_384;
/* Should never happen */
return 0;
}
/* If not Suite B just return first preference shared curve */
nmatch = 0;
}
/*
* If server preference set, our groups are the preference order
* otherwise peer decides.
*/
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
tls1_get_supported_groups(s, &pref, &num_pref);
tls1_get_peer_groups(s, &supp, &num_supp);
} else {
tls1_get_peer_groups(s, &pref, &num_pref);
tls1_get_supported_groups(s, &supp, &num_supp);
}
for (k = 0, i = 0; i < num_pref; i++) {
uint16_t id = pref[i];
if (!tls1_in_list(id, supp, num_supp)
|| !tls_curve_allowed(s, id, SSL_SECOP_CURVE_SHARED))
continue;
if (nmatch == k)
return id;
k++;
}
if (nmatch == -1)
return k;
/* Out of range (nmatch > k). */
return 0;
}
int tls1_set_groups(uint16_t **pext, size_t *pextlen,
int *groups, size_t ngroups)
{
uint16_t *glist;
size_t i;
/*
* Bitmap of groups included to detect duplicates: only works while group
* ids < 32
*/
unsigned long dup_list = 0;
+ if (ngroups == 0) {
+ SSLerr(SSL_F_TLS1_SET_GROUPS, SSL_R_BAD_LENGTH);
+ return 0;
+ }
if ((glist = OPENSSL_malloc(ngroups * sizeof(*glist))) == NULL) {
SSLerr(SSL_F_TLS1_SET_GROUPS, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < ngroups; i++) {
unsigned long idmask;
uint16_t id;
/* TODO(TLS1.3): Convert for DH groups */
id = tls1_nid2group_id(groups[i]);
idmask = 1L << id;
if (!id || (dup_list & idmask)) {
OPENSSL_free(glist);
return 0;
}
dup_list |= idmask;
glist[i] = id;
}
OPENSSL_free(*pext);
*pext = glist;
*pextlen = ngroups;
return 1;
}
# define MAX_CURVELIST OSSL_NELEM(nid_list)
typedef struct {
size_t nidcnt;
int nid_arr[MAX_CURVELIST];
} nid_cb_st;
static int nid_cb(const char *elem, int len, void *arg)
{
nid_cb_st *narg = arg;
size_t i;
int nid;
char etmp[20];
if (elem == NULL)
return 0;
if (narg->nidcnt == MAX_CURVELIST)
return 0;
if (len > (int)(sizeof(etmp) - 1))
return 0;
memcpy(etmp, elem, len);
etmp[len] = 0;
nid = EC_curve_nist2nid(etmp);
if (nid == NID_undef)
nid = OBJ_sn2nid(etmp);
if (nid == NID_undef)
nid = OBJ_ln2nid(etmp);
if (nid == NID_undef)
return 0;
for (i = 0; i < narg->nidcnt; i++)
if (narg->nid_arr[i] == nid)
return 0;
narg->nid_arr[narg->nidcnt++] = nid;
return 1;
}
/* Set groups based on a colon separate list */
int tls1_set_groups_list(uint16_t **pext, size_t *pextlen, const char *str)
{
nid_cb_st ncb;
ncb.nidcnt = 0;
if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb))
return 0;
if (pext == NULL)
return 1;
return tls1_set_groups(pext, pextlen, ncb.nid_arr, ncb.nidcnt);
}
/* Return group id of a key */
static uint16_t tls1_get_group_id(EVP_PKEY *pkey)
{
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
const EC_GROUP *grp;
if (ec == NULL)
return 0;
grp = EC_KEY_get0_group(ec);
return tls1_nid2group_id(EC_GROUP_get_curve_name(grp));
}
/* Check a key is compatible with compression extension */
static int tls1_check_pkey_comp(SSL *s, EVP_PKEY *pkey)
{
const EC_KEY *ec;
const EC_GROUP *grp;
unsigned char comp_id;
size_t i;
/* If not an EC key nothing to check */
if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
return 1;
ec = EVP_PKEY_get0_EC_KEY(pkey);
grp = EC_KEY_get0_group(ec);
/* Get required compression id */
if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) {
comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
} else if (SSL_IS_TLS13(s)) {
/*
* ec_point_formats extension is not used in TLSv1.3 so we ignore
* this check.
*/
return 1;
} else {
int field_type = EC_METHOD_get_field_type(EC_GROUP_method_of(grp));
if (field_type == NID_X9_62_prime_field)
comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
else if (field_type == NID_X9_62_characteristic_two_field)
comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
else
return 0;
}
/*
* If point formats extension present check it, otherwise everything is
* supported (see RFC4492).
*/
if (s->session->ext.ecpointformats == NULL)
return 1;
for (i = 0; i < s->session->ext.ecpointformats_len; i++) {
if (s->session->ext.ecpointformats[i] == comp_id)
return 1;
}
return 0;
}
/* Check a group id matches preferences */
int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_groups)
{
const uint16_t *groups;
size_t groups_len;
if (group_id == 0)
return 0;
/* Check for Suite B compliance */
if (tls1_suiteb(s) && s->s3->tmp.new_cipher != NULL) {
unsigned long cid = s->s3->tmp.new_cipher->id;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) {
if (group_id != TLSEXT_curve_P_256)
return 0;
} else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) {
if (group_id != TLSEXT_curve_P_384)
return 0;
} else {
/* Should never happen */
return 0;
}
}
if (check_own_groups) {
/* Check group is one of our preferences */
tls1_get_supported_groups(s, &groups, &groups_len);
if (!tls1_in_list(group_id, groups, groups_len))
return 0;
}
if (!tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_CHECK))
return 0;
/* For clients, nothing more to check */
if (!s->server)
return 1;
/* Check group is one of peers preferences */
tls1_get_peer_groups(s, &groups, &groups_len);
/*
* RFC 4492 does not require the supported elliptic curves extension
* so if it is not sent we can just choose any curve.
* It is invalid to send an empty list in the supported groups
* extension, so groups_len == 0 always means no extension.
*/
if (groups_len == 0)
return 1;
return tls1_in_list(group_id, groups, groups_len);
}
void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
size_t *num_formats)
{
/*
* If we have a custom point format list use it otherwise use default
*/
if (s->ext.ecpointformats) {
*pformats = s->ext.ecpointformats;
*num_formats = s->ext.ecpointformats_len;
} else {
*pformats = ecformats_default;
/* For Suite B we don't support char2 fields */
if (tls1_suiteb(s))
*num_formats = sizeof(ecformats_default) - 1;
else
*num_formats = sizeof(ecformats_default);
}
}
/*
* Check cert parameters compatible with extensions: currently just checks EC
* certificates have compatible curves and compression.
*/
static int tls1_check_cert_param(SSL *s, X509 *x, int check_ee_md)
{
uint16_t group_id;
EVP_PKEY *pkey;
pkey = X509_get0_pubkey(x);
if (pkey == NULL)
return 0;
/* If not EC nothing to do */
if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
return 1;
/* Check compression */
if (!tls1_check_pkey_comp(s, pkey))
return 0;
group_id = tls1_get_group_id(pkey);
/*
* For a server we allow the certificate to not be in our list of supported
* groups.
*/
if (!tls1_check_group_id(s, group_id, !s->server))
return 0;
/*
* Special case for suite B. We *MUST* sign using SHA256+P-256 or
* SHA384+P-384.
*/
if (check_ee_md && tls1_suiteb(s)) {
int check_md;
size_t i;
CERT *c = s->cert;
/* Check to see we have necessary signing algorithm */
if (group_id == TLSEXT_curve_P_256)
check_md = NID_ecdsa_with_SHA256;
else if (group_id == TLSEXT_curve_P_384)
check_md = NID_ecdsa_with_SHA384;
else
return 0; /* Should never happen */
for (i = 0; i < c->shared_sigalgslen; i++) {
if (check_md == c->shared_sigalgs[i]->sigandhash)
return 1;;
}
return 0;
}
return 1;
}
/*
* tls1_check_ec_tmp_key - Check EC temporary key compatibility
* @s: SSL connection
* @cid: Cipher ID we're considering using
*
* Checks that the kECDHE cipher suite we're considering using
* is compatible with the client extensions.
*
* Returns 0 when the cipher can't be used or 1 when it can.
*/
int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
{
/* If not Suite B just need a shared group */
if (!tls1_suiteb(s))
return tls1_shared_group(s, 0) != 0;
/*
* If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, no other
* curves permitted.
*/
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
return tls1_check_group_id(s, TLSEXT_curve_P_256, 1);
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
return tls1_check_group_id(s, TLSEXT_curve_P_384, 1);
return 0;
}
#else
static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
{
return 1;
}
#endif /* OPENSSL_NO_EC */
/* Default sigalg schemes */
static const uint16_t tls12_sigalgs[] = {
#ifndef OPENSSL_NO_EC
TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
TLSEXT_SIGALG_ed25519,
TLSEXT_SIGALG_ed448,
#endif
TLSEXT_SIGALG_rsa_pss_pss_sha256,
TLSEXT_SIGALG_rsa_pss_pss_sha384,
TLSEXT_SIGALG_rsa_pss_pss_sha512,
TLSEXT_SIGALG_rsa_pss_rsae_sha256,
TLSEXT_SIGALG_rsa_pss_rsae_sha384,
TLSEXT_SIGALG_rsa_pss_rsae_sha512,
TLSEXT_SIGALG_rsa_pkcs1_sha256,
TLSEXT_SIGALG_rsa_pkcs1_sha384,
TLSEXT_SIGALG_rsa_pkcs1_sha512,
#ifndef OPENSSL_NO_EC
TLSEXT_SIGALG_ecdsa_sha224,
TLSEXT_SIGALG_ecdsa_sha1,
#endif
TLSEXT_SIGALG_rsa_pkcs1_sha224,
TLSEXT_SIGALG_rsa_pkcs1_sha1,
#ifndef OPENSSL_NO_DSA
TLSEXT_SIGALG_dsa_sha224,
TLSEXT_SIGALG_dsa_sha1,
TLSEXT_SIGALG_dsa_sha256,
TLSEXT_SIGALG_dsa_sha384,
TLSEXT_SIGALG_dsa_sha512,
#endif
#ifndef OPENSSL_NO_GOST
TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
TLSEXT_SIGALG_gostr34102001_gostr3411,
#endif
};
#ifndef OPENSSL_NO_EC
static const uint16_t suiteb_sigalgs[] = {
TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
TLSEXT_SIGALG_ecdsa_secp384r1_sha384
};
#endif
static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
#ifndef OPENSSL_NO_EC
{"ecdsa_secp256r1_sha256", TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA256, NID_X9_62_prime256v1},
{"ecdsa_secp384r1_sha384", TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA384, NID_secp384r1},
{"ecdsa_secp521r1_sha512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA512, NID_secp521r1},
{"ed25519", TLSEXT_SIGALG_ed25519,
NID_undef, -1, EVP_PKEY_ED25519, SSL_PKEY_ED25519,
NID_undef, NID_undef},
{"ed448", TLSEXT_SIGALG_ed448,
NID_undef, -1, EVP_PKEY_ED448, SSL_PKEY_ED448,
NID_undef, NID_undef},
{NULL, TLSEXT_SIGALG_ecdsa_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA224, NID_undef},
{NULL, TLSEXT_SIGALG_ecdsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA1, NID_undef},
#endif
{"rsa_pss_rsae_sha256", TLSEXT_SIGALG_rsa_pss_rsae_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
NID_undef, NID_undef},
{"rsa_pss_rsae_sha384", TLSEXT_SIGALG_rsa_pss_rsae_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
NID_undef, NID_undef},
{"rsa_pss_rsae_sha512", TLSEXT_SIGALG_rsa_pss_rsae_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
NID_undef, NID_undef},
{"rsa_pss_pss_sha256", TLSEXT_SIGALG_rsa_pss_pss_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
NID_undef, NID_undef},
{"rsa_pss_pss_sha384", TLSEXT_SIGALG_rsa_pss_pss_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
NID_undef, NID_undef},
{"rsa_pss_pss_sha512", TLSEXT_SIGALG_rsa_pss_pss_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
NID_undef, NID_undef},
{"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha256WithRSAEncryption, NID_undef},
{"rsa_pkcs1_sha384", TLSEXT_SIGALG_rsa_pkcs1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha384WithRSAEncryption, NID_undef},
{"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha512WithRSAEncryption, NID_undef},
{"rsa_pkcs1_sha224", TLSEXT_SIGALG_rsa_pkcs1_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha224WithRSAEncryption, NID_undef},
{"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha1WithRSAEncryption, NID_undef},
#ifndef OPENSSL_NO_DSA
{NULL, TLSEXT_SIGALG_dsa_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_dsa_with_SHA256, NID_undef},
{NULL, TLSEXT_SIGALG_dsa_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_undef, NID_undef},
{NULL, TLSEXT_SIGALG_dsa_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_undef, NID_undef},
{NULL, TLSEXT_SIGALG_dsa_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_undef, NID_undef},
{NULL, TLSEXT_SIGALG_dsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_dsaWithSHA1, NID_undef},
#endif
#ifndef OPENSSL_NO_GOST
{NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
NID_undef, NID_undef},
{NULL, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
NID_undef, NID_undef},
{NULL, TLSEXT_SIGALG_gostr34102001_gostr3411,
NID_id_GostR3411_94, SSL_MD_GOST94_IDX,
NID_id_GostR3410_2001, SSL_PKEY_GOST01,
NID_undef, NID_undef}
#endif
};
/* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */
static const SIGALG_LOOKUP legacy_rsa_sigalg = {
"rsa_pkcs1_md5_sha1", 0,
NID_md5_sha1, SSL_MD_MD5_SHA1_IDX,
EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_undef, NID_undef
};
/*
* Default signature algorithm values used if signature algorithms not present.
* From RFC5246. Note: order must match certificate index order.
*/
static const uint16_t tls_default_sigalg[] = {
TLSEXT_SIGALG_rsa_pkcs1_sha1, /* SSL_PKEY_RSA */
0, /* SSL_PKEY_RSA_PSS_SIGN */
TLSEXT_SIGALG_dsa_sha1, /* SSL_PKEY_DSA_SIGN */
TLSEXT_SIGALG_ecdsa_sha1, /* SSL_PKEY_ECC */
TLSEXT_SIGALG_gostr34102001_gostr3411, /* SSL_PKEY_GOST01 */
TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, /* SSL_PKEY_GOST12_256 */
TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, /* SSL_PKEY_GOST12_512 */
0, /* SSL_PKEY_ED25519 */
0, /* SSL_PKEY_ED448 */
};
/* Lookup TLS signature algorithm */
static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg)
{
size_t i;
const SIGALG_LOOKUP *s;
for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
i++, s++) {
if (s->sigalg == sigalg)
return s;
}
return NULL;
}
/* Lookup hash: return 0 if invalid or not enabled */
int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
{
const EVP_MD *md;
if (lu == NULL)
return 0;
/* lu->hash == NID_undef means no associated digest */
if (lu->hash == NID_undef) {
md = NULL;
} else {
md = ssl_md(lu->hash_idx);
if (md == NULL)
return 0;
}
if (pmd)
*pmd = md;
return 1;
}
/*
* Check if key is large enough to generate RSA-PSS signature.
*
* The key must greater than or equal to 2 * hash length + 2.
* SHA512 has a hash length of 64 bytes, which is incompatible
* with a 128 byte (1024 bit) key.
*/
#define RSA_PSS_MINIMUM_KEY_SIZE(md) (2 * EVP_MD_size(md) + 2)
static int rsa_pss_check_min_key_size(const RSA *rsa, const SIGALG_LOOKUP *lu)
{
const EVP_MD *md;
if (rsa == NULL)
return 0;
if (!tls1_lookup_md(lu, &md) || md == NULL)
return 0;
if (RSA_size(rsa) < RSA_PSS_MINIMUM_KEY_SIZE(md))
return 0;
return 1;
}
/*
* Return a signature algorithm for TLS < 1.2 where the signature type
* is fixed by the certificate type.
*/
static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
{
if (idx == -1) {
if (s->server) {
size_t i;
/* Work out index corresponding to ciphersuite */
for (i = 0; i < SSL_PKEY_NUM; i++) {
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(i);
if (clu->amask & s->s3->tmp.new_cipher->algorithm_auth) {
idx = i;
break;
}
}
/*
* Some GOST ciphersuites allow more than one signature algorithms
* */
if (idx == SSL_PKEY_GOST01 && s->s3->tmp.new_cipher->algorithm_auth != SSL_aGOST01) {
int real_idx;
for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST01;
real_idx--) {
if (s->cert->pkeys[real_idx].privatekey != NULL) {
idx = real_idx;
break;
}
}
}
} else {
idx = s->cert->key - s->cert->pkeys;
}
}
if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg))
return NULL;
if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]);
if (!tls1_lookup_md(lu, NULL))
return NULL;
return lu;
}
return &legacy_rsa_sigalg;
}
/* Set peer sigalg based key type */
int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey)
{
size_t idx;
const SIGALG_LOOKUP *lu;
if (ssl_cert_lookup_by_pkey(pkey, &idx) == NULL)
return 0;
lu = tls1_get_legacy_sigalg(s, idx);
if (lu == NULL)
return 0;
s->s3->tmp.peer_sigalg = lu;
return 1;
}
size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
{
/*
* If Suite B mode use Suite B sigalgs only, ignore any other
* preferences.
*/
#ifndef OPENSSL_NO_EC
switch (tls1_suiteb(s)) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
*psigs = suiteb_sigalgs;
return OSSL_NELEM(suiteb_sigalgs);
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*psigs = suiteb_sigalgs;
return 1;
case SSL_CERT_FLAG_SUITEB_192_LOS:
*psigs = suiteb_sigalgs + 1;
return 1;
}
#endif
/*
* We use client_sigalgs (if not NULL) if we're a server
* and sending a certificate request or if we're a client and
* determining which shared algorithm to use.
*/
if ((s->server == sent) && s->cert->client_sigalgs != NULL) {
*psigs = s->cert->client_sigalgs;
return s->cert->client_sigalgslen;
} else if (s->cert->conf_sigalgs) {
*psigs = s->cert->conf_sigalgs;
return s->cert->conf_sigalgslen;
} else {
*psigs = tls12_sigalgs;
return OSSL_NELEM(tls12_sigalgs);
}
}
+#ifndef OPENSSL_NO_EC
+/*
+ * Called by servers only. Checks that we have a sig alg that supports the
+ * specified EC curve.
+ */
+int tls_check_sigalg_curve(const SSL *s, int curve)
+{
+ const uint16_t *sigs;
+ size_t siglen, i;
+
+ if (s->cert->conf_sigalgs) {
+ sigs = s->cert->conf_sigalgs;
+ siglen = s->cert->conf_sigalgslen;
+ } else {
+ sigs = tls12_sigalgs;
+ siglen = OSSL_NELEM(tls12_sigalgs);
+ }
+
+ for (i = 0; i < siglen; i++) {
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigs[i]);
+
+ if (lu == NULL)
+ continue;
+ if (lu->sig == EVP_PKEY_EC
+ && lu->curve != NID_undef
+ && curve == lu->curve)
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
/*
* Check signature algorithm is consistent with sent supported signature
* algorithms and if so set relevant digest and signature scheme in
* s.
*/
int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
{
const uint16_t *sent_sigs;
const EVP_MD *md = NULL;
char sigalgstr[2];
size_t sent_sigslen, i, cidx;
int pkeyid = EVP_PKEY_id(pkey);
const SIGALG_LOOKUP *lu;
/* Should never happen */
if (pkeyid == -1)
return -1;
if (SSL_IS_TLS13(s)) {
/* Disallow DSA for TLS 1.3 */
if (pkeyid == EVP_PKEY_DSA) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Only allow PSS for TLS 1.3 */
if (pkeyid == EVP_PKEY_RSA)
pkeyid = EVP_PKEY_RSA_PSS;
}
lu = tls1_lookup_sigalg(sig);
/*
* Check sigalgs is known. Disallow SHA1/SHA224 with TLS 1.3. Check key type
* is consistent with signature: RSA keys can be used for RSA-PSS
*/
if (lu == NULL
|| (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
|| (pkeyid != lu->sig
&& (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Check the sigalg is consistent with the key OID */
if (!ssl_cert_lookup_by_nid(EVP_PKEY_id(pkey), &cidx)
|| lu->sig_idx != (int)cidx) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
#ifndef OPENSSL_NO_EC
if (pkeyid == EVP_PKEY_EC) {
/* Check point compression is permitted */
if (!tls1_check_pkey_comp(s, pkey)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_ILLEGAL_POINT_COMPRESSION);
return 0;
}
/* For TLS 1.3 or Suite B check curve matches signature algorithm */
if (SSL_IS_TLS13(s) || tls1_suiteb(s)) {
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
if (lu->curve != NID_undef && curve != lu->curve) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
return 0;
}
}
if (!SSL_IS_TLS13(s)) {
/* Check curve matches extensions */
if (!tls1_check_group_id(s, tls1_get_group_id(pkey), 1)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
return 0;
}
if (tls1_suiteb(s)) {
/* Check sigalg matches a permissible Suite B value */
if (sig != TLSEXT_SIGALG_ecdsa_secp256r1_sha256
&& sig != TLSEXT_SIGALG_ecdsa_secp384r1_sha384) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
}
} else if (tls1_suiteb(s)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
#endif
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
if (sig == *sent_sigs)
break;
}
/* Allow fallback to SHA1 if not strict mode */
if (i == sent_sigslen && (lu->hash != NID_sha1
|| s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
if (!tls1_lookup_md(lu, &md)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_UNKNOWN_DIGEST);
return 0;
}
if (md != NULL) {
/*
* Make sure security callback allows algorithm. For historical
* reasons we have to pass the sigalg as a two byte char array.
*/
sigalgstr[0] = (sig >> 8) & 0xff;
sigalgstr[1] = sig & 0xff;
if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
EVP_MD_size(md) * 4, EVP_MD_type(md),
(void *)sigalgstr)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
/* Store the sigalg the peer uses */
s->s3->tmp.peer_sigalg = lu;
return 1;
}
int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid)
{
if (s->s3->tmp.peer_sigalg == NULL)
return 0;
*pnid = s->s3->tmp.peer_sigalg->sig;
return 1;
}
+int SSL_get_signature_type_nid(const SSL *s, int *pnid)
+{
+ if (s->s3->tmp.sigalg == NULL)
+ return 0;
+ *pnid = s->s3->tmp.sigalg->sig;
+ return 1;
+}
+
/*
* Set a mask of disabled algorithms: an algorithm is disabled if it isn't
* supported, doesn't appear in supported signature algorithms, isn't supported
* by the enabled protocol versions or by the security level.
*
* This function should only be used for checking which ciphers are supported
* by the client.
*
* Call ssl_cipher_disabled() to check that it's enabled or not.
*/
int ssl_set_client_disabled(SSL *s)
{
s->s3->tmp.mask_a = 0;
s->s3->tmp.mask_k = 0;
ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
if (ssl_get_min_max_version(s, &s->s3->tmp.min_ver,
&s->s3->tmp.max_ver, NULL) != 0)
return 0;
#ifndef OPENSSL_NO_PSK
/* with PSK there must be client callback set */
if (!s->psk_client_callback) {
s->s3->tmp.mask_a |= SSL_aPSK;
s->s3->tmp.mask_k |= SSL_PSK;
}
#endif /* OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_SRP
if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) {
s->s3->tmp.mask_a |= SSL_aSRP;
s->s3->tmp.mask_k |= SSL_kSRP;
}
#endif
return 1;
}
/*
* ssl_cipher_disabled - check that a cipher is disabled or not
* @s: SSL connection that you want to use the cipher on
* @c: cipher to check
* @op: Security check that you want to do
* @ecdhe: If set to 1 then TLSv1 ECDHE ciphers are also allowed in SSLv3
*
* Returns 1 when it's disabled, 0 when enabled.
*/
int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int ecdhe)
{
if (c->algorithm_mkey & s->s3->tmp.mask_k
|| c->algorithm_auth & s->s3->tmp.mask_a)
return 1;
if (s->s3->tmp.max_ver == 0)
return 1;
if (!SSL_IS_DTLS(s)) {
int min_tls = c->min_tls;
/*
* For historical reasons we will allow ECHDE to be selected by a server
* in SSLv3 if we are a client
*/
if (min_tls == TLS1_VERSION && ecdhe
&& (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0)
min_tls = SSL3_VERSION;
if ((min_tls > s->s3->tmp.max_ver) || (c->max_tls < s->s3->tmp.min_ver))
return 1;
}
if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver)
|| DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver)))
return 1;
return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
}
int tls_use_ticket(SSL *s)
{
if ((s->options & SSL_OP_NO_TICKET))
return 0;
return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
}
int tls1_set_server_sigalgs(SSL *s)
{
size_t i;
/* Clear any shared signature algorithms */
OPENSSL_free(s->cert->shared_sigalgs);
s->cert->shared_sigalgs = NULL;
s->cert->shared_sigalgslen = 0;
/* Clear certificate validity flags */
for (i = 0; i < SSL_PKEY_NUM; i++)
s->s3->tmp.valid_flags[i] = 0;
/*
* If peer sent no signature algorithms check to see if we support
* the default algorithm for each certificate type
*/
if (s->s3->tmp.peer_cert_sigalgs == NULL
&& s->s3->tmp.peer_sigalgs == NULL) {
const uint16_t *sent_sigs;
size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
for (i = 0; i < SSL_PKEY_NUM; i++) {
const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, i);
size_t j;
if (lu == NULL)
continue;
/* Check default matches a type we sent */
for (j = 0; j < sent_sigslen; j++) {
if (lu->sigalg == sent_sigs[j]) {
s->s3->tmp.valid_flags[i] = CERT_PKEY_SIGN;
break;
}
}
}
return 1;
}
if (!tls1_process_sigalgs(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_INTERNAL_ERROR);
return 0;
}
if (s->cert->shared_sigalgs != NULL)
return 1;
/* Fatal error if no shared signature algorithms */
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS1_SET_SERVER_SIGALGS,
SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
return 0;
}
/*-
* Gets the ticket information supplied by the client if any.
*
* hello: The parsed ClientHello data
* ret: (output) on return, if a ticket was decrypted, then this is set to
* point to the resulting session.
*/
SSL_TICKET_STATUS tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
SSL_SESSION **ret)
{
size_t size;
RAW_EXTENSION *ticketext;
*ret = NULL;
s->ext.ticket_expected = 0;
/*
* If tickets disabled or not supported by the protocol version
* (e.g. TLSv1.3) behave as if no ticket present to permit stateful
* resumption.
*/
if (s->version <= SSL3_VERSION || !tls_use_ticket(s))
return SSL_TICKET_NONE;
ticketext = &hello->pre_proc_exts[TLSEXT_IDX_session_ticket];
if (!ticketext->present)
return SSL_TICKET_NONE;
size = PACKET_remaining(&ticketext->data);
return tls_decrypt_ticket(s, PACKET_data(&ticketext->data), size,
hello->session_id, hello->session_id_len, ret);
}
/*-
* tls_decrypt_ticket attempts to decrypt a session ticket.
*
* If s->tls_session_secret_cb is set and we're not doing TLSv1.3 then we are
* expecting a pre-shared key ciphersuite, in which case we have no use for
* session tickets and one will never be decrypted, nor will
* s->ext.ticket_expected be set to 1.
*
* Side effects:
* Sets s->ext.ticket_expected to 1 if the server will have to issue
* a new session ticket to the client because the client indicated support
* (and s->tls_session_secret_cb is NULL) but the client either doesn't have
* a session ticket or we couldn't use the one it gave us, or if
* s->ctx->ext.ticket_key_cb asked to renew the client's ticket.
* Otherwise, s->ext.ticket_expected is set to 0.
*
* etick: points to the body of the session ticket extension.
* eticklen: the length of the session tickets extension.
* sess_id: points at the session ID.
* sesslen: the length of the session ID.
* psess: (output) on return, if a ticket was decrypted, then this is set to
* point to the resulting session.
*/
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)
{
SSL_SESSION *sess = NULL;
unsigned char *sdec;
const unsigned char *p;
int slen, renew_ticket = 0, declen;
SSL_TICKET_STATUS ret = SSL_TICKET_FATAL_ERR_OTHER;
size_t mlen;
unsigned char tick_hmac[EVP_MAX_MD_SIZE];
HMAC_CTX *hctx = NULL;
EVP_CIPHER_CTX *ctx = NULL;
SSL_CTX *tctx = s->session_ctx;
if (eticklen == 0) {
/*
* The client will accept a ticket but doesn't currently have
* one (TLSv1.2 and below), or treated as a fatal error in TLSv1.3
*/
ret = SSL_TICKET_EMPTY;
goto end;
}
if (!SSL_IS_TLS13(s) && s->ext.session_secret_cb) {
/*
* Indicate that the ticket couldn't be decrypted rather than
* generating the session from ticket now, trigger
* abbreviated handshake based on external mechanism to
* calculate the master secret later.
*/
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
/* Need at least keyname + iv */
if (eticklen < TLSEXT_KEYNAME_LENGTH + EVP_MAX_IV_LENGTH) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
/* Initialize session ticket encryption and HMAC contexts */
hctx = HMAC_CTX_new();
if (hctx == NULL) {
ret = SSL_TICKET_FATAL_ERR_MALLOC;
goto end;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
ret = SSL_TICKET_FATAL_ERR_MALLOC;
goto end;
}
if (tctx->ext.ticket_key_cb) {
unsigned char *nctick = (unsigned char *)etick;
int rv = tctx->ext.ticket_key_cb(s, nctick,
nctick + TLSEXT_KEYNAME_LENGTH,
ctx, hctx, 0);
if (rv < 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
if (rv == 0) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
if (rv == 2)
renew_ticket = 1;
} else {
/* Check key name matches */
if (memcmp(etick, tctx->ext.tick_key_name,
TLSEXT_KEYNAME_LENGTH) != 0) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
if (HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
sizeof(tctx->ext.secure->tick_hmac_key),
EVP_sha256(), NULL) <= 0
|| EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
tctx->ext.secure->tick_aes_key,
etick + TLSEXT_KEYNAME_LENGTH) <= 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
if (SSL_IS_TLS13(s))
renew_ticket = 1;
}
/*
* Attempt to process session ticket, first conduct sanity and integrity
* checks on ticket.
*/
mlen = HMAC_size(hctx);
if (mlen == 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
/* Sanity check ticket length: must exceed keyname + IV + HMAC */
if (eticklen <=
TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx) + mlen) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
if (HMAC_Update(hctx, etick, eticklen) <= 0
|| HMAC_Final(hctx, tick_hmac, NULL) <= 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
p = etick + TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
eticklen -= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
sdec = OPENSSL_malloc(eticklen);
if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p,
(int)eticklen) <= 0) {
OPENSSL_free(sdec);
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
if (EVP_DecryptFinal(ctx, sdec + slen, &declen) <= 0) {
OPENSSL_free(sdec);
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
slen += declen;
p = sdec;
sess = d2i_SSL_SESSION(NULL, &p, slen);
slen -= p - sdec;
OPENSSL_free(sdec);
if (sess) {
/* Some additional consistency checks */
if (slen != 0) {
SSL_SESSION_free(sess);
sess = NULL;
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
/*
* The session ID, if non-empty, is used by some clients to detect
* that the ticket has been accepted. So we copy it to the session
* structure. If it is empty set length to zero as required by
* standard.
*/
if (sesslen) {
memcpy(sess->session_id, sess_id, sesslen);
sess->session_id_length = sesslen;
}
if (renew_ticket)
ret = SSL_TICKET_SUCCESS_RENEW;
else
ret = SSL_TICKET_SUCCESS;
goto end;
}
ERR_clear_error();
/*
* For session parse failure, indicate that we need to send a new ticket.
*/
ret = SSL_TICKET_NO_DECRYPT;
end:
EVP_CIPHER_CTX_free(ctx);
HMAC_CTX_free(hctx);
/*
* If set, the decrypt_ticket_cb() is called unless a fatal error was
* detected above. The callback is responsible for checking |ret| before it
* performs any action
*/
if (s->session_ctx->decrypt_ticket_cb != NULL
&& (ret == SSL_TICKET_EMPTY
|| ret == SSL_TICKET_NO_DECRYPT
|| ret == SSL_TICKET_SUCCESS
|| ret == SSL_TICKET_SUCCESS_RENEW)) {
size_t keyname_len = eticklen;
int retcb;
if (keyname_len > TLSEXT_KEYNAME_LENGTH)
keyname_len = TLSEXT_KEYNAME_LENGTH;
retcb = s->session_ctx->decrypt_ticket_cb(s, sess, etick, keyname_len,
ret,
s->session_ctx->ticket_cb_data);
switch (retcb) {
case SSL_TICKET_RETURN_ABORT:
ret = SSL_TICKET_FATAL_ERR_OTHER;
break;
case SSL_TICKET_RETURN_IGNORE:
ret = SSL_TICKET_NONE;
SSL_SESSION_free(sess);
sess = NULL;
break;
case SSL_TICKET_RETURN_IGNORE_RENEW:
if (ret != SSL_TICKET_EMPTY && ret != SSL_TICKET_NO_DECRYPT)
ret = SSL_TICKET_NO_DECRYPT;
/* else the value of |ret| will already do the right thing */
SSL_SESSION_free(sess);
sess = NULL;
break;
case SSL_TICKET_RETURN_USE:
case SSL_TICKET_RETURN_USE_RENEW:
if (ret != SSL_TICKET_SUCCESS
&& ret != SSL_TICKET_SUCCESS_RENEW)
ret = SSL_TICKET_FATAL_ERR_OTHER;
else if (retcb == SSL_TICKET_RETURN_USE)
ret = SSL_TICKET_SUCCESS;
else
ret = SSL_TICKET_SUCCESS_RENEW;
break;
default:
ret = SSL_TICKET_FATAL_ERR_OTHER;
}
}
if (s->ext.session_secret_cb == NULL || SSL_IS_TLS13(s)) {
switch (ret) {
case SSL_TICKET_NO_DECRYPT:
case SSL_TICKET_SUCCESS_RENEW:
case SSL_TICKET_EMPTY:
s->ext.ticket_expected = 1;
}
}
*psess = sess;
return ret;
}
/* Check to see if a signature algorithm is allowed */
static int tls12_sigalg_allowed(SSL *s, int op, const SIGALG_LOOKUP *lu)
{
unsigned char sigalgstr[2];
int secbits;
/* See if sigalgs is recognised and if hash is enabled */
if (!tls1_lookup_md(lu, NULL))
return 0;
/* DSA is not allowed in TLS 1.3 */
if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
return 0;
/* TODO(OpenSSL1.2) fully axe DSA/etc. in ClientHello per TLS 1.3 spec */
if (!s->server && !SSL_IS_DTLS(s) && s->s3->tmp.min_ver >= TLS1_3_VERSION
&& (lu->sig == EVP_PKEY_DSA || lu->hash_idx == SSL_MD_SHA1_IDX
|| lu->hash_idx == SSL_MD_MD5_IDX
|| lu->hash_idx == SSL_MD_SHA224_IDX))
return 0;
/* See if public key algorithm allowed */
if (ssl_cert_is_disabled(lu->sig_idx))
return 0;
if (lu->sig == NID_id_GostR3410_2012_256
|| lu->sig == NID_id_GostR3410_2012_512
|| lu->sig == NID_id_GostR3410_2001) {
/* We never allow GOST sig algs on the server with TLSv1.3 */
if (s->server && SSL_IS_TLS13(s))
return 0;
if (!s->server
&& s->method->version == TLS_ANY_VERSION
&& s->s3->tmp.max_ver >= TLS1_3_VERSION) {
int i, num;
STACK_OF(SSL_CIPHER) *sk;
/*
* We're a client that could negotiate TLSv1.3. We only allow GOST
* sig algs if we could negotiate TLSv1.2 or below and we have GOST
* ciphersuites enabled.
*/
if (s->s3->tmp.min_ver >= TLS1_3_VERSION)
return 0;
sk = SSL_get_ciphers(s);
num = sk != NULL ? sk_SSL_CIPHER_num(sk) : 0;
for (i = 0; i < num; 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 ((c->algorithm_mkey & SSL_kGOST) != 0)
break;
}
if (i == num)
return 0;
}
}
if (lu->hash == NID_undef)
return 1;
/* Security bits: half digest bits */
secbits = EVP_MD_size(ssl_md(lu->hash_idx)) * 4;
/* Finally see if security callback allows it */
sigalgstr[0] = (lu->sigalg >> 8) & 0xff;
sigalgstr[1] = lu->sigalg & 0xff;
return ssl_security(s, op, secbits, lu->hash, (void *)sigalgstr);
}
/*
* Get a mask of disabled public key algorithms based on supported signature
* algorithms. For example if no signature algorithm supports RSA then RSA is
* disabled.
*/
void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
{
const uint16_t *sigalgs;
size_t i, sigalgslen;
uint32_t disabled_mask = SSL_aRSA | SSL_aDSS | SSL_aECDSA;
/*
* Go through all signature algorithms seeing if we support any
* in disabled_mask.
*/
sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
for (i = 0; i < sigalgslen; i++, sigalgs++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*sigalgs);
const SSL_CERT_LOOKUP *clu;
if (lu == NULL)
continue;
clu = ssl_cert_lookup_by_idx(lu->sig_idx);
if (clu == NULL)
continue;
/* If algorithm is disabled see if we can enable it */
if ((clu->amask & disabled_mask) != 0
&& tls12_sigalg_allowed(s, op, lu))
disabled_mask &= ~clu->amask;
}
*pmask_a |= disabled_mask;
}
int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
const uint16_t *psig, size_t psiglen)
{
size_t i;
int rv = 0;
for (i = 0; i < psiglen; i++, psig++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*psig);
if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
continue;
if (!WPACKET_put_bytes_u16(pkt, *psig))
return 0;
/*
* If TLS 1.3 must have at least one valid TLS 1.3 message
* signing algorithm: i.e. neither RSA nor SHA1/SHA224
*/
if (rv == 0 && (!SSL_IS_TLS13(s)
|| (lu->sig != EVP_PKEY_RSA
&& lu->hash != NID_sha1
&& lu->hash != NID_sha224)))
rv = 1;
}
if (rv == 0)
SSLerr(SSL_F_TLS12_COPY_SIGALGS, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return rv;
}
/* Given preference and allowed sigalgs set shared sigalgs */
static size_t tls12_shared_sigalgs(SSL *s, const SIGALG_LOOKUP **shsig,
const uint16_t *pref, size_t preflen,
const uint16_t *allow, size_t allowlen)
{
const uint16_t *ptmp, *atmp;
size_t i, j, nmatch = 0;
for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*ptmp);
/* Skip disabled hashes or signature algorithms */
if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu))
continue;
for (j = 0, atmp = allow; j < allowlen; j++, atmp++) {
if (*ptmp == *atmp) {
nmatch++;
if (shsig)
*shsig++ = lu;
break;
}
}
}
return nmatch;
}
/* Set shared signature algorithms for SSL structures */
static int tls1_set_shared_sigalgs(SSL *s)
{
const uint16_t *pref, *allow, *conf;
size_t preflen, allowlen, conflen;
size_t nmatch;
const SIGALG_LOOKUP **salgs = NULL;
CERT *c = s->cert;
unsigned int is_suiteb = tls1_suiteb(s);
OPENSSL_free(c->shared_sigalgs);
c->shared_sigalgs = NULL;
c->shared_sigalgslen = 0;
/* If client use client signature algorithms if not NULL */
if (!s->server && c->client_sigalgs && !is_suiteb) {
conf = c->client_sigalgs;
conflen = c->client_sigalgslen;
} else if (c->conf_sigalgs && !is_suiteb) {
conf = c->conf_sigalgs;
conflen = c->conf_sigalgslen;
} else
conflen = tls12_get_psigalgs(s, 0, &conf);
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) {
pref = conf;
preflen = conflen;
allow = s->s3->tmp.peer_sigalgs;
allowlen = s->s3->tmp.peer_sigalgslen;
} else {
allow = conf;
allowlen = conflen;
pref = s->s3->tmp.peer_sigalgs;
preflen = s->s3->tmp.peer_sigalgslen;
}
nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen);
if (nmatch) {
if ((salgs = OPENSSL_malloc(nmatch * sizeof(*salgs))) == NULL) {
SSLerr(SSL_F_TLS1_SET_SHARED_SIGALGS, ERR_R_MALLOC_FAILURE);
return 0;
}
nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen);
} else {
salgs = NULL;
}
c->shared_sigalgs = salgs;
c->shared_sigalgslen = nmatch;
return 1;
}
int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen)
{
unsigned int stmp;
size_t size, i;
uint16_t *buf;
size = PACKET_remaining(pkt);
/* Invalid data length */
if (size == 0 || (size & 1) != 0)
return 0;
size >>= 1;
if ((buf = OPENSSL_malloc(size * sizeof(*buf))) == NULL) {
SSLerr(SSL_F_TLS1_SAVE_U16, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < size && PACKET_get_net_2(pkt, &stmp); i++)
buf[i] = stmp;
if (i != size) {
OPENSSL_free(buf);
return 0;
}
OPENSSL_free(*pdest);
*pdest = buf;
*pdestlen = size;
return 1;
}
int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert)
{
/* Extension ignored for inappropriate versions */
if (!SSL_USE_SIGALGS(s))
return 1;
/* Should never happen */
if (s->cert == NULL)
return 0;
if (cert)
return tls1_save_u16(pkt, &s->s3->tmp.peer_cert_sigalgs,
&s->s3->tmp.peer_cert_sigalgslen);
else
return tls1_save_u16(pkt, &s->s3->tmp.peer_sigalgs,
&s->s3->tmp.peer_sigalgslen);
}
/* Set preferred digest for each key type */
int tls1_process_sigalgs(SSL *s)
{
size_t i;
uint32_t *pvalid = s->s3->tmp.valid_flags;
CERT *c = s->cert;
if (!tls1_set_shared_sigalgs(s))
return 0;
for (i = 0; i < SSL_PKEY_NUM; i++)
pvalid[i] = 0;
for (i = 0; i < c->shared_sigalgslen; i++) {
const SIGALG_LOOKUP *sigptr = c->shared_sigalgs[i];
int idx = sigptr->sig_idx;
/* Ignore PKCS1 based sig algs in TLSv1.3 */
if (SSL_IS_TLS13(s) && sigptr->sig == EVP_PKEY_RSA)
continue;
/* If not disabled indicate we can explicitly sign */
if (pvalid[idx] == 0 && !ssl_cert_is_disabled(idx))
pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
}
return 1;
}
int SSL_get_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash)
{
uint16_t *psig = s->s3->tmp.peer_sigalgs;
size_t numsigalgs = s->s3->tmp.peer_sigalgslen;
if (psig == NULL || numsigalgs > INT_MAX)
return 0;
if (idx >= 0) {
const SIGALG_LOOKUP *lu;
if (idx >= (int)numsigalgs)
return 0;
psig += idx;
if (rhash != NULL)
*rhash = (unsigned char)((*psig >> 8) & 0xff);
if (rsig != NULL)
*rsig = (unsigned char)(*psig & 0xff);
lu = tls1_lookup_sigalg(*psig);
if (psign != NULL)
*psign = lu != NULL ? lu->sig : NID_undef;
if (phash != NULL)
*phash = lu != NULL ? lu->hash : NID_undef;
if (psignhash != NULL)
*psignhash = lu != NULL ? lu->sigandhash : NID_undef;
}
return (int)numsigalgs;
}
int SSL_get_shared_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash)
{
const SIGALG_LOOKUP *shsigalgs;
if (s->cert->shared_sigalgs == NULL
|| idx < 0
|| idx >= (int)s->cert->shared_sigalgslen
|| s->cert->shared_sigalgslen > INT_MAX)
return 0;
shsigalgs = s->cert->shared_sigalgs[idx];
if (phash != NULL)
*phash = shsigalgs->hash;
if (psign != NULL)
*psign = shsigalgs->sig;
if (psignhash != NULL)
*psignhash = shsigalgs->sigandhash;
if (rsig != NULL)
*rsig = (unsigned char)(shsigalgs->sigalg & 0xff);
if (rhash != NULL)
*rhash = (unsigned char)((shsigalgs->sigalg >> 8) & 0xff);
return (int)s->cert->shared_sigalgslen;
}
/* Maximum possible number of unique entries in sigalgs array */
#define TLS_MAX_SIGALGCNT (OSSL_NELEM(sigalg_lookup_tbl) * 2)
typedef struct {
size_t sigalgcnt;
/* TLSEXT_SIGALG_XXX values */
uint16_t sigalgs[TLS_MAX_SIGALGCNT];
} sig_cb_st;
static void get_sigorhash(int *psig, int *phash, const char *str)
{
if (strcmp(str, "RSA") == 0) {
*psig = EVP_PKEY_RSA;
} else if (strcmp(str, "RSA-PSS") == 0 || strcmp(str, "PSS") == 0) {
*psig = EVP_PKEY_RSA_PSS;
} else if (strcmp(str, "DSA") == 0) {
*psig = EVP_PKEY_DSA;
} else if (strcmp(str, "ECDSA") == 0) {
*psig = EVP_PKEY_EC;
} else {
*phash = OBJ_sn2nid(str);
if (*phash == NID_undef)
*phash = OBJ_ln2nid(str);
}
}
/* Maximum length of a signature algorithm string component */
#define TLS_MAX_SIGSTRING_LEN 40
static int sig_cb(const char *elem, int len, void *arg)
{
sig_cb_st *sarg = arg;
size_t i;
const SIGALG_LOOKUP *s;
char etmp[TLS_MAX_SIGSTRING_LEN], *p;
int sig_alg = NID_undef, hash_alg = NID_undef;
if (elem == NULL)
return 0;
if (sarg->sigalgcnt == TLS_MAX_SIGALGCNT)
return 0;
if (len > (int)(sizeof(etmp) - 1))
return 0;
memcpy(etmp, elem, len);
etmp[len] = 0;
p = strchr(etmp, '+');
/*
* We only allow SignatureSchemes listed in the sigalg_lookup_tbl;
* if there's no '+' in the provided name, look for the new-style combined
* name. If not, match both sig+hash to find the needed SIGALG_LOOKUP.
* Just sig+hash is not unique since TLS 1.3 adds rsa_pss_pss_* and
* rsa_pss_rsae_* that differ only by public key OID; in such cases
* we will pick the _rsae_ variant, by virtue of them appearing earlier
* in the table.
*/
if (p == NULL) {
for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
i++, s++) {
if (s->name != NULL && strcmp(etmp, s->name) == 0) {
sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
break;
}
}
if (i == OSSL_NELEM(sigalg_lookup_tbl))
return 0;
} else {
*p = 0;
p++;
if (*p == 0)
return 0;
get_sigorhash(&sig_alg, &hash_alg, etmp);
get_sigorhash(&sig_alg, &hash_alg, p);
if (sig_alg == NID_undef || hash_alg == NID_undef)
return 0;
for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
i++, s++) {
if (s->hash == hash_alg && s->sig == sig_alg) {
sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
break;
}
}
if (i == OSSL_NELEM(sigalg_lookup_tbl))
return 0;
}
/* Reject duplicates */
for (i = 0; i < sarg->sigalgcnt - 1; i++) {
if (sarg->sigalgs[i] == sarg->sigalgs[sarg->sigalgcnt - 1]) {
sarg->sigalgcnt--;
return 0;
}
}
return 1;
}
/*
* Set supported signature algorithms based on a colon separated list of the
* form sig+hash e.g. RSA+SHA512:DSA+SHA512
*/
int tls1_set_sigalgs_list(CERT *c, const char *str, int client)
{
sig_cb_st sig;
sig.sigalgcnt = 0;
if (!CONF_parse_list(str, ':', 1, sig_cb, &sig))
return 0;
if (c == NULL)
return 1;
return tls1_set_raw_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
}
int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen,
int client)
{
uint16_t *sigalgs;
if ((sigalgs = OPENSSL_malloc(salglen * sizeof(*sigalgs))) == NULL) {
SSLerr(SSL_F_TLS1_SET_RAW_SIGALGS, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(sigalgs, psigs, salglen * sizeof(*sigalgs));
if (client) {
OPENSSL_free(c->client_sigalgs);
c->client_sigalgs = sigalgs;
c->client_sigalgslen = salglen;
} else {
OPENSSL_free(c->conf_sigalgs);
c->conf_sigalgs = sigalgs;
c->conf_sigalgslen = salglen;
}
return 1;
}
int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client)
{
uint16_t *sigalgs, *sptr;
size_t i;
if (salglen & 1)
return 0;
if ((sigalgs = OPENSSL_malloc((salglen / 2) * sizeof(*sigalgs))) == NULL) {
SSLerr(SSL_F_TLS1_SET_SIGALGS, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0, sptr = sigalgs; i < salglen; i += 2) {
size_t j;
const SIGALG_LOOKUP *curr;
int md_id = *psig_nids++;
int sig_id = *psig_nids++;
for (j = 0, curr = sigalg_lookup_tbl; j < OSSL_NELEM(sigalg_lookup_tbl);
j++, curr++) {
if (curr->hash == md_id && curr->sig == sig_id) {
*sptr++ = curr->sigalg;
break;
}
}
if (j == OSSL_NELEM(sigalg_lookup_tbl))
goto err;
}
if (client) {
OPENSSL_free(c->client_sigalgs);
c->client_sigalgs = sigalgs;
c->client_sigalgslen = salglen / 2;
} else {
OPENSSL_free(c->conf_sigalgs);
c->conf_sigalgs = sigalgs;
c->conf_sigalgslen = salglen / 2;
}
return 1;
err:
OPENSSL_free(sigalgs);
return 0;
}
static int tls1_check_sig_alg(CERT *c, X509 *x, int default_nid)
{
int sig_nid;
size_t i;
if (default_nid == -1)
return 1;
sig_nid = X509_get_signature_nid(x);
if (default_nid)
return sig_nid == default_nid ? 1 : 0;
for (i = 0; i < c->shared_sigalgslen; i++)
if (sig_nid == c->shared_sigalgs[i]->sigandhash)
return 1;
return 0;
}
/* Check to see if a certificate issuer name matches list of CA names */
static int ssl_check_ca_name(STACK_OF(X509_NAME) *names, X509 *x)
{
X509_NAME *nm;
int i;
nm = X509_get_issuer_name(x);
for (i = 0; i < sk_X509_NAME_num(names); i++) {
if (!X509_NAME_cmp(nm, sk_X509_NAME_value(names, i)))
return 1;
}
return 0;
}
/*
* Check certificate chain is consistent with TLS extensions and is usable by
* server. This servers two purposes: it allows users to check chains before
* passing them to the server and it allows the server to check chains before
* attempting to use them.
*/
/* Flags which need to be set for a certificate when strict mode not set */
#define CERT_PKEY_VALID_FLAGS \
(CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM)
/* Strict mode flags */
#define CERT_PKEY_STRICT_FLAGS \
(CERT_PKEY_VALID_FLAGS|CERT_PKEY_CA_SIGNATURE|CERT_PKEY_CA_PARAM \
| CERT_PKEY_ISSUER_NAME|CERT_PKEY_CERT_TYPE)
int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
int idx)
{
int i;
int rv = 0;
int check_flags = 0, strict_mode;
CERT_PKEY *cpk = NULL;
CERT *c = s->cert;
uint32_t *pvalid;
unsigned int suiteb_flags = tls1_suiteb(s);
/* idx == -1 means checking server chains */
if (idx != -1) {
/* idx == -2 means checking client certificate chains */
if (idx == -2) {
cpk = c->key;
idx = (int)(cpk - c->pkeys);
} else
cpk = c->pkeys + idx;
pvalid = s->s3->tmp.valid_flags + idx;
x = cpk->x509;
pk = cpk->privatekey;
chain = cpk->chain;
strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT;
/* If no cert or key, forget it */
if (!x || !pk)
goto end;
} else {
size_t certidx;
if (!x || !pk)
return 0;
if (ssl_cert_lookup_by_pkey(pk, &certidx) == NULL)
return 0;
idx = certidx;
pvalid = s->s3->tmp.valid_flags + idx;
if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
check_flags = CERT_PKEY_STRICT_FLAGS;
else
check_flags = CERT_PKEY_VALID_FLAGS;
strict_mode = 1;
}
if (suiteb_flags) {
int ok;
if (check_flags)
check_flags |= CERT_PKEY_SUITEB;
ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags);
if (ok == X509_V_OK)
rv |= CERT_PKEY_SUITEB;
else if (!check_flags)
goto end;
}
/*
* Check all signature algorithms are consistent with signature
* algorithms extension if TLS 1.2 or later and strict mode.
*/
if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
int default_nid;
int rsign = 0;
if (s->s3->tmp.peer_cert_sigalgs != NULL
|| s->s3->tmp.peer_sigalgs != NULL) {
default_nid = 0;
/* If no sigalgs extension use defaults from RFC5246 */
} else {
switch (idx) {
case SSL_PKEY_RSA:
rsign = EVP_PKEY_RSA;
default_nid = NID_sha1WithRSAEncryption;
break;
case SSL_PKEY_DSA_SIGN:
rsign = EVP_PKEY_DSA;
default_nid = NID_dsaWithSHA1;
break;
case SSL_PKEY_ECC:
rsign = EVP_PKEY_EC;
default_nid = NID_ecdsa_with_SHA1;
break;
case SSL_PKEY_GOST01:
rsign = NID_id_GostR3410_2001;
default_nid = NID_id_GostR3411_94_with_GostR3410_2001;
break;
case SSL_PKEY_GOST12_256:
rsign = NID_id_GostR3410_2012_256;
default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256;
break;
case SSL_PKEY_GOST12_512:
rsign = NID_id_GostR3410_2012_512;
default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512;
break;
default:
default_nid = -1;
break;
}
}
/*
* If peer sent no signature algorithms extension and we have set
* preferred signature algorithms check we support sha1.
*/
if (default_nid > 0 && c->conf_sigalgs) {
size_t j;
const uint16_t *p = c->conf_sigalgs;
for (j = 0; j < c->conf_sigalgslen; j++, p++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*p);
if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign)
break;
}
if (j == c->conf_sigalgslen) {
if (check_flags)
goto skip_sigs;
else
goto end;
}
}
/* Check signature algorithm of each cert in chain */
if (!tls1_check_sig_alg(c, x, default_nid)) {
if (!check_flags)
goto end;
} else
rv |= CERT_PKEY_EE_SIGNATURE;
rv |= CERT_PKEY_CA_SIGNATURE;
for (i = 0; i < sk_X509_num(chain); i++) {
if (!tls1_check_sig_alg(c, sk_X509_value(chain, i), default_nid)) {
if (check_flags) {
rv &= ~CERT_PKEY_CA_SIGNATURE;
break;
} else
goto end;
}
}
}
/* Else not TLS 1.2, so mark EE and CA signing algorithms OK */
else if (check_flags)
rv |= CERT_PKEY_EE_SIGNATURE | CERT_PKEY_CA_SIGNATURE;
skip_sigs:
/* Check cert parameters are consistent */
if (tls1_check_cert_param(s, x, 1))
rv |= CERT_PKEY_EE_PARAM;
else if (!check_flags)
goto end;
if (!s->server)
rv |= CERT_PKEY_CA_PARAM;
/* In strict mode check rest of chain too */
else if (strict_mode) {
rv |= CERT_PKEY_CA_PARAM;
for (i = 0; i < sk_X509_num(chain); i++) {
X509 *ca = sk_X509_value(chain, i);
if (!tls1_check_cert_param(s, ca, 0)) {
if (check_flags) {
rv &= ~CERT_PKEY_CA_PARAM;
break;
} else
goto end;
}
}
}
if (!s->server && strict_mode) {
STACK_OF(X509_NAME) *ca_dn;
int check_type = 0;
switch (EVP_PKEY_id(pk)) {
case EVP_PKEY_RSA:
check_type = TLS_CT_RSA_SIGN;
break;
case EVP_PKEY_DSA:
check_type = TLS_CT_DSS_SIGN;
break;
case EVP_PKEY_EC:
check_type = TLS_CT_ECDSA_SIGN;
break;
}
if (check_type) {
const uint8_t *ctypes = s->s3->tmp.ctype;
size_t j;
for (j = 0; j < s->s3->tmp.ctype_len; j++, ctypes++) {
if (*ctypes == check_type) {
rv |= CERT_PKEY_CERT_TYPE;
break;
}
}
if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags)
goto end;
} else {
rv |= CERT_PKEY_CERT_TYPE;
}
ca_dn = s->s3->tmp.peer_ca_names;
if (!sk_X509_NAME_num(ca_dn))
rv |= CERT_PKEY_ISSUER_NAME;
if (!(rv & CERT_PKEY_ISSUER_NAME)) {
if (ssl_check_ca_name(ca_dn, x))
rv |= CERT_PKEY_ISSUER_NAME;
}
if (!(rv & CERT_PKEY_ISSUER_NAME)) {
for (i = 0; i < sk_X509_num(chain); i++) {
X509 *xtmp = sk_X509_value(chain, i);
if (ssl_check_ca_name(ca_dn, xtmp)) {
rv |= CERT_PKEY_ISSUER_NAME;
break;
}
}
}
if (!check_flags && !(rv & CERT_PKEY_ISSUER_NAME))
goto end;
} else
rv |= CERT_PKEY_ISSUER_NAME | CERT_PKEY_CERT_TYPE;
if (!check_flags || (rv & check_flags) == check_flags)
rv |= CERT_PKEY_VALID;
end:
if (TLS1_get_version(s) >= TLS1_2_VERSION)
rv |= *pvalid & (CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN);
else
rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN;
/*
* When checking a CERT_PKEY structure all flags are irrelevant if the
* chain is invalid.
*/
if (!check_flags) {
if (rv & CERT_PKEY_VALID) {
*pvalid = rv;
} else {
/* Preserve sign and explicit sign flag, clear rest */
*pvalid &= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
return 0;
}
}
return rv;
}
/* Set validity of certificates in an SSL structure */
void tls1_set_cert_validity(SSL *s)
{
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_PSS_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_256);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED25519);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED448);
}
/* User level utility function to check a chain is suitable */
int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
{
return tls1_check_chain(s, x, pk, chain, -1);
}
#ifndef OPENSSL_NO_DH
DH *ssl_get_auto_dh(SSL *s)
{
int dh_secbits = 80;
if (s->cert->dh_tmp_auto == 2)
return DH_get_1024_160();
if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
if (s->s3->tmp.new_cipher->strength_bits == 256)
dh_secbits = 128;
else
dh_secbits = 80;
} else {
if (s->s3->tmp.cert == NULL)
return NULL;
dh_secbits = EVP_PKEY_security_bits(s->s3->tmp.cert->privatekey);
}
if (dh_secbits >= 128) {
DH *dhp = DH_new();
BIGNUM *p, *g;
if (dhp == NULL)
return NULL;
g = BN_new();
if (g == NULL || !BN_set_word(g, 2)) {
DH_free(dhp);
BN_free(g);
return NULL;
}
if (dh_secbits >= 192)
p = BN_get_rfc3526_prime_8192(NULL);
else
p = BN_get_rfc3526_prime_3072(NULL);
if (p == NULL || !DH_set0_pqg(dhp, p, NULL, g)) {
DH_free(dhp);
BN_free(p);
BN_free(g);
return NULL;
}
return dhp;
}
if (dh_secbits >= 112)
return DH_get_2048_224();
return DH_get_1024_160();
}
#endif
static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op)
{
int secbits = -1;
EVP_PKEY *pkey = X509_get0_pubkey(x);
if (pkey) {
/*
* If no parameters this will return -1 and fail using the default
* security callback for any non-zero security level. This will
* reject keys which omit parameters but this only affects DSA and
* omission of parameters is never (?) done in practice.
*/
secbits = EVP_PKEY_security_bits(pkey);
}
if (s)
return ssl_security(s, op, secbits, 0, x);
else
return ssl_ctx_security(ctx, op, secbits, 0, x);
}
static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
{
/* Lookup signature algorithm digest */
int secbits, nid, pknid;
/* Don't check signature if self signed */
if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0)
return 1;
if (!X509_get_signature_info(x, &nid, &pknid, &secbits, NULL))
secbits = -1;
/* If digest NID not defined use signature NID */
if (nid == NID_undef)
nid = pknid;
if (s)
return ssl_security(s, op, secbits, nid, x);
else
return ssl_ctx_security(ctx, op, secbits, nid, x);
}
int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee)
{
if (vfy)
vfy = SSL_SECOP_PEER;
if (is_ee) {
if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy))
return SSL_R_EE_KEY_TOO_SMALL;
} else {
if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy))
return SSL_R_CA_KEY_TOO_SMALL;
}
if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy))
return SSL_R_CA_MD_TOO_WEAK;
return 1;
}
/*
* Check security of a chain, if |sk| includes the end entity certificate then
* |x| is NULL. If |vfy| is 1 then we are verifying a peer chain and not sending
* one to the peer. Return values: 1 if ok otherwise error code to use
*/
int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy)
{
int rv, start_idx, i;
if (x == NULL) {
x = sk_X509_value(sk, 0);
start_idx = 1;
} else
start_idx = 0;
rv = ssl_security_cert(s, NULL, x, vfy, 1);
if (rv != 1)
return rv;
for (i = start_idx; i < sk_X509_num(sk); i++) {
x = sk_X509_value(sk, i);
rv = ssl_security_cert(s, NULL, x, vfy, 0);
if (rv != 1)
return rv;
}
return 1;
}
/*
* For TLS 1.2 servers check if we have a certificate which can be used
* with the signature algorithm "lu" and return index of certificate.
*/
static int tls12_get_cert_sigalg_idx(const SSL *s, const SIGALG_LOOKUP *lu)
{
int sig_idx = lu->sig_idx;
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(sig_idx);
/* If not recognised or not supported by cipher mask it is not suitable */
if (clu == NULL
|| (clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0
|| (clu->nid == EVP_PKEY_RSA_PSS
&& (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA) != 0))
return -1;
return s->s3->tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
}
/*
* Returns true if |s| has a usable certificate configured for use
* with signature scheme |sig|.
* "Usable" includes a check for presence as well as applying
* the signature_algorithm_cert restrictions sent by the peer (if any).
* Returns false if no usable certificate is found.
*/
static int has_usable_cert(SSL *s, const SIGALG_LOOKUP *sig, int idx)
{
const SIGALG_LOOKUP *lu;
int mdnid, pknid;
size_t i;
/* TLS 1.2 callers can override lu->sig_idx, but not TLS 1.3 callers. */
if (idx == -1)
idx = sig->sig_idx;
if (!ssl_has_cert(s, idx))
return 0;
if (s->s3->tmp.peer_cert_sigalgs != NULL) {
for (i = 0; i < s->s3->tmp.peer_cert_sigalgslen; i++) {
lu = tls1_lookup_sigalg(s->s3->tmp.peer_cert_sigalgs[i]);
if (lu == NULL
|| !X509_get_signature_info(s->cert->pkeys[idx].x509, &mdnid,
&pknid, NULL, NULL))
continue;
/*
* TODO this does not differentiate between the
* rsa_pss_pss_* and rsa_pss_rsae_* schemes since we do not
* have a chain here that lets us look at the key OID in the
* signing certificate.
*/
if (mdnid == lu->hash && pknid == lu->sig)
return 1;
}
return 0;
}
return 1;
}
/*
* Choose an appropriate signature algorithm based on available certificates
* Sets chosen certificate and signature algorithm.
*
* For servers if we fail to find a required certificate it is a fatal error,
* an appropriate error code is set and a TLS alert is sent.
*
* For clients fatalerrs is set to 0. If a certificate is not suitable it is not
* a fatal error: we will either try another certificate or not present one
* to the server. In this case no error is set.
*/
int tls_choose_sigalg(SSL *s, int fatalerrs)
{
const SIGALG_LOOKUP *lu = NULL;
int sig_idx = -1;
s->s3->tmp.cert = NULL;
s->s3->tmp.sigalg = NULL;
if (SSL_IS_TLS13(s)) {
size_t i;
#ifndef OPENSSL_NO_EC
int curve = -1;
#endif
/* Look for a certificate matching shared sigalgs */
for (i = 0; i < s->cert->shared_sigalgslen; i++) {
lu = s->cert->shared_sigalgs[i];
sig_idx = -1;
/* Skip SHA1, SHA224, DSA and RSA if not PSS */
if (lu->hash == NID_sha1
|| lu->hash == NID_sha224
|| lu->sig == EVP_PKEY_DSA
|| lu->sig == EVP_PKEY_RSA)
continue;
/* Check that we have a cert, and signature_algorithms_cert */
if (!tls1_lookup_md(lu, NULL) || !has_usable_cert(s, lu, -1))
continue;
if (lu->sig == EVP_PKEY_EC) {
#ifndef OPENSSL_NO_EC
if (curve == -1) {
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
}
if (lu->curve != NID_undef && curve != lu->curve)
continue;
#else
continue;
#endif
} else if (lu->sig == EVP_PKEY_RSA_PSS) {
/* validate that key is large enough for the signature algorithm */
EVP_PKEY *pkey;
pkey = s->cert->pkeys[lu->sig_idx].privatekey;
if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(pkey), lu))
continue;
}
break;
}
if (i == s->cert->shared_sigalgslen) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CHOOSE_SIGALG,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
} else {
/* If ciphersuite doesn't require a cert nothing to do */
if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aCERT))
return 1;
if (!s->server && !ssl_has_cert(s, s->cert->key - s->cert->pkeys))
return 1;
if (SSL_USE_SIGALGS(s)) {
size_t i;
if (s->s3->tmp.peer_sigalgs != NULL) {
#ifndef OPENSSL_NO_EC
int curve;
/* For Suite B need to match signature algorithm to curve */
if (tls1_suiteb(s)) {
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
} else {
curve = -1;
}
#endif
/*
* Find highest preference signature algorithm matching
* cert type
*/
for (i = 0; i < s->cert->shared_sigalgslen; i++) {
lu = s->cert->shared_sigalgs[i];
if (s->server) {
if ((sig_idx = tls12_get_cert_sigalg_idx(s, lu)) == -1)
continue;
} else {
int cc_idx = s->cert->key - s->cert->pkeys;
sig_idx = lu->sig_idx;
if (cc_idx != sig_idx)
continue;
}
/* Check that we have a cert, and sig_algs_cert */
if (!has_usable_cert(s, lu, sig_idx))
continue;
if (lu->sig == EVP_PKEY_RSA_PSS) {
/* validate that key is large enough for the signature algorithm */
EVP_PKEY *pkey = s->cert->pkeys[sig_idx].privatekey;
if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(pkey), lu))
continue;
}
#ifndef OPENSSL_NO_EC
if (curve == -1 || lu->curve == curve)
#endif
break;
}
if (i == s->cert->shared_sigalgslen) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_CHOOSE_SIGALG,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
} else {
/*
* If we have no sigalg use defaults
*/
const uint16_t *sent_sigs;
size_t sent_sigslen;
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
if (lu->sigalg == *sent_sigs
&& has_usable_cert(s, lu, lu->sig_idx))
break;
}
if (i == sent_sigslen) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_CHOOSE_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
} else {
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
}
if (sig_idx == -1)
sig_idx = lu->sig_idx;
s->s3->tmp.cert = &s->cert->pkeys[sig_idx];
s->cert->key = s->s3->tmp.cert;
s->s3->tmp.sigalg = lu;
return 1;
}
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode)
{
if (mode != TLSEXT_max_fragment_length_DISABLED
&& !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
SSLerr(SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
ctx->ext.max_fragment_len_mode = mode;
return 1;
}
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode)
{
if (mode != TLSEXT_max_fragment_length_DISABLED
&& !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
SSLerr(SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
ssl->ext.max_fragment_len_mode = mode;
return 1;
}
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session)
{
return session->ext.max_fragment_len_mode;
}
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index f7ab0fa47040..b6825d20c2dc 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -1,810 +1,818 @@
/*
* Copyright 2016-2018 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 <stdlib.h>
#include "ssl_locl.h"
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/kdf.h>
-#define TLS13_MAX_LABEL_LEN 246
+/*
+ * RFC 8446, 7.1 Key Schedule, says:
+ * Note: With common hash functions, any label longer than 12 characters
+ * requires an additional iteration of the hash function to compute.
+ * The labels in this specification have all been chosen to fit within
+ * this limit.
+ */
+#define TLS13_MAX_LABEL_LEN 12
/* Always filled with zeros */
static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
/*
* Given a |secret|; a |label| of length |labellen|; and |data| of length
* |datalen| (e.g. typically a hash of the handshake messages), derive a new
* secret |outlen| bytes long and store it in the location pointed to be |out|.
* The |data| value may be zero length. Returns 1 on success 0 on failure.
*/
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)
{
- const unsigned char label_prefix[] = "tls13 ";
+ static const unsigned char label_prefix[] = "tls13 ";
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
int ret;
size_t hkdflabellen;
size_t hashlen;
/*
- * 2 bytes for length of whole HkdfLabel + 1 byte for length of combined
- * prefix and label + bytes for the label itself + bytes for the hash
+ * 2 bytes for length of derived secret + 1 byte for length of combined
+ * prefix and label + bytes for the label itself + 1 byte length of hash
+ * + bytes for the hash itself
*/
unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t) +
+ sizeof(label_prefix) + TLS13_MAX_LABEL_LEN
+ EVP_MAX_MD_SIZE];
WPACKET pkt;
if (pctx == NULL)
return 0;
hashlen = EVP_MD_size(md);
if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
|| !WPACKET_put_bytes_u16(&pkt, outlen)
|| !WPACKET_start_sub_packet_u8(&pkt)
|| !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1)
|| !WPACKET_memcpy(&pkt, label, labellen)
|| !WPACKET_close(&pkt)
|| !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
|| !WPACKET_get_total_written(&pkt, &hkdflabellen)
|| !WPACKET_finish(&pkt)) {
EVP_PKEY_CTX_free(pctx);
WPACKET_cleanup(&pkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
ERR_R_INTERNAL_ERROR);
return 0;
}
ret = EVP_PKEY_derive_init(pctx) <= 0
|| EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY)
<= 0
|| EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0
|| EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, hashlen) <= 0
|| EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdflabel, hkdflabellen) <= 0
|| EVP_PKEY_derive(pctx, out, &outlen) <= 0;
EVP_PKEY_CTX_free(pctx);
if (ret != 0)
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
ERR_R_INTERNAL_ERROR);
return ret == 0;
}
/*
* Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on
* success 0 on failure.
*/
int tls13_derive_key(SSL *s, const EVP_MD *md, const unsigned char *secret,
unsigned char *key, size_t keylen)
{
static const unsigned char keylabel[] = "key";
return tls13_hkdf_expand(s, md, secret, keylabel, sizeof(keylabel) - 1,
NULL, 0, key, keylen);
}
/*
* Given a |secret| generate an |iv| of length |ivlen| bytes. Returns 1 on
* success 0 on failure.
*/
int tls13_derive_iv(SSL *s, const EVP_MD *md, const unsigned char *secret,
unsigned char *iv, size_t ivlen)
{
static const unsigned char ivlabel[] = "iv";
return tls13_hkdf_expand(s, md, secret, ivlabel, sizeof(ivlabel) - 1,
NULL, 0, iv, ivlen);
}
int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
const unsigned char *secret,
unsigned char *fin, size_t finlen)
{
static const unsigned char finishedlabel[] = "finished";
return tls13_hkdf_expand(s, md, secret, finishedlabel,
sizeof(finishedlabel) - 1, NULL, 0, fin, finlen);
}
/*
* Given the previous secret |prevsecret| and a new input secret |insecret| of
* length |insecretlen|, generate a new secret and store it in the location
* pointed to by |outsecret|. Returns 1 on success 0 on failure.
*/
int tls13_generate_secret(SSL *s, const EVP_MD *md,
const unsigned char *prevsecret,
const unsigned char *insecret,
size_t insecretlen,
unsigned char *outsecret)
{
size_t mdlen, prevsecretlen;
int mdleni;
int ret;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
static const char derived_secret_label[] = "derived";
unsigned char preextractsec[EVP_MAX_MD_SIZE];
if (pctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
ERR_R_INTERNAL_ERROR);
return 0;
}
mdleni = EVP_MD_size(md);
/* Ensure cast to size_t is safe */
if (!ossl_assert(mdleni >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
ERR_R_INTERNAL_ERROR);
return 0;
}
mdlen = (size_t)mdleni;
if (insecret == NULL) {
insecret = default_zeros;
insecretlen = mdlen;
}
if (prevsecret == NULL) {
prevsecret = default_zeros;
prevsecretlen = 0;
} else {
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
unsigned char hash[EVP_MAX_MD_SIZE];
/* The pre-extract derive step uses a hash of no messages */
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_TLS13_GENERATE_SECRET,
ERR_R_INTERNAL_ERROR);
EVP_MD_CTX_free(mctx);
EVP_PKEY_CTX_free(pctx);
return 0;
}
EVP_MD_CTX_free(mctx);
/* Generate the pre-extract secret */
if (!tls13_hkdf_expand(s, md, prevsecret,
(unsigned char *)derived_secret_label,
sizeof(derived_secret_label) - 1, hash, mdlen,
preextractsec, mdlen)) {
/* SSLfatal() already called */
EVP_PKEY_CTX_free(pctx);
return 0;
}
prevsecret = preextractsec;
prevsecretlen = mdlen;
}
ret = EVP_PKEY_derive_init(pctx) <= 0
|| EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY)
<= 0
|| EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0
|| EVP_PKEY_CTX_set1_hkdf_key(pctx, insecret, insecretlen) <= 0
|| EVP_PKEY_CTX_set1_hkdf_salt(pctx, prevsecret, prevsecretlen)
<= 0
|| EVP_PKEY_derive(pctx, outsecret, &mdlen)
<= 0;
if (ret != 0)
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
ERR_R_INTERNAL_ERROR);
EVP_PKEY_CTX_free(pctx);
if (prevsecret == preextractsec)
OPENSSL_cleanse(preextractsec, mdlen);
return ret == 0;
}
/*
* Given an input secret |insecret| of length |insecretlen| generate the
* handshake secret. This requires the early secret to already have been
* generated. Returns 1 on success 0 on failure.
*/
int tls13_generate_handshake_secret(SSL *s, const unsigned char *insecret,
size_t insecretlen)
{
/* Calls SSLfatal() if required */
return tls13_generate_secret(s, ssl_handshake_md(s), s->early_secret,
insecret, insecretlen,
(unsigned char *)&s->handshake_secret);
}
/*
* Given the handshake secret |prev| of length |prevlen| generate the master
* secret and store its length in |*secret_size|. Returns 1 on success 0 on
* failure.
*/
int tls13_generate_master_secret(SSL *s, unsigned char *out,
unsigned char *prev, size_t prevlen,
size_t *secret_size)
{
const EVP_MD *md = ssl_handshake_md(s);
*secret_size = EVP_MD_size(md);
/* Calls SSLfatal() if required */
return tls13_generate_secret(s, md, prev, NULL, 0, out);
}
/*
* Generates the mac for the Finished message. Returns the length of the MAC or
* 0 on error.
*/
size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
unsigned char *out)
{
const EVP_MD *md = ssl_handshake_md(s);
unsigned char hash[EVP_MAX_MD_SIZE];
size_t hashlen, ret = 0;
EVP_PKEY *key = NULL;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
/* SSLfatal() already called */
goto err;
}
if (str == s->method->ssl3_enc->server_finished_label) {
key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
s->server_finished_secret, hashlen);
} else if (SSL_IS_FIRST_HANDSHAKE(s)) {
key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
s->client_finished_secret, hashlen);
} else {
unsigned char finsecret[EVP_MAX_MD_SIZE];
if (!tls13_derive_finishedkey(s, ssl_handshake_md(s),
s->client_app_traffic_secret,
finsecret, hashlen))
goto err;
key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret,
hashlen);
OPENSSL_cleanse(finsecret, sizeof(finsecret));
}
if (key == NULL
|| ctx == NULL
|| EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0
|| EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0
|| EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC,
ERR_R_INTERNAL_ERROR);
goto err;
}
ret = hashlen;
err:
EVP_PKEY_free(key);
EVP_MD_CTX_free(ctx);
return ret;
}
/*
* There isn't really a key block in TLSv1.3, but we still need this function
* for initialising the cipher and hash. Returns 1 on success or 0 on failure.
*/
int tls13_setup_key_block(SSL *s)
{
const EVP_CIPHER *c;
const EVP_MD *hash;
int mac_type = NID_undef;
s->session->cipher = s->s3->tmp.new_cipher;
if (!ssl_cipher_get_evp
(s->session, &c, &hash, &mac_type, NULL, NULL, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_SETUP_KEY_BLOCK,
SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
return 0;
}
s->s3->tmp.new_sym_enc = c;
s->s3->tmp.new_hash = hash;
return 1;
}
static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
const EVP_CIPHER *ciph,
const unsigned char *insecret,
const unsigned char *hash,
const unsigned char *label,
size_t labellen, unsigned char *secret,
unsigned char *iv, EVP_CIPHER_CTX *ciph_ctx)
{
unsigned char key[EVP_MAX_KEY_LENGTH];
size_t ivlen, keylen, taglen;
int hashleni = EVP_MD_size(md);
size_t hashlen;
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV,
ERR_R_EVP_LIB);
goto err;
}
hashlen = (size_t)hashleni;
if (!tls13_hkdf_expand(s, md, insecret, label, labellen, hash, hashlen,
secret, hashlen)) {
/* SSLfatal() already called */
goto err;
}
/* TODO(size_t): convert me */
keylen = EVP_CIPHER_key_length(ciph);
if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) {
uint32_t algenc;
ivlen = EVP_CCM_TLS_IV_LEN;
if (s->s3->tmp.new_cipher == NULL) {
/* We've not selected a cipher yet - we must be doing early data */
algenc = s->session->cipher->algorithm_enc;
} else {
algenc = s->s3->tmp.new_cipher->algorithm_enc;
}
if (algenc & (SSL_AES128CCM8 | SSL_AES256CCM8))
taglen = EVP_CCM8_TLS_TAG_LEN;
else
taglen = EVP_CCM_TLS_TAG_LEN;
} else {
ivlen = EVP_CIPHER_iv_length(ciph);
taglen = 0;
}
if (!tls13_derive_key(s, md, secret, key, keylen)
|| !tls13_derive_iv(s, md, secret, iv, ivlen)) {
/* SSLfatal() already called */
goto err;
}
if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, sending) <= 0
|| !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
|| (taglen != 0 && !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG,
taglen, NULL))
|| EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV,
ERR_R_EVP_LIB);
goto err;
}
return 1;
err:
OPENSSL_cleanse(key, sizeof(key));
return 0;
}
int tls13_change_cipher_state(SSL *s, int which)
{
static const unsigned char client_early_traffic[] = "c e traffic";
static const unsigned char client_handshake_traffic[] = "c hs traffic";
static const unsigned char client_application_traffic[] = "c ap traffic";
static const unsigned char server_handshake_traffic[] = "s hs traffic";
static const unsigned char server_application_traffic[] = "s ap traffic";
static const unsigned char exporter_master_secret[] = "exp master";
static const unsigned char resumption_master_secret[] = "res master";
static const unsigned char early_exporter_master_secret[] = "e exp master";
unsigned char *iv;
unsigned char secret[EVP_MAX_MD_SIZE];
unsigned char hashval[EVP_MAX_MD_SIZE];
unsigned char *hash = hashval;
unsigned char *insecret;
unsigned char *finsecret = NULL;
const char *log_label = NULL;
EVP_CIPHER_CTX *ciph_ctx;
size_t finsecretlen = 0;
const unsigned char *label;
size_t labellen, hashlen = 0;
int ret = 0;
const EVP_MD *md = NULL;
const EVP_CIPHER *cipher = NULL;
if (which & SSL3_CC_READ) {
if (s->enc_read_ctx != NULL) {
EVP_CIPHER_CTX_reset(s->enc_read_ctx);
} else {
s->enc_read_ctx = EVP_CIPHER_CTX_new();
if (s->enc_read_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
goto err;
}
}
ciph_ctx = s->enc_read_ctx;
iv = s->read_iv;
RECORD_LAYER_reset_read_sequence(&s->rlayer);
} else {
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
if (s->enc_write_ctx != NULL) {
EVP_CIPHER_CTX_reset(s->enc_write_ctx);
} else {
s->enc_write_ctx = EVP_CIPHER_CTX_new();
if (s->enc_write_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
goto err;
}
}
ciph_ctx = s->enc_write_ctx;
iv = s->write_iv;
RECORD_LAYER_reset_write_sequence(&s->rlayer);
}
if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE))
|| ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) {
if (which & SSL3_CC_EARLY) {
EVP_MD_CTX *mdctx = NULL;
long handlen;
void *hdata;
unsigned int hashlenui;
const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session);
insecret = s->early_secret;
label = client_early_traffic;
labellen = sizeof(client_early_traffic) - 1;
log_label = CLIENT_EARLY_LABEL;
handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
if (handlen <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE,
SSL_R_BAD_HANDSHAKE_LENGTH);
goto err;
}
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
&& s->max_early_data > 0
&& s->session->ext.max_early_data == 0) {
/*
* If we are attempting to send early data, and we've decided to
* actually do it but max_early_data in s->session is 0 then we
* must be using an external PSK.
*/
if (!ossl_assert(s->psksession != NULL
&& s->max_early_data ==
s->psksession->ext.max_early_data)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
sslcipher = SSL_SESSION_get0_cipher(s->psksession);
}
if (sslcipher == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK);
goto err;
}
/*
* We need to calculate the handshake digest using the digest from
* the session. We haven't yet selected our ciphersuite so we can't
* use ssl_handshake_md().
*/
mdctx = EVP_MD_CTX_new();
if (mdctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
goto err;
}
cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher));
md = ssl_md(sslcipher->algorithm2);
if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
|| !EVP_DigestUpdate(mdctx, hdata, handlen)
|| !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
EVP_MD_CTX_free(mdctx);
goto err;
}
hashlen = hashlenui;
EVP_MD_CTX_free(mdctx);
if (!tls13_hkdf_expand(s, md, insecret,
early_exporter_master_secret,
sizeof(early_exporter_master_secret) - 1,
hashval, hashlen,
s->early_exporter_master_secret, hashlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!ssl_log_secret(s, EARLY_EXPORTER_SECRET_LABEL,
s->early_exporter_master_secret, hashlen)) {
/* SSLfatal() already called */
goto err;
}
} else if (which & SSL3_CC_HANDSHAKE) {
insecret = s->handshake_secret;
finsecret = s->client_finished_secret;
finsecretlen = EVP_MD_size(ssl_handshake_md(s));
label = client_handshake_traffic;
labellen = sizeof(client_handshake_traffic) - 1;
log_label = CLIENT_HANDSHAKE_LABEL;
/*
* The handshake hash used for the server read/client write handshake
* traffic secret is the same as the hash for the server
* write/client read handshake traffic secret. However, if we
* processed early data then we delay changing the server
* read/client write cipher state until later, and the handshake
* hashes have moved on. Therefore we use the value saved earlier
* when we did the server write/client read change cipher state.
*/
hash = s->handshake_traffic_hash;
} else {
insecret = s->master_secret;
label = client_application_traffic;
labellen = sizeof(client_application_traffic) - 1;
log_label = CLIENT_APPLICATION_LABEL;
/*
* For this we only use the handshake hashes up until the server
* Finished hash. We do not include the client's Finished, which is
* what ssl_handshake_hash() would give us. Instead we use the
* previously saved value.
*/
hash = s->server_finished_hash;
}
} else {
/* Early data never applies to client-read/server-write */
if (which & SSL3_CC_HANDSHAKE) {
insecret = s->handshake_secret;
finsecret = s->server_finished_secret;
finsecretlen = EVP_MD_size(ssl_handshake_md(s));
label = server_handshake_traffic;
labellen = sizeof(server_handshake_traffic) - 1;
log_label = SERVER_HANDSHAKE_LABEL;
} else {
insecret = s->master_secret;
label = server_application_traffic;
labellen = sizeof(server_application_traffic) - 1;
log_label = SERVER_APPLICATION_LABEL;
}
}
if (!(which & SSL3_CC_EARLY)) {
md = ssl_handshake_md(s);
cipher = s->s3->tmp.new_sym_enc;
if (!ssl3_digest_cached_records(s, 1)
|| !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
/* SSLfatal() already called */;
goto err;
}
}
/*
* Save the hash of handshakes up to now for use when we calculate the
* client application traffic secret
*/
if (label == server_application_traffic)
memcpy(s->server_finished_hash, hashval, hashlen);
if (label == server_handshake_traffic)
memcpy(s->handshake_traffic_hash, hashval, hashlen);
if (label == client_application_traffic) {
/*
* We also create the resumption master secret, but this time use the
* hash for the whole handshake including the Client Finished
*/
if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret,
resumption_master_secret,
sizeof(resumption_master_secret) - 1,
hashval, hashlen, s->resumption_master_secret,
hashlen)) {
/* SSLfatal() already called */
goto err;
}
}
if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
insecret, hash, label, labellen, secret, iv,
ciph_ctx)) {
/* SSLfatal() already called */
goto err;
}
if (label == server_application_traffic) {
memcpy(s->server_app_traffic_secret, secret, hashlen);
/* Now we create the exporter master secret */
if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret,
exporter_master_secret,
sizeof(exporter_master_secret) - 1,
hash, hashlen, s->exporter_master_secret,
hashlen)) {
/* SSLfatal() already called */
goto err;
}
if (!ssl_log_secret(s, EXPORTER_SECRET_LABEL, s->exporter_master_secret,
hashlen)) {
/* SSLfatal() already called */
goto err;
}
} else if (label == client_application_traffic)
memcpy(s->client_app_traffic_secret, secret, hashlen);
if (!ssl_log_secret(s, log_label, secret, hashlen)) {
/* SSLfatal() already called */
goto err;
}
if (finsecret != NULL
&& !tls13_derive_finishedkey(s, ssl_handshake_md(s), secret,
finsecret, finsecretlen)) {
/* SSLfatal() already called */
goto err;
}
if (!s->server && label == client_early_traffic)
s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS;
else
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
ret = 1;
err:
OPENSSL_cleanse(secret, sizeof(secret));
return ret;
}
int tls13_update_key(SSL *s, int sending)
{
static const unsigned char application_traffic[] = "traffic upd";
const EVP_MD *md = ssl_handshake_md(s);
size_t hashlen = EVP_MD_size(md);
unsigned char *insecret, *iv;
unsigned char secret[EVP_MAX_MD_SIZE];
EVP_CIPHER_CTX *ciph_ctx;
int ret = 0;
if (s->server == sending)
insecret = s->server_app_traffic_secret;
else
insecret = s->client_app_traffic_secret;
if (sending) {
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
iv = s->write_iv;
ciph_ctx = s->enc_write_ctx;
RECORD_LAYER_reset_write_sequence(&s->rlayer);
} else {
iv = s->read_iv;
ciph_ctx = s->enc_read_ctx;
RECORD_LAYER_reset_read_sequence(&s->rlayer);
}
if (!derive_secret_key_and_iv(s, sending, ssl_handshake_md(s),
s->s3->tmp.new_sym_enc, insecret, NULL,
application_traffic,
sizeof(application_traffic) - 1, secret, iv,
ciph_ctx)) {
/* SSLfatal() already called */
goto err;
}
memcpy(insecret, secret, hashlen);
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
ret = 1;
err:
OPENSSL_cleanse(secret, sizeof(secret));
return ret;
}
int tls13_alert_code(int code)
{
/* There are 2 additional alerts in TLSv1.3 compared to TLSv1.2 */
if (code == SSL_AD_MISSING_EXTENSION || code == SSL_AD_CERTIFICATE_REQUIRED)
return code;
return tls1_alert_code(code);
}
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)
{
unsigned char exportsecret[EVP_MAX_MD_SIZE];
static const unsigned char exporterlabel[] = "exporter";
unsigned char hash[EVP_MAX_MD_SIZE], data[EVP_MAX_MD_SIZE];
const EVP_MD *md = ssl_handshake_md(s);
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned int hashsize, datalen;
int ret = 0;
if (ctx == NULL || !ossl_statem_export_allowed(s))
goto err;
if (!use_context)
contextlen = 0;
if (EVP_DigestInit_ex(ctx, md, NULL) <= 0
|| EVP_DigestUpdate(ctx, context, contextlen) <= 0
|| EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0
|| EVP_DigestInit_ex(ctx, md, NULL) <= 0
|| EVP_DigestFinal_ex(ctx, data, &datalen) <= 0
|| !tls13_hkdf_expand(s, md, s->exporter_master_secret,
(const unsigned char *)label, llen,
data, datalen, exportsecret, hashsize)
|| !tls13_hkdf_expand(s, md, exportsecret, exporterlabel,
sizeof(exporterlabel) - 1, hash, hashsize,
out, olen))
goto err;
ret = 1;
err:
EVP_MD_CTX_free(ctx);
return ret;
}
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)
{
static const unsigned char exporterlabel[] = "exporter";
unsigned char exportsecret[EVP_MAX_MD_SIZE];
unsigned char hash[EVP_MAX_MD_SIZE], data[EVP_MAX_MD_SIZE];
const EVP_MD *md;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned int hashsize, datalen;
int ret = 0;
const SSL_CIPHER *sslcipher;
if (ctx == NULL || !ossl_statem_export_early_allowed(s))
goto err;
if (!s->server && s->max_early_data > 0
&& s->session->ext.max_early_data == 0)
sslcipher = SSL_SESSION_get0_cipher(s->psksession);
else
sslcipher = SSL_SESSION_get0_cipher(s->session);
md = ssl_md(sslcipher->algorithm2);
/*
* Calculate the hash value and store it in |data|. The reason why
* the empty string is used is that the definition of TLS-Exporter
* is like so:
*
* TLS-Exporter(label, context_value, key_length) =
* HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
* "exporter", Hash(context_value), key_length)
*
* Derive-Secret(Secret, Label, Messages) =
* HKDF-Expand-Label(Secret, Label,
* Transcript-Hash(Messages), Hash.length)
*
* Here Transcript-Hash is the cipher suite hash algorithm.
*/
if (EVP_DigestInit_ex(ctx, md, NULL) <= 0
|| EVP_DigestUpdate(ctx, context, contextlen) <= 0
|| EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0
|| EVP_DigestInit_ex(ctx, md, NULL) <= 0
|| EVP_DigestFinal_ex(ctx, data, &datalen) <= 0
|| !tls13_hkdf_expand(s, md, s->early_exporter_master_secret,
(const unsigned char *)label, llen,
data, datalen, exportsecret, hashsize)
|| !tls13_hkdf_expand(s, md, exportsecret, exporterlabel,
sizeof(exporterlabel) - 1, hash, hashsize,
out, olen))
goto err;
ret = 1;
err:
EVP_MD_CTX_free(ctx);
return ret;
}

File Metadata

Mime Type
application/octet-stream
Expires
Tue, Aug 20, 4:50 PM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
eajf_MU7uYTZ
Default Alt Text
(4 MB)

Event Timeline