Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/crypto/openssl/CHANGES.md b/crypto/openssl/CHANGES.md
index e41181b5bbb0..5b0193bc3955 100644
--- a/crypto/openssl/CHANGES.md
+++ b/crypto/openssl/CHANGES.md
@@ -1,20117 +1,20150 @@
OpenSSL CHANGES
===============
This is a high-level summary of the most important changes.
For a full list of changes, see the [git commit log][log] and
pick the appropriate release branch.
[log]: https://github.com/openssl/openssl/commits/
OpenSSL Releases
----------------
- [OpenSSL 3.0](#openssl-30)
- [OpenSSL 1.1.1](#openssl-111)
- [OpenSSL 1.1.0](#openssl-110)
- [OpenSSL 1.0.2](#openssl-102)
- [OpenSSL 1.0.1](#openssl-101)
- [OpenSSL 1.0.0](#openssl-100)
- [OpenSSL 0.9.x](#openssl-09x)
OpenSSL 3.0
-----------
For OpenSSL 3.0 a [Migration guide][] has been added, so the CHANGES entries
listed here are only a brief description.
The migration guide contains more detailed information related to new features,
breaking changes, and mappings for the large list of deprecated functions.
[Migration guide]: https://github.com/openssl/openssl/tree/master/doc/man7/migration_guide.pod
+### Changes between 3.0.15 and 3.0.16 [11 Feb 2025]
+
+ * Fixed timing side-channel in ECDSA signature computation.
+
+ There is a timing signal of around 300 nanoseconds when the top word of
+ the inverted ECDSA nonce value is zero. This can happen with significant
+ probability only for some of the supported elliptic curves. In particular
+ the NIST P-521 curve is affected. To be able to measure this leak, the
+ attacker process must either be located in the same physical computer or
+ must have a very fast network connection with low latency.
+
+ ([CVE-2024-13176])
+
+ *Tomáš Mráz*
+
+ * Fixed possible OOB memory access with invalid low-level GF(2^m) elliptic
+ curve parameters.
+
+ Use of the low-level GF(2^m) elliptic curve APIs with untrusted
+ explicit values for the field polynomial can lead to out-of-bounds memory
+ reads or writes.
+ Applications working with "exotic" explicit binary (GF(2^m)) curve
+ parameters, that make it possible to represent invalid field polynomials
+ with a zero constant term, via the above or similar APIs, may terminate
+ abruptly as a result of reading or writing outside of array bounds. Remote
+ code execution cannot easily be ruled out.
+
+ ([CVE-2024-9143])
+
+ *Viktor Dukhovni*
+
### Changes between 3.0.14 and 3.0.15 [3 Sep 2024]
* Fixed possible denial of service in X.509 name checks.
Applications performing certificate name checks (e.g., TLS clients checking
server certificates) may attempt to read an invalid memory address when
comparing the expected name with an `otherName` subject alternative name of
an X.509 certificate. This may result in an exception that terminates the
application program.
([CVE-2024-6119])
*Viktor Dukhovni*
* Fixed possible buffer overread in SSL_select_next_proto().
Calling the OpenSSL API function SSL_select_next_proto with an empty
supported client protocols buffer may cause a crash or memory contents
to be sent to the peer.
([CVE-2024-5535])
*Matt Caswell*
### Changes between 3.0.13 and 3.0.14 [4 Jun 2024]
* Fixed potential use after free after SSL_free_buffers() is called.
The SSL_free_buffers function is used to free the internal OpenSSL
buffer used when processing an incoming record from the network.
The call is only expected to succeed if the buffer is not currently
in use. However, two scenarios have been identified where the buffer
is freed even when still in use.
The first scenario occurs where a record header has been received
from the network and processed by OpenSSL, but the full record body
has not yet arrived. In this case calling SSL_free_buffers will succeed
even though a record has only been partially processed and the buffer
is still in use.
The second scenario occurs where a full record containing application
data has been received and processed by OpenSSL but the application has
only read part of this data. Again a call to SSL_free_buffers will
succeed even though the buffer is still in use.
([CVE-2024-4741])
*Matt Caswell*
* Fixed an issue where checking excessively long DSA keys or parameters may
be very slow.
Applications that use the functions EVP_PKEY_param_check() or
EVP_PKEY_public_check() to check a DSA public key or DSA parameters may
experience long delays. Where the key or parameters that are being checked
have been obtained from an untrusted source this may lead to a Denial of
Service.
To resolve this issue DSA keys larger than OPENSSL_DSA_MAX_MODULUS_BITS
will now fail the check immediately with a DSA_R_MODULUS_TOO_LARGE error
reason.
([CVE-2024-4603])
*Tomáš Mráz*
* Improved EC/DSA nonce generation routines to avoid bias and timing
side channel leaks.
Thanks to Florian Sieck from Universität zu Lübeck and George Pantelakis
and Hubert Kario from Red Hat for reporting the issues.
*Tomáš Mráz and Paul Dale*
* Fixed an issue where some non-default TLS server configurations can cause
unbounded memory growth when processing TLSv1.3 sessions. An attacker may
exploit certain server configurations to trigger unbounded memory growth that
would lead to a Denial of Service
This problem can occur in TLSv1.3 if the non-default SSL_OP_NO_TICKET option
is being used (but not if early_data is also configured and the default
anti-replay protection is in use). In this case, under certain conditions,
the session cache can get into an incorrect state and it will fail to flush
properly as it fills. The session cache will continue to grow in an unbounded
manner. A malicious client could deliberately create the scenario for this
failure to force a Denial of Service. It may also happen by accident in
normal operation.
([CVE-2024-2511])
*Matt Caswell*
* New atexit configuration switch, which controls whether the OPENSSL_cleanup
is registered when libcrypto is unloaded. This can be used on platforms
where using atexit() from shared libraries causes crashes on exit.
*Randall S. Becker*
### Changes between 3.0.12 and 3.0.13 [30 Jan 2024]
* A file in PKCS12 format can contain certificates and keys and may come from
an untrusted source. The PKCS12 specification allows certain fields to be
NULL, but OpenSSL did not correctly check for this case. A fix has been
applied to prevent a NULL pointer dereference that results in OpenSSL
crashing. If an application processes PKCS12 files from an untrusted source
using the OpenSSL APIs then that application will be vulnerable to this
issue prior to this fix.
OpenSSL APIs that were vulnerable to this are: PKCS12_parse(),
PKCS12_unpack_p7data(), PKCS12_unpack_p7encdata(), PKCS12_unpack_authsafes()
and PKCS12_newpass().
We have also fixed a similar issue in SMIME_write_PKCS7(). However since this
function is related to writing data we do not consider it security
significant.
([CVE-2024-0727])
*Matt Caswell*
* When function EVP_PKEY_public_check() is called on RSA public keys,
a computation is done to confirm that the RSA modulus, n, is composite.
For valid RSA keys, n is a product of two or more large primes and this
computation completes quickly. However, if n is an overly large prime,
then this computation would take a long time.
An application that calls EVP_PKEY_public_check() and supplies an RSA key
obtained from an untrusted source could be vulnerable to a Denial of Service
attack.
The function EVP_PKEY_public_check() is not called from other OpenSSL
functions however it is called from the OpenSSL pkey command line
application. For that reason that application is also vulnerable if used
with the "-pubin" and "-check" options on untrusted data.
To resolve this issue RSA keys larger than OPENSSL_RSA_MAX_MODULUS_BITS will
now fail the check immediately with an RSA_R_MODULUS_TOO_LARGE error reason.
([CVE-2023-6237])
*Tomáš Mráz*
* Restore the encoding of SM2 PrivateKeyInfo and SubjectPublicKeyInfo to
have the contained AlgorithmIdentifier.algorithm set to id-ecPublicKey
rather than SM2.
*Richard Levitte*
* The POLY1305 MAC (message authentication code) implementation in OpenSSL
for PowerPC CPUs saves the contents of vector registers in different
order than they are restored. Thus the contents of some of these vector
registers is corrupted when returning to the caller. The vulnerable code is
used only on newer PowerPC processors supporting the PowerISA 2.07
instructions.
The consequences of this kind of internal application state corruption can
be various - from no consequences, if the calling application does not
depend on the contents of non-volatile XMM registers at all, to the worst
consequences, where the attacker could get complete control of the
application process. However unless the compiler uses the vector registers
for storing pointers, the most likely consequence, if any, would be an
incorrect result of some application dependent calculations or a crash
leading to a denial of service.
([CVE-2023-6129])
*Rohan McLure*
* Fix excessive time spent in DH check / generation with large Q parameter
value.
Applications that use the functions DH_generate_key() to generate an
X9.42 DH key may experience long delays. Likewise, applications that use
DH_check_pub_key(), DH_check_pub_key_ex() or EVP_PKEY_public_check()
to check an X9.42 DH key or X9.42 DH parameters may experience long delays.
Where the key or parameters that are being checked have been obtained from
an untrusted source this may lead to a Denial of Service.
([CVE-2023-5678])
*Richard Levitte*
### Changes between 3.0.11 and 3.0.12 [24 Oct 2023]
* Fix incorrect key and IV resizing issues when calling EVP_EncryptInit_ex2(),
EVP_DecryptInit_ex2() or EVP_CipherInit_ex2() with OSSL_PARAM parameters
that alter the key or IV length ([CVE-2023-5363]).
*Paul Dale*
### Changes between 3.0.10 and 3.0.11 [19 Sep 2023]
* Fix POLY1305 MAC implementation corrupting XMM registers on Windows.
The POLY1305 MAC (message authentication code) implementation in OpenSSL
does not save the contents of non-volatile XMM registers on Windows 64
platform when calculating the MAC of data larger than 64 bytes. Before
returning to the caller all the XMM registers are set to zero rather than
restoring their previous content. The vulnerable code is used only on newer
x86_64 processors supporting the AVX512-IFMA instructions.
The consequences of this kind of internal application state corruption can
be various - from no consequences, if the calling application does not
depend on the contents of non-volatile XMM registers at all, to the worst
consequences, where the attacker could get complete control of the
application process. However given the contents of the registers are just
zeroized so the attacker cannot put arbitrary values inside, the most likely
consequence, if any, would be an incorrect result of some application
dependent calculations or a crash leading to a denial of service.
([CVE-2023-4807])
*Bernd Edlinger*
### Changes between 3.0.9 and 3.0.10 [1 Aug 2023]
* Fix excessive time spent checking DH q parameter value.
The function DH_check() performs various checks on DH parameters. After
fixing CVE-2023-3446 it was discovered that a large q parameter value can
also trigger an overly long computation during some of these checks.
A correct q value, if present, cannot be larger than the modulus p
parameter, thus it is unnecessary to perform these checks if q is larger
than p.
If DH_check() is called with such q parameter value,
DH_CHECK_INVALID_Q_VALUE return flag is set and the computationally
intensive checks are skipped.
([CVE-2023-3817])
*Tomáš Mráz*
* Fix DH_check() excessive time with over sized modulus.
The function DH_check() performs various checks on DH parameters. One of
those checks confirms that the modulus ("p" parameter) is not too large.
Trying to use a very large modulus is slow and OpenSSL will not normally use
a modulus which is over 10,000 bits in length.
However the DH_check() function checks numerous aspects of the key or
parameters that have been supplied. Some of those checks use the supplied
modulus value even if it has already been found to be too large.
A new limit has been added to DH_check of 32,768 bits. Supplying a
key/parameters with a modulus over this size will simply cause DH_check() to
fail.
([CVE-2023-3446])
*Matt Caswell*
* Do not ignore empty associated data entries with AES-SIV.
The AES-SIV algorithm allows for authentication of multiple associated
data entries along with the encryption. To authenticate empty data the
application has to call `EVP_EncryptUpdate()` (or `EVP_CipherUpdate()`)
with NULL pointer as the output buffer and 0 as the input buffer length.
The AES-SIV implementation in OpenSSL just returns success for such call
instead of performing the associated data authentication operation.
The empty data thus will not be authenticated. ([CVE-2023-2975])
Thanks to Juerg Wullschleger (Google) for discovering the issue.
The fix changes the authentication tag value and the ciphertext for
applications that use empty associated data entries with AES-SIV.
To decrypt data encrypted with previous versions of OpenSSL the application
has to skip calls to `EVP_DecryptUpdate()` for empty associated data
entries.
*Tomáš Mráz*
### Changes between 3.0.8 and 3.0.9 [30 May 2023]
* Mitigate for the time it takes for `OBJ_obj2txt` to translate gigantic
OBJECT IDENTIFIER sub-identifiers to canonical numeric text form.
OBJ_obj2txt() would translate any size OBJECT IDENTIFIER to canonical
numeric text form. For gigantic sub-identifiers, this would take a very
long time, the time complexity being O(n^2) where n is the size of that
sub-identifier. ([CVE-2023-2650])
To mitigitate this, `OBJ_obj2txt()` will only translate an OBJECT
IDENTIFIER to canonical numeric text form if the size of that OBJECT
IDENTIFIER is 586 bytes or less, and fail otherwise.
The basis for this restriction is [RFC 2578 (STD 58), section 3.5]. OBJECT
IDENTIFIER values, which stipulates that OBJECT IDENTIFIERS may have at
most 128 sub-identifiers, and that the maximum value that each sub-
identifier may have is 2^32-1 (4294967295 decimal).
For each byte of every sub-identifier, only the 7 lower bits are part of
the value, so the maximum amount of bytes that an OBJECT IDENTIFIER with
these restrictions may occupy is 32 * 128 / 7, which is approximately 586
bytes.
*Richard Levitte*
* Fixed buffer overread in AES-XTS decryption on ARM 64 bit platforms which
happens if the buffer size is 4 mod 5 in 16 byte AES blocks. This can
trigger a crash of an application using AES-XTS decryption if the memory
just after the buffer being decrypted is not mapped.
Thanks to Anton Romanov (Amazon) for discovering the issue.
([CVE-2023-1255])
*Nevine Ebeid*
* Reworked the Fix for the Timing Oracle in RSA Decryption ([CVE-2022-4304]).
The previous fix for this timing side channel turned out to cause
a severe 2-3x performance regression in the typical use case
compared to 3.0.7. The new fix uses existing constant time
code paths, and restores the previous performance level while
fully eliminating all existing timing side channels.
The fix was developed by Bernd Edlinger with testing support
by Hubert Kario.
*Bernd Edlinger*
* Corrected documentation of X509_VERIFY_PARAM_add0_policy() to mention
that it does not enable policy checking. Thanks to David Benjamin for
discovering this issue.
([CVE-2023-0466])
*Tomáš Mráz*
* Fixed an issue where invalid certificate policies in leaf certificates are
silently ignored by OpenSSL and other certificate policy checks are skipped
for that certificate. A malicious CA could use this to deliberately assert
invalid certificate policies in order to circumvent policy checking on the
certificate altogether.
([CVE-2023-0465])
*Matt Caswell*
* Limited the number of nodes created in a policy tree to mitigate
against CVE-2023-0464. The default limit is set to 1000 nodes, which
should be sufficient for most installations. If required, the limit
can be adjusted by setting the OPENSSL_POLICY_TREE_NODES_MAX build
time define to a desired maximum number of nodes or zero to allow
unlimited growth.
([CVE-2023-0464])
*Paul Dale*
### Changes between 3.0.7 and 3.0.8 [7 Feb 2023]
* Fixed NULL dereference during PKCS7 data verification.
A NULL pointer can be dereferenced when signatures are being
verified on PKCS7 signed or signedAndEnveloped data. In case the hash
algorithm used for the signature is known to the OpenSSL library but
the implementation of the hash algorithm is not available the digest
initialization will fail. There is a missing check for the return
value from the initialization function which later leads to invalid
usage of the digest API most likely leading to a crash.
([CVE-2023-0401])
PKCS7 data is processed by the SMIME library calls and also by the
time stamp (TS) library calls. The TLS implementation in OpenSSL does
not call these functions however third party applications would be
affected if they call these functions to verify signatures on untrusted
data.
*Tomáš Mráz*
* Fixed X.400 address type confusion in X.509 GeneralName.
There is a type confusion vulnerability relating to X.400 address processing
inside an X.509 GeneralName. X.400 addresses were parsed as an ASN1_STRING
but the public structure definition for GENERAL_NAME incorrectly specified
the type of the x400Address field as ASN1_TYPE. This field is subsequently
interpreted by the OpenSSL function GENERAL_NAME_cmp as an ASN1_TYPE rather
than an ASN1_STRING.
When CRL checking is enabled (i.e. the application sets the
X509_V_FLAG_CRL_CHECK flag), this vulnerability may allow an attacker to
pass arbitrary pointers to a memcmp call, enabling them to read memory
contents or enact a denial of service.
([CVE-2023-0286])
*Hugo Landau*
* Fixed NULL dereference validating DSA public key.
An invalid pointer dereference on read can be triggered when an
application tries to check a malformed DSA public key by the
EVP_PKEY_public_check() function. This will most likely lead
to an application crash. This function can be called on public
keys supplied from untrusted sources which could allow an attacker
to cause a denial of service attack.
The TLS implementation in OpenSSL does not call this function
but applications might call the function if there are additional
security requirements imposed by standards such as FIPS 140-3.
([CVE-2023-0217])
*Shane Lontis, Tomáš Mráz*
* Fixed Invalid pointer dereference in d2i_PKCS7 functions.
An invalid pointer dereference on read can be triggered when an
application tries to load malformed PKCS7 data with the
d2i_PKCS7(), d2i_PKCS7_bio() or d2i_PKCS7_fp() functions.
The result of the dereference is an application crash which could
lead to a denial of service attack. The TLS implementation in OpenSSL
does not call this function however third party applications might
call these functions on untrusted data.
([CVE-2023-0216])
*Tomáš Mráz*
* Fixed Use-after-free following BIO_new_NDEF.
The public API function BIO_new_NDEF is a helper function used for
streaming ASN.1 data via a BIO. It is primarily used internally to OpenSSL
to support the SMIME, CMS and PKCS7 streaming capabilities, but may also
be called directly by end user applications.
The function receives a BIO from the caller, prepends a new BIO_f_asn1
filter BIO onto the front of it to form a BIO chain, and then returns
the new head of the BIO chain to the caller. Under certain conditions,
for example if a CMS recipient public key is invalid, the new filter BIO
is freed and the function returns a NULL result indicating a failure.
However, in this case, the BIO chain is not properly cleaned up and the
BIO passed by the caller still retains internal pointers to the previously
freed filter BIO. If the caller then goes on to call BIO_pop() on the BIO
then a use-after-free will occur. This will most likely result in a crash.
([CVE-2023-0215])
*Viktor Dukhovni, Matt Caswell*
* Fixed Double free after calling PEM_read_bio_ex.
The function PEM_read_bio_ex() reads a PEM file from a BIO and parses and
decodes the "name" (e.g. "CERTIFICATE"), any header data and the payload
data. If the function succeeds then the "name_out", "header" and "data"
arguments are populated with pointers to buffers containing the relevant
decoded data. The caller is responsible for freeing those buffers. It is
possible to construct a PEM file that results in 0 bytes of payload data.
In this case PEM_read_bio_ex() will return a failure code but will populate
the header argument with a pointer to a buffer that has already been freed.
If the caller also frees this buffer then a double free will occur. This
will most likely lead to a crash.
The functions PEM_read_bio() and PEM_read() are simple wrappers around
PEM_read_bio_ex() and therefore these functions are also directly affected.
These functions are also called indirectly by a number of other OpenSSL
functions including PEM_X509_INFO_read_bio_ex() and
SSL_CTX_use_serverinfo_file() which are also vulnerable. Some OpenSSL
internal uses of these functions are not vulnerable because the caller does
not free the header argument if PEM_read_bio_ex() returns a failure code.
([CVE-2022-4450])
*Kurt Roeckx, Matt Caswell*
* Fixed Timing Oracle in RSA Decryption.
A timing based side channel exists in the OpenSSL RSA Decryption
implementation which could be sufficient to recover a plaintext across
a network in a Bleichenbacher style attack. To achieve a successful
decryption an attacker would have to be able to send a very large number
of trial messages for decryption. The vulnerability affects all RSA padding
modes: PKCS#1 v1.5, RSA-OEAP and RSASVE.
([CVE-2022-4304])
*Dmitry Belyavsky, Hubert Kario*
* Fixed X.509 Name Constraints Read Buffer Overflow.
A read buffer overrun can be triggered in X.509 certificate verification,
specifically in name constraint checking. The read buffer overrun might
result in a crash which could lead to a denial of service attack.
In a TLS client, this can be triggered by connecting to a malicious
server. In a TLS server, this can be triggered if the server requests
client authentication and a malicious client connects.
([CVE-2022-4203])
*Viktor Dukhovni*
* Fixed X.509 Policy Constraints Double Locking security issue.
If an X.509 certificate contains a malformed policy constraint and
policy processing is enabled, then a write lock will be taken twice
recursively. On some operating systems (most widely: Windows) this
results in a denial of service when the affected process hangs. Policy
processing being enabled on a publicly facing server is not considered
to be a common setup.
([CVE-2022-3996])
*Paul Dale*
* Our provider implementations of `OSSL_FUNC_KEYMGMT_EXPORT` and
`OSSL_FUNC_KEYMGMT_GET_PARAMS` for EC and SM2 keys now honor
`OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT` as set (and
default to `POINT_CONVERSION_UNCOMPRESSED`) when exporting
`OSSL_PKEY_PARAM_PUB_KEY`, instead of unconditionally using
`POINT_CONVERSION_COMPRESSED` as in previous 3.x releases.
For symmetry, our implementation of `EVP_PKEY_ASN1_METHOD->export_to`
for legacy EC and SM2 keys is also changed similarly to honor the
equivalent conversion format flag as specified in the underlying
`EC_KEY` object being exported to a provider, when this function is
called through `EVP_PKEY_export()`.
*Nicola Tuveri*
### Changes between 3.0.6 and 3.0.7 [1 Nov 2022]
* Fixed two buffer overflows in punycode decoding functions.
A buffer overrun can be triggered in X.509 certificate verification,
specifically in name constraint checking. Note that this occurs after
certificate chain signature verification and requires either a CA to
have signed the malicious certificate or for the application to continue
certificate verification despite failure to construct a path to a trusted
issuer.
In a TLS client, this can be triggered by connecting to a malicious
server. In a TLS server, this can be triggered if the server requests
client authentication and a malicious client connects.
An attacker can craft a malicious email address to overflow
an arbitrary number of bytes containing the `.` character (decimal 46)
on the stack. This buffer overflow could result in a crash (causing a
denial of service).
([CVE-2022-3786])
An attacker can craft a malicious email address to overflow four
attacker-controlled bytes on the stack. This buffer overflow could
result in a crash (causing a denial of service) or potentially remote code
execution depending on stack layout for any given platform/compiler.
([CVE-2022-3602])
*Paul Dale*
* Removed all references to invalid OSSL_PKEY_PARAM_RSA names for CRT
parameters in OpenSSL code.
Applications should not use the names OSSL_PKEY_PARAM_RSA_FACTOR,
OSSL_PKEY_PARAM_RSA_EXPONENT and OSSL_PKEY_PARAM_RSA_COEFFICIENT.
Use the numbered names such as OSSL_PKEY_PARAM_RSA_FACTOR1 instead.
Using these invalid names may cause algorithms to use slower methods
that ignore the CRT parameters.
*Shane Lontis*
* Fixed a regression introduced in 3.0.6 version raising errors on some stack
operations.
*Tomáš Mráz*
* Fixed a regression introduced in 3.0.6 version not refreshing the certificate
data to be signed before signing the certificate.
*Gibeom Gwon*
* Added RIPEMD160 to the default provider.
*Paul Dale*
* Ensured that the key share group sent or accepted for the key exchange
is allowed for the protocol version.
*Matt Caswell*
### Changes between 3.0.5 and 3.0.6 [11 Oct 2022]
* OpenSSL supports creating a custom cipher via the legacy
EVP_CIPHER_meth_new() function and associated function calls. This function
was deprecated in OpenSSL 3.0 and application authors are instead encouraged
to use the new provider mechanism in order to implement custom ciphers.
OpenSSL versions 3.0.0 to 3.0.5 incorrectly handle legacy custom ciphers
passed to the EVP_EncryptInit_ex2(), EVP_DecryptInit_ex2() and
EVP_CipherInit_ex2() functions (as well as other similarly named encryption
and decryption initialisation functions). Instead of using the custom cipher
directly it incorrectly tries to fetch an equivalent cipher from the
available providers. An equivalent cipher is found based on the NID passed to
EVP_CIPHER_meth_new(). This NID is supposed to represent the unique NID for a
given cipher. However it is possible for an application to incorrectly pass
NID_undef as this value in the call to EVP_CIPHER_meth_new(). When NID_undef
is used in this way the OpenSSL encryption/decryption initialisation function
will match the NULL cipher as being equivalent and will fetch this from the
available providers. This will succeed if the default provider has been
loaded (or if a third party provider has been loaded that offers this
cipher). Using the NULL cipher means that the plaintext is emitted as the
ciphertext.
Applications are only affected by this issue if they call
EVP_CIPHER_meth_new() using NID_undef and subsequently use it in a call to an
encryption/decryption initialisation function. Applications that only use
SSL/TLS are not impacted by this issue.
([CVE-2022-3358])
*Matt Caswell*
* Fix LLVM vs Apple LLVM version numbering confusion that caused build failures
on MacOS 10.11
*Richard Levitte*
* Fixed the linux-mips64 Configure target which was missing the
SIXTY_FOUR_BIT bn_ops flag. This was causing heap corruption on that
platform.
*Adam Joseph*
* Fix handling of a ticket key callback that returns 0 in TLSv1.3 to not send a
ticket
*Matt Caswell*
* Correctly handle a retransmitted ClientHello in DTLS
*Matt Caswell*
* Fixed detection of ktls support in cross-compile environment on Linux
*Tomas Mraz*
* Fixed some regressions and test failures when running the 3.0.0 FIPS provider
against 3.0.x
*Paul Dale*
* Fixed SSL_pending() and SSL_has_pending() with DTLS which were failing to
report correct results in some cases
*Matt Caswell*
* Fix UWP builds by defining VirtualLock
*Charles Milette*
* For known safe primes use the minimum key length according to RFC 7919.
Longer private key sizes unnecessarily raise the cycles needed to compute the
shared secret without any increase of the real security. This fixes a
regression from 1.1.1 where these shorter keys were generated for the known
safe primes.
*Tomas Mraz*
* Added the loongarch64 target
*Shi Pujin*
* Fixed EC ASM flag passing. Flags for ASM implementations of EC curves were
only passed to the FIPS provider and not to the default or legacy provider.
*Juergen Christ*
* Fixed reported performance degradation on aarch64. Restored the
implementation prior to commit 2621751 ("aes/asm/aesv8-armx.pl: avoid
32-bit lane assignment in CTR mode") for 64bit targets only, since it is
reportedly 2-17% slower and the silicon errata only affects 32bit targets.
The new algorithm is still used for 32 bit targets.
*Bernd Edlinger*
* Added a missing header for memcmp that caused compilation failure on some
platforms
*Gregor Jasny*
### Changes between 3.0.4 and 3.0.5 [5 Jul 2022]
* The OpenSSL 3.0.4 release introduced a serious bug in the RSA
implementation for X86_64 CPUs supporting the AVX512IFMA instructions.
This issue makes the RSA implementation with 2048 bit private keys
incorrect on such machines and memory corruption will happen during
the computation. As a consequence of the memory corruption an attacker
may be able to trigger a remote code execution on the machine performing
the computation.
SSL/TLS servers or other servers using 2048 bit RSA private keys running
on machines supporting AVX512IFMA instructions of the X86_64 architecture
are affected by this issue.
([CVE-2022-2274])
*Xi Ruoyao*
* AES OCB mode for 32-bit x86 platforms using the AES-NI assembly optimised
implementation would not encrypt the entirety of the data under some
circumstances. This could reveal sixteen bytes of data that was
preexisting in the memory that wasn't written. In the special case of
"in place" encryption, sixteen bytes of the plaintext would be revealed.
Since OpenSSL does not support OCB based cipher suites for TLS and DTLS,
they are both unaffected.
([CVE-2022-2097])
*Alex Chernyakhovsky, David Benjamin, Alejandro Sedeño*
### Changes between 3.0.3 and 3.0.4 [21 Jun 2022]
* In addition to the c_rehash shell command injection identified in
CVE-2022-1292, further bugs where the c_rehash script does not
properly sanitise shell metacharacters to prevent command injection have been
fixed.
When the CVE-2022-1292 was fixed it was not discovered that there
are other places in the script where the file names of certificates
being hashed were possibly passed to a command executed through the shell.
This script is distributed by some operating systems in a manner where
it is automatically executed. On such operating systems, an attacker
could execute arbitrary commands with the privileges of the script.
Use of the c_rehash script is considered obsolete and should be replaced
by the OpenSSL rehash command line tool.
(CVE-2022-2068)
*Daniel Fiala, Tomáš Mráz*
* Case insensitive string comparison no longer uses locales. It has instead
been directly implemented.
*Paul Dale*
### Changes between 3.0.2 and 3.0.3 [3 May 2022]
* Case insensitive string comparison is reimplemented via new locale-agnostic
comparison functions OPENSSL_str[n]casecmp always using the POSIX locale for
comparison. The previous implementation had problems when the Turkish locale
was used.
*Dmitry Belyavskiy*
* Fixed a bug in the c_rehash script which was not properly sanitising shell
metacharacters to prevent command injection. This script is distributed by
some operating systems in a manner where it is automatically executed. On
such operating systems, an attacker could execute arbitrary commands with the
privileges of the script.
Use of the c_rehash script is considered obsolete and should be replaced
by the OpenSSL rehash command line tool.
(CVE-2022-1292)
*Tomáš Mráz*
* Fixed a bug in the function `OCSP_basic_verify` that verifies the signer
certificate on an OCSP response. The bug caused the function in the case
where the (non-default) flag OCSP_NOCHECKS is used to return a postivie
response (meaning a successful verification) even in the case where the
response signing certificate fails to verify.
It is anticipated that most users of `OCSP_basic_verify` will not use the
OCSP_NOCHECKS flag. In this case the `OCSP_basic_verify` function will return
a negative value (indicating a fatal error) in the case of a certificate
verification failure. The normal expected return value in this case would be
0.
This issue also impacts the command line OpenSSL "ocsp" application. When
verifying an ocsp response with the "-no_cert_checks" option the command line
application will report that the verification is successful even though it
has in fact failed. In this case the incorrect successful response will also
be accompanied by error messages showing the failure and contradicting the
apparently successful result.
([CVE-2022-1343])
*Matt Caswell*
* Fixed a bug where the RC4-MD5 ciphersuite incorrectly used the
AAD data as the MAC key. This made the MAC key trivially predictable.
An attacker could exploit this issue by performing a man-in-the-middle attack
to modify data being sent from one endpoint to an OpenSSL 3.0 recipient such
that the modified data would still pass the MAC integrity check.
Note that data sent from an OpenSSL 3.0 endpoint to a non-OpenSSL 3.0
endpoint will always be rejected by the recipient and the connection will
fail at that point. Many application protocols require data to be sent from
the client to the server first. Therefore, in such a case, only an OpenSSL
3.0 server would be impacted when talking to a non-OpenSSL 3.0 client.
If both endpoints are OpenSSL 3.0 then the attacker could modify data being
sent in both directions. In this case both clients and servers could be
affected, regardless of the application protocol.
Note that in the absence of an attacker this bug means that an OpenSSL 3.0
endpoint communicating with a non-OpenSSL 3.0 endpoint will fail to complete
the handshake when using this ciphersuite.
The confidentiality of data is not impacted by this issue, i.e. an attacker
cannot decrypt data that has been encrypted using this ciphersuite - they can
only modify it.
In order for this attack to work both endpoints must legitimately negotiate
the RC4-MD5 ciphersuite. This ciphersuite is not compiled by default in
OpenSSL 3.0, and is not available within the default provider or the default
ciphersuite list. This ciphersuite will never be used if TLSv1.3 has been
negotiated. In order for an OpenSSL 3.0 endpoint to use this ciphersuite the
following must have occurred:
1) OpenSSL must have been compiled with the (non-default) compile time option
enable-weak-ssl-ciphers
2) OpenSSL must have had the legacy provider explicitly loaded (either
through application code or via configuration)
3) The ciphersuite must have been explicitly added to the ciphersuite list
4) The libssl security level must have been set to 0 (default is 1)
5) A version of SSL/TLS below TLSv1.3 must have been negotiated
6) Both endpoints must negotiate the RC4-MD5 ciphersuite in preference to any
others that both endpoints have in common
(CVE-2022-1434)
*Matt Caswell*
* Fix a bug in the OPENSSL_LH_flush() function that breaks reuse of the memory
occuppied by the removed hash table entries.
This function is used when decoding certificates or keys. If a long lived
process periodically decodes certificates or keys its memory usage will
expand without bounds and the process might be terminated by the operating
system causing a denial of service. Also traversing the empty hash table
entries will take increasingly more time.
Typically such long lived processes might be TLS clients or TLS servers
configured to accept client certificate authentication.
(CVE-2022-1473)
*Hugo Landau, Aliaksei Levin*
* The functions `OPENSSL_LH_stats` and `OPENSSL_LH_stats_bio` now only report
the `num_items`, `num_nodes` and `num_alloc_nodes` statistics. All other
statistics are no longer supported. For compatibility, these statistics are
still listed in the output but are now always reported as zero.
*Hugo Landau*
### Changes between 3.0.1 and 3.0.2 [15 Mar 2022]
* Fixed a bug in the BN_mod_sqrt() function that can cause it to loop forever
for non-prime moduli.
Internally this function is used when parsing certificates that contain
elliptic curve public keys in compressed form or explicit elliptic curve
parameters with a base point encoded in compressed form.
It is possible to trigger the infinite loop by crafting a certificate that
has invalid explicit curve parameters.
Since certificate parsing happens prior to verification of the certificate
signature, any process that parses an externally supplied certificate may thus
be subject to a denial of service attack. The infinite loop can also be
reached when parsing crafted private keys as they can contain explicit
elliptic curve parameters.
Thus vulnerable situations include:
- TLS clients consuming server certificates
- TLS servers consuming client certificates
- Hosting providers taking certificates or private keys from customers
- Certificate authorities parsing certification requests from subscribers
- Anything else which parses ASN.1 elliptic curve parameters
Also any other applications that use the BN_mod_sqrt() where the attacker
can control the parameter values are vulnerable to this DoS issue.
([CVE-2022-0778])
*Tomáš Mráz*
* Add ciphersuites based on DHE_PSK (RFC 4279) and ECDHE_PSK (RFC 5489)
to the list of ciphersuites providing Perfect Forward Secrecy as
required by SECLEVEL >= 3.
*Dmitry Belyavskiy, Nicola Tuveri*
* Made the AES constant time code for no-asm configurations
optional due to the resulting 95% performance degradation.
The AES constant time code can be enabled, for no assembly
builds, with: ./config no-asm -DOPENSSL_AES_CONST_TIME
*Paul Dale*
* Fixed PEM_write_bio_PKCS8PrivateKey() to make it possible to use empty
passphrase strings.
*Darshan Sen*
* The negative return value handling of the certificate verification callback
was reverted. The replacement is to set the verification retry state with
the SSL_set_retry_verify() function.
*Tomáš Mráz*
### Changes between 3.0.0 and 3.0.1 [14 Dec 2021]
* Fixed invalid handling of X509_verify_cert() internal errors in libssl
Internally libssl in OpenSSL calls X509_verify_cert() on the client side to
verify a certificate supplied by a server. That function may return a
negative return value to indicate an internal error (for example out of
memory). Such a negative return value is mishandled by OpenSSL and will cause
an IO function (such as SSL_connect() or SSL_do_handshake()) to not indicate
success and a subsequent call to SSL_get_error() to return the value
SSL_ERROR_WANT_RETRY_VERIFY. This return value is only supposed to be
returned by OpenSSL if the application has previously called
SSL_CTX_set_cert_verify_callback(). Since most applications do not do this
the SSL_ERROR_WANT_RETRY_VERIFY return value from SSL_get_error() will be
totally unexpected and applications may not behave correctly as a result. The
exact behaviour will depend on the application but it could result in
crashes, infinite loops or other similar incorrect responses.
This issue is made more serious in combination with a separate bug in OpenSSL
3.0 that will cause X509_verify_cert() to indicate an internal error when
processing a certificate chain. This will occur where a certificate does not
include the Subject Alternative Name extension but where a Certificate
Authority has enforced name constraints. This issue can occur even with valid
chains.
([CVE-2021-4044])
*Matt Caswell*
* Corrected a few file name and file reference bugs in the build,
installation and setup scripts, which lead to installation verification
failures. Slightly enhanced the installation verification script.
*Richard Levitte*
* Fixed EVP_PKEY_eq() to make it possible to use it with strictly private
keys.
*Richard Levitte*
* Fixed PVK encoder to properly query for the passphrase.
*Tomáš Mráz*
* Multiple fixes in the OSSL_HTTP API functions.
*David von Oheimb*
* Allow sign extension in OSSL_PARAM_allocate_from_text() for the
OSSL_PARAM_INTEGER data type and return error on negative numbers
used with the OSSL_PARAM_UNSIGNED_INTEGER data type. Make
OSSL_PARAM_BLD_push_BN{,_pad}() return an error on negative numbers.
*Richard Levitte*
* Allow copying uninitialized digest contexts with EVP_MD_CTX_copy_ex.
*Tomáš Mráz*
* Fixed detection of ARMv7 and ARM64 CPU features on FreeBSD.
*Allan Jude*
* Multiple threading fixes.
*Matt Caswell*
* Added NULL digest implementation to keep compatibility with 1.1.1 version.
*Tomáš Mráz*
* Allow fetching an operation from the provider that owns an unexportable key
as a fallback if that is still allowed by the property query.
*Richard Levitte*
### Changes between 1.1.1 and 3.0.0 [7 sep 2021]
* TLS_MAX_VERSION, DTLS_MAX_VERSION and DTLS_MIN_VERSION constants are now
deprecated.
*Matt Caswell*
* The `OPENSSL_s390xcap` environment variable can be used to set bits in the
S390X capability vector to zero. This simplifies testing of different code
paths on S390X architecture.
*Patrick Steuer*
* Encrypting more than 2^64 TLS records with AES-GCM is disallowed
as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness Requirements from
SP 800-38D". The communication will fail at this point.
*Paul Dale*
* The EC_GROUP_clear_free() function is deprecated as there is nothing
confidential in EC_GROUP data.
*Nicola Tuveri*
* The byte order mark (BOM) character is ignored if encountered at the
beginning of a PEM-formatted file.
*Dmitry Belyavskiy*
* Added CMS support for the Russian GOST algorithms.
*Dmitry Belyavskiy*
* Due to move of the implementation of cryptographic operations
to the providers, validation of various operation parameters can
be postponed until the actual operation is executed where previously
it happened immediately when an operation parameter was set.
For example when setting an unsupported curve with
EVP_PKEY_CTX_set_ec_paramgen_curve_nid() this function call will not
fail but later keygen operations with the EVP_PKEY_CTX will fail.
*OpenSSL team members and many third party contributors*
* The EVP_get_cipherbyname() function will return NULL for algorithms such as
"AES-128-SIV", "AES-128-CBC-CTS" and "CAMELLIA-128-CBC-CTS" which were
previously only accessible via low level interfaces. Use EVP_CIPHER_fetch()
instead to retrieve these algorithms from a provider.
*Shane Lontis*
* On build targets where the multilib postfix is set in the build
configuration the libdir directory was changing based on whether
the lib directory with the multilib postfix exists on the system
or not. This unpredictable behavior was removed and eventual
multilib postfix is now always added to the default libdir. Use
`--libdir=lib` to override the libdir if adding the postfix is
undesirable.
*Jan Lána*
* The triple DES key wrap functionality now conforms to RFC 3217 but is
no longer interoperable with OpenSSL 1.1.1.
*Paul Dale*
* The ERR_GET_FUNC() function was removed. With the loss of meaningful
function codes, this function can only cause problems for calling
applications.
*Paul Dale*
* Add a configurable flag to output date formats as ISO 8601. Does not
change the default date format.
*William Edmisten*
* Version of MSVC earlier than 1300 could get link warnings, which could
be suppressed if the undocumented -DI_CAN_LIVE_WITH_LNK4049 was set.
Support for this flag has been removed.
*Rich Salz*
* Rework and make DEBUG macros consistent. Remove unused -DCONF_DEBUG,
-DBN_CTX_DEBUG, and REF_PRINT. Add a new tracing category and use it for
printing reference counts. Rename -DDEBUG_UNUSED to -DUNUSED_RESULT_DEBUG
Fix BN_DEBUG_RAND so it compiles and, when set, force DEBUG_RAND to be set
also. Rename engine_debug_ref to be ENGINE_REF_PRINT also for consistency.
*Rich Salz*
* The signatures of the functions to get and set options on SSL and
SSL_CTX objects changed from "unsigned long" to "uint64_t" type.
Some source code changes may be required.
*Rich Salz*
* The public definitions of conf_method_st and conf_st have been
deprecated. They will be made opaque in a future release.
*Rich Salz and Tomáš Mráz*
* Client-initiated renegotiation is disabled by default. To allow it, use
the -client_renegotiation option, the SSL_OP_ALLOW_CLIENT_RENEGOTIATION
flag, or the "ClientRenegotiation" config parameter as appropriate.
*Rich Salz*
* Add "abspath" and "includedir" pragma's to config files, to prevent,
or modify relative pathname inclusion.
*Rich Salz*
* OpenSSL includes a cryptographic module that is intended to be FIPS 140-2
validated. Please consult the README-FIPS and
README-PROVIDERS files, as well as the migration guide.
*OpenSSL team members and many third party contributors*
* For the key types DH and DHX the allowed settable parameters are now different.
*Shane Lontis*
* The openssl commands that read keys, certificates, and CRLs now
automatically detect the PEM or DER format of the input files.
*David von Oheimb, Richard Levitte, and Tomáš Mráz*
* Added enhanced PKCS#12 APIs which accept a library context.
*Jon Spillett*
* The default manual page suffix ($MANSUFFIX) has been changed to "ossl"
*Matt Caswell*
* Added support for Kernel TLS (KTLS).
*Boris Pismenny, John Baldwin and Andrew Gallatin*
* Support for RFC 5746 secure renegotiation is now required by default for
SSL or TLS connections to succeed.
*Benjamin Kaduk*
* The signature of the `copy` functional parameter of the
EVP_PKEY_meth_set_copy() function has changed so its `src` argument is
now `const EVP_PKEY_CTX *` instead of `EVP_PKEY_CTX *`. Similarly
the signature of the `pub_decode` functional parameter of the
EVP_PKEY_asn1_set_public() function has changed so its `pub` argument is
now `const X509_PUBKEY *` instead of `X509_PUBKEY *`.
*David von Oheimb*
* The error return values from some control calls (ctrl) have changed.
*Paul Dale*
* A public key check is now performed during EVP_PKEY_derive_set_peer().
*Shane Lontis*
* Many functions in the EVP_ namespace that are getters of values from
implementations or contexts were renamed to include get or get0 in their
names. Old names are provided as macro aliases for compatibility and
are not deprecated.
*Tomáš Mráz*
* The EVP_PKEY_CTRL_PKCS7_ENCRYPT, EVP_PKEY_CTRL_PKCS7_DECRYPT,
EVP_PKEY_CTRL_PKCS7_SIGN, EVP_PKEY_CTRL_CMS_ENCRYPT,
EVP_PKEY_CTRL_CMS_DECRYPT, and EVP_PKEY_CTRL_CMS_SIGN control operations
are deprecated.
*Tomáš Mráz*
* The EVP_PKEY_public_check() and EVP_PKEY_param_check() functions now work for
more key types.
* The output from the command line applications may have minor
changes.
*Paul Dale*
* The output from numerous "printing" may have minor changes.
*David von Oheimb*
* Windows thread synchronization uses read/write primitives (SRWLock) when
supported by the OS, otherwise CriticalSection continues to be used.
*Vincent Drake*
* Add filter BIO BIO_f_readbuffer() that allows BIO_tell() and BIO_seek() to
work on read only BIO source/sinks that do not support these functions.
This allows piping or redirection of a file BIO using stdin to be buffered
into memory. This is used internally in OSSL_DECODER_from_bio().
*Shane Lontis*
* OSSL_STORE_INFO_get_type() may now return an additional value. In 1.1.1
this function would return one of the values OSSL_STORE_INFO_NAME,
OSSL_STORE_INFO_PKEY, OSSL_STORE_INFO_PARAMS, OSSL_STORE_INFO_CERT or
OSSL_STORE_INFO_CRL. Decoded public keys would previously have been reported
as type OSSL_STORE_INFO_PKEY in 1.1.1. In 3.0 decoded public keys are now
reported as having the new type OSSL_STORE_INFO_PUBKEY. Applications
using this function should be amended to handle the changed return value.
*Richard Levitte*
* Improved adherence to Enhanced Security Services (ESS, RFC 2634 and RFC 5035)
for the TSP and CMS Advanced Electronic Signatures (CAdES) implementations.
As required by RFC 5035 check both ESSCertID and ESSCertIDv2 if both present.
Correct the semantics of checking the validation chain in case ESSCertID{,v2}
contains more than one certificate identifier: This means that all
certificates referenced there MUST be part of the validation chain.
*David von Oheimb*
* The implementation of older EVP ciphers related to CAST, IDEA, SEED, RC2, RC4,
RC5, DESX and DES have been moved to the legacy provider.
*Matt Caswell*
* The implementation of the EVP digests MD2, MD4, MDC2, WHIRLPOOL and
RIPEMD-160 have been moved to the legacy provider.
*Matt Caswell*
* The deprecated function EVP_PKEY_get0() now returns NULL being called for a
provided key.
*Dmitry Belyavskiy*
* The deprecated functions EVP_PKEY_get0_RSA(),
EVP_PKEY_get0_DSA(), EVP_PKEY_get0_EC_KEY(), EVP_PKEY_get0_DH(),
EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305() and EVP_PKEY_get0_siphash() as
well as the similarly named "get1" functions behave differently in
OpenSSL 3.0.
*Matt Caswell*
* A number of functions handling low-level keys or engines were deprecated
including EVP_PKEY_set1_engine(), EVP_PKEY_get0_engine(), EVP_PKEY_assign(),
EVP_PKEY_get0(), EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305() and
EVP_PKEY_get0_siphash().
*Matt Caswell*
* PKCS#5 PBKDF1 key derivation has been moved from PKCS5_PBE_keyivgen() into
the legacy crypto provider as an EVP_KDF. Applications requiring this KDF
will need to load the legacy crypto provider. This includes these PBE
algorithms which use this KDF:
- NID_pbeWithMD2AndDES_CBC
- NID_pbeWithMD5AndDES_CBC
- NID_pbeWithSHA1AndRC2_CBC
- NID_pbeWithMD2AndRC2_CBC
- NID_pbeWithMD5AndRC2_CBC
- NID_pbeWithSHA1AndDES_CBC
*Jon Spillett*
* Deprecated obsolete BIO_set_callback(), BIO_get_callback(), and
BIO_debug_callback() functions.
*Tomáš Mráz*
* Deprecated obsolete EVP_PKEY_CTX_get0_dh_kdf_ukm() and
EVP_PKEY_CTX_get0_ecdh_kdf_ukm() functions.
*Tomáš Mráz*
* The RAND_METHOD APIs have been deprecated.
*Paul Dale*
* The SRP APIs have been deprecated.
*Matt Caswell*
* Add a compile time option to prevent the caching of provider fetched
algorithms. This is enabled by including the no-cached-fetch option
at configuration time.
*Paul Dale*
* pkcs12 now uses defaults of PBKDF2, AES and SHA-256, with a MAC iteration
count of PKCS12_DEFAULT_ITER.
*Tomáš Mráz and Sahana Prasad*
* The openssl speed command does not use low-level API calls anymore.
*Tomáš Mráz*
* Parallel dual-prime 1024-bit modular exponentiation for AVX512_IFMA
capable processors.
*Ilya Albrekht, Sergey Kirillov, Andrey Matyukov (Intel Corp)*
* Combining the Configure options no-ec and no-dh no longer disables TLSv1.3.
*Matt Caswell*
* Implemented support for fully "pluggable" TLSv1.3 groups. This means that
providers may supply their own group implementations (using either the "key
exchange" or the "key encapsulation" methods) which will automatically be
detected and used by libssl.
*Matt Caswell, Nicola Tuveri*
* The undocumented function X509_certificate_type() has been deprecated;
*Rich Salz*
* Deprecated the obsolete BN_pseudo_rand() and BN_pseudo_rand_range().
*Tomáš Mráz*
* Removed RSA padding mode for SSLv23 (which was only used for
SSLv2). This includes the functions RSA_padding_check_SSLv23() and
RSA_padding_add_SSLv23() and the `-ssl` option in the deprecated
`rsautl` command.
*Rich Salz*
* Deprecated the obsolete X9.31 RSA key generation related functions.
* While a callback function set via `SSL_CTX_set_cert_verify_callback()`
is not allowed to return a value > 1, this is no more taken as failure.
*Viktor Dukhovni and David von Oheimb*
* Deprecated the obsolete X9.31 RSA key generation related functions
BN_X931_generate_Xpq(), BN_X931_derive_prime_ex(), and
BN_X931_generate_prime_ex().
*Tomáš Mráz*
* The default key generation method for the regular 2-prime RSA keys was
changed to the FIPS 186-4 B.3.6 method.
*Shane Lontis*
* Deprecated the BN_is_prime_ex() and BN_is_prime_fasttest_ex() functions.
*Kurt Roeckx*
* Deprecated EVP_MD_CTX_set_update_fn() and EVP_MD_CTX_update_fn().
*Rich Salz*
* Deprecated the type OCSP_REQ_CTX and the functions OCSP_REQ_CTX_*() and
replaced with OSSL_HTTP_REQ_CTX and the functions OSSL_HTTP_REQ_CTX_*().
*Rich Salz, Richard Levitte, and David von Oheimb*
* Deprecated `X509_http_nbio()` and `X509_CRL_http_nbio()`.
*David von Oheimb*
* Deprecated `OCSP_parse_url()`.
*David von Oheimb*
* Validation of SM2 keys has been separated from the validation of regular EC
keys.
*Nicola Tuveri*
* Behavior of the `pkey` app is changed, when using the `-check` or `-pubcheck`
switches: a validation failure triggers an early exit, returning a failure
exit status to the parent process.
*Nicola Tuveri*
* Changed behavior of SSL_CTX_set_ciphersuites() and SSL_set_ciphersuites()
to ignore unknown ciphers.
*Otto Hollmann*
* The `-cipher-commands` and `-digest-commands` options
of the command line utility `list` have been deprecated.
Instead use the `-cipher-algorithms` and `-digest-algorithms` options.
*Dmitry Belyavskiy*
* Added convenience functions for generating asymmetric key pairs:
The 'quick' one-shot (yet somewhat limited) function L<EVP_PKEY_Q_keygen(3)>
and macros for the most common cases: <EVP_RSA_gen(3)> and L<EVP_EC_gen(3)>.
*David von Oheimb*
* All of the low level EC_KEY functions have been deprecated.
*Shane Lontis, Paul Dale, Richard Levitte, and Tomáš Mráz*
* Deprecated all the libcrypto and libssl error string loading
functions.
*Richard Levitte*
* The functions SSL_CTX_set_tmp_dh_callback and SSL_set_tmp_dh_callback, as
well as the macros SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() have been
deprecated.
*Matt Caswell*
* The `-crypt` option to the `passwd` command line tool has been removed.
*Paul Dale*
* The -C option to the `x509`, `dhparam`, `dsaparam`, and `ecparam` commands
were removed.
*Rich Salz*
* Add support for AES Key Wrap inverse ciphers to the EVP layer.
*Shane Lontis*
* Deprecated EVP_PKEY_set1_tls_encodedpoint() and
EVP_PKEY_get1_tls_encodedpoint().
*Matt Caswell*
* The security callback, which can be customised by application code, supports
the security operation SSL_SECOP_TMP_DH. One location of the "other" parameter
was incorrectly passing a DH object. It now passed an EVP_PKEY in all cases.
*Matt Caswell*
* Add PKCS7_get_octet_string() and PKCS7_type_is_other() to the public
interface. Their functionality remains unchanged.
*Jordan Montgomery*
* Added new option for 'openssl list', '-providers', which will display the
list of loaded providers, their names, version and status. It optionally
displays their gettable parameters.
*Paul Dale*
* Removed EVP_PKEY_set_alias_type().
*Richard Levitte*
* Deprecated `EVP_PKEY_CTX_set_rsa_keygen_pubexp()` and introduced
`EVP_PKEY_CTX_set1_rsa_keygen_pubexp()`, which is now preferred.
*Jeremy Walch*
* Changed all "STACK" functions to be macros instead of inline functions. Macro
parameters are still checked for type safety at compile time via helper
inline functions.
*Matt Caswell*
* Remove the RAND_DRBG API
*Paul Dale and Matthias St. Pierre*
* Allow `SSL_set1_host()` and `SSL_add1_host()` to take IP literal addresses
as well as actual hostnames.
*David Woodhouse*
* The 'MinProtocol' and 'MaxProtocol' configuration commands now silently
ignore TLS protocol version bounds when configuring DTLS-based contexts, and
conversely, silently ignore DTLS protocol version bounds when configuring
TLS-based contexts. The commands can be repeated to set bounds of both
types. The same applies with the corresponding "min_protocol" and
"max_protocol" command-line switches, in case some application uses both TLS
and DTLS.
SSL_CTX instances that are created for a fixed protocol version (e.g.
`TLSv1_server_method()`) also silently ignore version bounds. Previously
attempts to apply bounds to these protocol versions would result in an
error. Now only the "version-flexible" SSL_CTX instances are subject to
limits in configuration files in command-line options.
*Viktor Dukhovni*
* Deprecated the `ENGINE` API. Engines should be replaced with providers
going forward.
*Paul Dale*
* Reworked the recorded ERR codes to make better space for system errors.
To distinguish them, the macro `ERR_SYSTEM_ERROR()` indicates if the
given code is a system error (true) or an OpenSSL error (false).
*Richard Levitte*
* Reworked the test perl framework to better allow parallel testing.
*Nicola Tuveri and David von Oheimb*
* Added ciphertext stealing algorithms AES-128-CBC-CTS, AES-192-CBC-CTS and
AES-256-CBC-CTS to the providers. CS1, CS2 and CS3 variants are supported.
*Shane Lontis*
* 'Configure' has been changed to figure out the configuration target if
none is given on the command line. Consequently, the 'config' script is
now only a mere wrapper. All documentation is changed to only mention
'Configure'.
*Rich Salz and Richard Levitte*
* Added a library context `OSSL_LIB_CTX` that applications as well as
other libraries can use to form a separate context within which
libcrypto operations are performed.
*Richard Levitte*
* Added various `_ex` functions to the OpenSSL API that support using
a non-default `OSSL_LIB_CTX`.
*OpenSSL team*
* Handshake now fails if Extended Master Secret extension is dropped
on renegotiation.
*Tomáš Mráz*
* Dropped interactive mode from the `openssl` program.
*Richard Levitte*
* Deprecated `EVP_PKEY_cmp()` and `EVP_PKEY_cmp_parameters()`.
*David von Oheimb and Shane Lontis*
* Deprecated `EC_METHOD_get_field_type()`.
*Billy Bob Brumley*
* Deprecated EC_GFp_simple_method(), EC_GFp_mont_method(),
EC_GF2m_simple_method(), EC_GFp_nist_method(), EC_GFp_nistp224_method()
EC_GFp_nistp256_method(), and EC_GFp_nistp521_method().
*Billy Bob Brumley*
* Deprecated EC_GROUP_new(), EC_GROUP_method_of(), and EC_POINT_method_of().
*Billy Bob Brumley*
* Add CAdES-BES signature verification support, mostly derived
from ESSCertIDv2 TS (RFC 5816) contribution by Marek Klein.
*Filipe Raimundo da Silva*
* Add CAdES-BES signature scheme and attributes support (RFC 5126) to CMS API.
*Antonio Iacono*
* Added the AuthEnvelopedData content type structure (RFC 5083) with AES-GCM
parameter (RFC 5084) for the Cryptographic Message Syntax (CMS).
*Jakub Zelenka*
* Deprecated EC_POINT_make_affine() and EC_POINTs_make_affine().
*Billy Bob Brumley*
* Deprecated EC_GROUP_precompute_mult(), EC_GROUP_have_precompute_mult(), and
EC_KEY_precompute_mult().
*Billy Bob Brumley*
* Deprecated EC_POINTs_mul().
*Billy Bob Brumley*
* Removed FIPS_mode() and FIPS_mode_set().
*Shane Lontis*
* The SSL option SSL_OP_IGNORE_UNEXPECTED_EOF is introduced.
*Dmitry Belyavskiy*
* Deprecated EC_POINT_set_Jprojective_coordinates_GFp() and
EC_POINT_get_Jprojective_coordinates_GFp().
*Billy Bob Brumley*
* Added OSSL_PARAM_BLD to the public interface. This allows OSSL_PARAM
arrays to be more easily constructed via a series of utility functions.
Create a parameter builder using OSSL_PARAM_BLD_new(), add parameters using
the various push functions and finally convert to a passable OSSL_PARAM
array using OSSL_PARAM_BLD_to_param().
*Paul Dale*
* The security strength of SHA1 and MD5 based signatures in TLS has been
reduced.
*Kurt Roeckx*
* Added EVP_PKEY_set_type_by_keymgmt(), to initialise an EVP_PKEY to
contain a provider side internal key.
*Richard Levitte*
* ASN1_verify(), ASN1_digest() and ASN1_sign() have been deprecated.
*Richard Levitte*
* Project text documents not yet having a proper file name extension
(`HACKING`, `LICENSE`, `NOTES*`, `README*`, `VERSION`) have been renamed to
`*.md` as far as reasonable, else `*.txt`, for better use with file managers.
*David von Oheimb*
* The main project documents (README, NEWS, CHANGES, INSTALL, SUPPORT)
have been converted to Markdown with the goal to produce documents
which not only look pretty when viewed online in the browser, but
remain well readable inside a plain text editor.
To achieve this goal, a 'minimalistic' Markdown style has been applied
which avoids formatting elements that interfere too much with the
reading flow in the text file. For example, it
* avoids [ATX headings][] and uses [setext headings][] instead
(which works for `<h1>` and `<h2>` headings only).
* avoids [inline links][] and uses [reference links][] instead.
* avoids [fenced code blocks][] and uses [indented code blocks][] instead.
[ATX headings]: https://github.github.com/gfm/#atx-headings
[setext headings]: https://github.github.com/gfm/#setext-headings
[inline links]: https://github.github.com/gfm/#inline-link
[reference links]: https://github.github.com/gfm/#reference-link
[fenced code blocks]: https://github.github.com/gfm/#fenced-code-blocks
[indented code blocks]: https://github.github.com/gfm/#indented-code-blocks
*Matthias St. Pierre*
* The test suite is changed to preserve results of each test recipe.
A new directory test-runs/ with subdirectories named like the
test recipes are created in the build tree for this purpose.
*Richard Levitte*
* Added an implementation of CMP and CRMF (RFC 4210, RFC 4211 RFC 6712).
This adds `crypto/cmp/`, `crpyto/crmf/`, `apps/cmp.c`, and `test/cmp_*`.
See L<openssl-cmp(1)> and L<OSSL_CMP_exec_IR_ses(3)> as starting points.
*David von Oheimb, Martin Peylo*
* Generalized the HTTP client code from `crypto/ocsp/` into `crpyto/http/`.
It supports arbitrary request and response content types, GET redirection,
TLS, connections via HTTP(S) proxies, connections and exchange via
user-defined BIOs (allowing implicit connections), persistent connections,
and timeout checks. See L<OSSL_HTTP_transfer(3)> etc. for details.
The legacy OCSP-focused (and only partly documented) API
is retained for backward compatibility, while most of it is deprecated.
*David von Oheimb*
* Added `util/check-format.pl`, a tool for checking adherence to the
OpenSSL coding style <https://www.openssl.org/policies/codingstyle.html>.
The checks performed are incomplete and yield some false positives.
Still the tool should be useful for detecting most typical glitches.
*David von Oheimb*
* `BIO_do_connect()` and `BIO_do_handshake()` have been extended:
If domain name resolution yields multiple IP addresses all of them are tried
after `connect()` failures.
*David von Oheimb*
* All of the low level RSA functions have been deprecated.
*Paul Dale*
* X509 certificates signed using SHA1 are no longer allowed at security
level 1 and above.
*Kurt Roeckx*
* The command line utilities dhparam, dsa, gendsa and dsaparam have been
modified to use PKEY APIs. These commands are now in maintenance mode
and no new features will be added to them.
*Paul Dale*
* The command line utility rsautl has been deprecated.
*Paul Dale*
* The command line utilities genrsa and rsa have been modified to use PKEY
APIs. They now write PKCS#8 keys by default. These commands are now in
maintenance mode and no new features will be added to them.
*Paul Dale*
* All of the low level DH functions have been deprecated.
*Paul Dale and Matt Caswell*
* All of the low level DSA functions have been deprecated.
*Paul Dale*
* Reworked the treatment of EC EVP_PKEYs with the SM2 curve to
automatically become EVP_PKEY_SM2 rather than EVP_PKEY_EC.
*Richard Levitte*
* Deprecated low level ECDH and ECDSA functions.
*Paul Dale*
* Deprecated EVP_PKEY_decrypt_old() and EVP_PKEY_encrypt_old().
*Richard Levitte*
* Enhanced the documentation of EVP_PKEY_get_size(), EVP_PKEY_get_bits()
and EVP_PKEY_get_security_bits(). Especially EVP_PKEY_get_size() needed
a new formulation to include all the things it can be used for,
as well as words of caution.
*Richard Levitte*
* The SSL_CTX_set_tlsext_ticket_key_cb(3) function has been deprecated.
*Paul Dale*
* All of the low level HMAC functions have been deprecated.
*Paul Dale and David von Oheimb*
* Over two thousand fixes were made to the documentation, including:
- Common options (such as -rand/-writerand, TLS version control, etc)
were refactored and point to newly-enhanced descriptions in openssl.pod.
- Added style conformance for all options (with help from Richard Levitte),
documented all reported missing options, added a CI build to check
that all options are documented and that no unimplemented options
are documented.
- Documented some internals, such as all use of environment variables.
- Addressed all internal broken L<> references.
*Rich Salz*
* All of the low level CMAC functions have been deprecated.
*Paul Dale*
* The low-level MD2, MD4, MD5, MDC2, RIPEMD160 and Whirlpool digest
functions have been deprecated.
*Paul Dale and David von Oheimb*
* Corrected the documentation of the return values from the `EVP_DigestSign*`
set of functions. The documentation mentioned negative values for some
errors, but this was never the case, so the mention of negative values
was removed.
Code that followed the documentation and thereby check with something
like `EVP_DigestSignInit(...) <= 0` will continue to work undisturbed.
*Richard Levitte*
* All of the low level cipher functions have been deprecated.
*Matt Caswell and Paul Dale*
* Removed include/openssl/opensslconf.h.in and replaced it with
include/openssl/configuration.h.in, which differs in not including
<openssl/macros.h>. A short header include/openssl/opensslconf.h
was added to include both.
This allows internal hacks where one might need to modify the set
of configured macros, for example this if deprecated symbols are
still supposed to be available internally:
#include <openssl/configuration.h>
#undef OPENSSL_NO_DEPRECATED
#define OPENSSL_SUPPRESS_DEPRECATED
#include <openssl/macros.h>
This should not be used by applications that use the exported
symbols, as that will lead to linking errors.
*Richard Levitte*
* Fixed an overflow bug in the x64_64 Montgomery squaring procedure
used in exponentiation with 512-bit moduli. No EC algorithms are
affected. Analysis suggests that attacks against 2-prime RSA1024,
3-prime RSA1536, and DSA1024 as a result of this defect would be very
difficult to perform and are not believed likely. Attacks against DH512
are considered just feasible. However, for an attack the target would
have to re-use the DH512 private key, which is not recommended anyway.
Also applications directly using the low-level API BN_mod_exp may be
affected if they use BN_FLG_CONSTTIME.
([CVE-2019-1551])
*Andy Polyakov*
* Most memory-debug features have been deprecated, and the functionality
replaced with no-ops.
*Rich Salz*
* Added documentation for the STACK API.
*Rich Salz*
* Introduced a new method type and API, OSSL_ENCODER, to represent
generic encoders. These do the same sort of job that PEM writers
and d2i functions do, but with support for methods supplied by
providers, and the possibility for providers to support other
formats as well.
*Richard Levitte*
* Introduced a new method type and API, OSSL_DECODER, to represent
generic decoders. These do the same sort of job that PEM readers
and i2d functions do, but with support for methods supplied by
providers, and the possibility for providers to support other
formats as well.
*Richard Levitte*
* Added a .pragma directive to the syntax of configuration files, to
allow varying behavior in a supported and predictable manner.
Currently added pragma:
.pragma dollarid:on
This allows dollar signs to be a keyword character unless it's
followed by a opening brace or parenthesis. This is useful for
platforms where dollar signs are commonly used in names, such as
volume names and system directory names on VMS.
*Richard Levitte*
* Added functionality to create an EVP_PKEY from user data.
*Richard Levitte*
* Change the interpretation of the '--api' configuration option to
mean that this is a desired API compatibility level with no
further meaning. The previous interpretation, that this would
also mean to remove all deprecated symbols up to and including
the given version, no requires that 'no-deprecated' is also used
in the configuration.
When building applications, the desired API compatibility level
can be set with the OPENSSL_API_COMPAT macro like before. For
API compatibility version below 3.0, the old style numerical
value is valid as before, such as -DOPENSSL_API_COMPAT=0x10100000L.
For version 3.0 and on, the value is expected to be the decimal
value calculated from the major and minor version like this:
MAJOR * 10000 + MINOR * 100
Examples:
-DOPENSSL_API_COMPAT=30000 For 3.0
-DOPENSSL_API_COMPAT=30200 For 3.2
To hide declarations that are deprecated up to and including the
given API compatibility level, -DOPENSSL_NO_DEPRECATED must be
given when building the application as well.
*Richard Levitte*
* Added the X509_LOOKUP_METHOD called X509_LOOKUP_store, to allow
access to certificate and CRL stores via URIs and OSSL_STORE
loaders.
This adds the following functions:
- X509_LOOKUP_store()
- X509_STORE_load_file()
- X509_STORE_load_path()
- X509_STORE_load_store()
- SSL_add_store_cert_subjects_to_stack()
- SSL_CTX_set_default_verify_store()
- SSL_CTX_load_verify_file()
- SSL_CTX_load_verify_dir()
- SSL_CTX_load_verify_store()
*Richard Levitte*
* Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY.
The presence of this system service is determined at run-time.
*Richard Levitte*
* Added functionality to create an EVP_PKEY context based on data
for methods from providers. This takes an algorithm name and a
property query string and simply stores them, with the intent
that any operation that uses this context will use those strings
to fetch the needed methods implicitly, thereby making the port
of application written for pre-3.0 OpenSSL easier.
*Richard Levitte*
* The undocumented function NCONF_WIN32() has been deprecated; for
conversion details see the HISTORY section of doc/man5/config.pod
*Rich Salz*
* Introduced the new functions EVP_DigestSignInit_ex() and
EVP_DigestVerifyInit_ex(). The macros EVP_DigestSignUpdate() and
EVP_DigestVerifyUpdate() have been converted to functions. See the man
pages for further details.
*Matt Caswell*
* Over two thousand fixes were made to the documentation, including:
adding missing command flags, better style conformance, documentation
of internals, etc.
*Rich Salz, Richard Levitte*
* s390x assembly pack: add hardware-support for P-256, P-384, P-521,
X25519, X448, Ed25519 and Ed448.
*Patrick Steuer*
* Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just
the first value.
*Jon Spillett*
* Deprecated the public definition of `ERR_STATE` as well as the function
`ERR_get_state()`. This is done in preparation of making `ERR_STATE` an
opaque type.
*Richard Levitte*
* Added ERR functionality to give callers access to the stored function
names that have replaced the older function code based functions.
New functions are ERR_peek_error_func(), ERR_peek_last_error_func(),
ERR_peek_error_data(), ERR_peek_last_error_data(), ERR_get_error_all(),
ERR_peek_error_all() and ERR_peek_last_error_all().
Deprecate ERR functions ERR_get_error_line(), ERR_get_error_line_data(),
ERR_peek_error_line_data(), ERR_peek_last_error_line_data() and
ERR_func_error_string().
*Richard Levitte*
* Extended testing to be verbose for failing tests only. The make variables
VERBOSE_FAILURE or VF can be used to enable this:
$ make VF=1 test # Unix
$ mms /macro=(VF=1) test ! OpenVMS
$ nmake VF=1 test # Windows
*Richard Levitte*
* Added the `-copy_extensions` option to the `x509` command for use with
`-req` and `-x509toreq`. When given with the `copy` or `copyall` argument,
all extensions in the request are copied to the certificate or vice versa.
*David von Oheimb*, *Kirill Stefanenkov <kirill_stefanenkov@rambler.ru>*
* Added the `-copy_extensions` option to the `req` command for use with
`-x509`. When given with the `copy` or `copyall` argument,
all extensions in the certification request are copied to the certificate.
*David von Oheimb*
* The `x509`, `req`, and `ca` commands now make sure that X.509v3 certificates
they generate are by default RFC 5280 compliant in the following sense:
There is a subjectKeyIdentifier extension with a hash value of the public key
and for not self-signed certs there is an authorityKeyIdentifier extension
with a keyIdentifier field or issuer information identifying the signing key.
This is done unless some configuration overrides the new default behavior,
such as `subjectKeyIdentifier = none` and `authorityKeyIdentifier = none`.
*David von Oheimb*
* Added several checks to `X509_verify_cert()` according to requirements in
RFC 5280 in case `X509_V_FLAG_X509_STRICT` is set
(which may be done by using the CLI option `-x509_strict`):
* The basicConstraints of CA certificates must be marked critical.
* CA certificates must explicitly include the keyUsage extension.
* If a pathlenConstraint is given the key usage keyCertSign must be allowed.
* The issuer name of any certificate must not be empty.
* The subject name of CA certs, certs with keyUsage crlSign,
and certs without subjectAlternativeName must not be empty.
* If a subjectAlternativeName extension is given it must not be empty.
* The signatureAlgorithm field and the cert signature must be consistent.
* Any given authorityKeyIdentifier and any given subjectKeyIdentifier
must not be marked critical.
* The authorityKeyIdentifier must be given for X.509v3 certs
unless they are self-signed.
* The subjectKeyIdentifier must be given for all X.509v3 CA certs.
*David von Oheimb*
* Certificate verification using `X509_verify_cert()` meanwhile rejects EC keys
with explicit curve parameters (specifiedCurve) as required by RFC 5480.
*Tomáš Mráz*
* For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters, when loading a encoded key
or calling `EC_GROUP_new_from_ecpkparameters()`/
`EC_GROUP_new_from_ecparameters()`.
This prevents bypass of security hardening and performance gains,
especially for curves with specialized EC_METHODs.
By default, if a key encoded with explicit parameters is loaded and later
encoded, the output is still encoded with explicit parameters, even if
internally a "named" EC_GROUP is used for computation.
*Nicola Tuveri*
* Compute ECC cofactors if not provided during EC_GROUP construction. Before
this change, EC_GROUP_set_generator would accept order and/or cofactor as
NULL. After this change, only the cofactor parameter can be NULL. It also
does some minimal sanity checks on the passed order.
([CVE-2019-1547])
*Billy Bob Brumley*
* Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
An attack is simple, if the first CMS_recipientInfo is valid but the
second CMS_recipientInfo is chosen ciphertext. If the second
recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
encryption key will be replaced by garbage, and the message cannot be
decoded, but if the RSA decryption fails, the correct encryption key is
used and the recipient will not notice the attack.
As a work around for this potential attack the length of the decrypted
key must be equal to the cipher default key length, in case the
certifiate is not given and all recipientInfo are tried out.
The old behaviour can be re-enabled in the CMS code by setting the
CMS_DEBUG_DECRYPT flag.
*Bernd Edlinger*
* Early start up entropy quality from the DEVRANDOM seed source has been
improved for older Linux systems. The RAND subsystem will wait for
/dev/random to be producing output before seeding from /dev/urandom.
The seeded state is stored for future library initialisations using
a system global shared memory segment. The shared memory identifier
can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to
the desired value. The default identifier is 114.
*Paul Dale*
* Revised BN_generate_prime_ex to not avoid factors 2..17863 in p-1
when primes for RSA keys are computed.
Since we previously always generated primes == 2 (mod 3) for RSA keys,
the 2-prime and 3-prime RSA modules were easy to distinguish, since
`N = p*q = 1 (mod 3)`, but `N = p*q*r = 2 (mod 3)`. Therefore fingerprinting
2-prime vs. 3-prime RSA keys was possible by computing N mod 3.
This avoids possible fingerprinting of newly generated RSA modules.
*Bernd Edlinger*
* Correct the extended master secret constant on EBCDIC systems. Without this
fix TLS connections between an EBCDIC system and a non-EBCDIC system that
negotiate EMS will fail. Unfortunately this also means that TLS connections
between EBCDIC systems with this fix, and EBCDIC systems without this
fix will fail if they negotiate EMS.
*Matt Caswell*
* Changed the library initialisation so that the config file is now loaded
by default. This was already the case for libssl. It now occurs for both
libcrypto and libssl. Use the OPENSSL_INIT_NO_LOAD_CONFIG option to
`OPENSSL_init_crypto()` to suppress automatic loading of a config file.
*Matt Caswell*
* Introduced new error raising macros, `ERR_raise()` and `ERR_raise_data()`,
where the former acts as a replacement for `ERR_put_error()`, and the
latter replaces the combination `ERR_put_error()` + `ERR_add_error_data()`.
`ERR_raise_data()` adds more flexibility by taking a format string and
an arbitrary number of arguments following it, to be processed with
`BIO_snprintf()`.
*Richard Levitte*
* Introduced a new function, `OSSL_PROVIDER_available()`, which can be used
to check if a named provider is loaded and available. When called, it
will also activate all fallback providers if such are still present.
*Richard Levitte*
* Enforce a minimum DH modulus size of 512 bits.
*Bernd Edlinger*
* Changed DH parameters to generate the order q subgroup instead of 2q.
Previously generated DH parameters are still accepted by DH_check
but DH_generate_key works around that by clearing bit 0 of the
private key for those. This avoids leaking bit 0 of the private key.
*Bernd Edlinger*
* Significantly reduce secure memory usage by the randomness pools.
*Paul Dale*
* `{CRYPTO,OPENSSL}_mem_debug_{push,pop}` are now no-ops and have been
deprecated.
*Rich Salz*
* A new type, EVP_KEYEXCH, has been introduced to represent key exchange
algorithms. An implementation of a key exchange algorithm can be obtained
by using the function EVP_KEYEXCH_fetch(). An EVP_KEYEXCH algorithm can be
used in a call to EVP_PKEY_derive_init_ex() which works in a similar way to
the older EVP_PKEY_derive_init() function. See the man pages for the new
functions for further details.
*Matt Caswell*
* The EVP_PKEY_CTX_set_dh_pad() macro has now been converted to a function.
*Matt Caswell*
* Removed the function names from error messages and deprecated the
xxx_F_xxx define's.
*Richard Levitte*
* Removed NextStep support and the macro OPENSSL_UNISTD
*Rich Salz*
* Removed DES_check_key. Also removed OPENSSL_IMPLEMENT_GLOBAL,
OPENSSL_GLOBAL_REF, OPENSSL_DECLARE_GLOBAL.
Also removed "export var as function" capability; we do not export
variables, only functions.
*Rich Salz*
* RC5_32_set_key has been changed to return an int type, with 0 indicating
an error and 1 indicating success. In previous versions of OpenSSL this
was a void type. If a key was set longer than the maximum possible this
would crash.
*Matt Caswell*
* Support SM2 signing and verification schemes with X509 certificate.
*Paul Yang*
* Use SHA256 as the default digest for TS query in the `ts` app.
*Tomáš Mráz*
* Change PBKDF2 to conform to SP800-132 instead of the older PKCS5 RFC2898.
*Shane Lontis*
* Default cipher lists/suites are now available via a function, the
#defines are deprecated.
*Todd Short*
* Add target VC-WIN32-UWP, VC-WIN64A-UWP, VC-WIN32-ARM-UWP and
VC-WIN64-ARM-UWP in Windows OneCore target for making building libraries
for Windows Store apps easier. Also, the "no-uplink" option has been added.
*Kenji Mouri*
* Join the directories crypto/x509 and crypto/x509v3
*Richard Levitte*
* Added command 'openssl kdf' that uses the EVP_KDF API.
*Shane Lontis*
* Added command 'openssl mac' that uses the EVP_MAC API.
*Shane Lontis*
* Added OPENSSL_info() to get diverse built-in OpenSSL data, such
as default directories. Also added the command 'openssl info'
for scripting purposes.
*Richard Levitte*
* The functions AES_ige_encrypt() and AES_bi_ige_encrypt() have been
deprecated.
*Matt Caswell*
* Add prediction resistance to the DRBG reseeding process.
*Paul Dale*
* Limit the number of blocks in a data unit for AES-XTS to 2^20 as
mandated by IEEE Std 1619-2018.
*Paul Dale*
* Added newline escaping functionality to a filename when using openssl dgst.
This output format is to replicate the output format found in the `*sum`
checksum programs. This aims to preserve backward compatibility.
*Matt Eaton, Richard Levitte, and Paul Dale*
* Removed the heartbeat message in DTLS feature, as it has very
little usage and doesn't seem to fulfill a valuable purpose.
The configuration option is now deprecated.
*Richard Levitte*
* Changed the output of 'openssl {digestname} < file' to display the
digest name in its output.
*Richard Levitte*
* Added a new generic trace API which provides support for enabling
instrumentation through trace output.
*Richard Levitte & Matthias St. Pierre*
* Added build tests for C++. These are generated files that only do one
thing, to include one public OpenSSL head file each. This tests that
the public header files can be usefully included in a C++ application.
This test isn't enabled by default. It can be enabled with the option
'enable-buildtest-c++'.
*Richard Levitte*
* Added KB KDF (EVP_KDF_KB) to EVP_KDF.
*Robbie Harwood*
* Added SSH KDF (EVP_KDF_SSHKDF) and KRB5 KDF (EVP_KDF_KRB5KDF) to EVP_KDF.
*Simo Sorce*
* Added Single Step KDF (EVP_KDF_SS), X963 KDF, and X942 KDF to EVP_KDF.
*Shane Lontis*
* Added KMAC to EVP_MAC.
*Shane Lontis*
* Added property based algorithm implementation selection framework to
the core.
*Paul Dale*
* Added SCA hardening for modular field inversion in EC_GROUP through
a new dedicated field_inv() pointer in EC_METHOD.
This also addresses a leakage affecting conversions from projective
to affine coordinates.
*Billy Bob Brumley, Nicola Tuveri*
* Added EVP_KDF, an EVP layer KDF API, to simplify adding KDF and PRF
implementations. This includes an EVP_PKEY to EVP_KDF bridge for
those algorithms that were already supported through the EVP_PKEY API
(scrypt, TLS1 PRF and HKDF). The low-level KDF functions for PBKDF2
and scrypt are now wrappers that call EVP_KDF.
*David Makepeace*
* Build devcrypto engine as a dynamic engine.
*Eneas U de Queiroz*
* Add keyed BLAKE2 to EVP_MAC.
*Antoine Salon*
* Fix a bug in the computation of the endpoint-pair shared secret used
by DTLS over SCTP. This breaks interoperability with older versions
of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. There is a runtime
switch SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG (off by default) enabling
interoperability with such broken implementations. However, enabling
this switch breaks interoperability with correct implementations.
* Fix a use after free bug in d2i_X509_PUBKEY when overwriting a
re-used X509_PUBKEY object if the second PUBKEY is malformed.
*Bernd Edlinger*
* Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
*Richard Levitte*
* Changed the license to the Apache License v2.0.
*Richard Levitte*
* Switch to a new version scheme using three numbers MAJOR.MINOR.PATCH.
- Major releases (indicated by incrementing the MAJOR release number)
may introduce incompatible API/ABI changes.
- Minor releases (indicated by incrementing the MINOR release number)
may introduce new features but retain API/ABI compatibility.
- Patch releases (indicated by incrementing the PATCH number)
are intended for bug fixes and other improvements of existing
features only (like improving performance or adding documentation)
and retain API/ABI compatibility.
*Richard Levitte*
* Add support for RFC5297 SIV mode (siv128), including AES-SIV.
*Todd Short*
* Remove the 'dist' target and add a tarball building script. The
'dist' target has fallen out of use, and it shouldn't be
necessary to configure just to create a source distribution.
*Richard Levitte*
* Recreate the OS390-Unix config target. It no longer relies on a
special script like it did for OpenSSL pre-1.1.0.
*Richard Levitte*
* Instead of having the source directories listed in Configure, add
a 'build.info' keyword SUBDIRS to indicate what sub-directories to
look into.
*Richard Levitte*
* Add GMAC to EVP_MAC.
*Paul Dale*
* Ported the HMAC, CMAC and SipHash EVP_PKEY_METHODs to EVP_MAC.
*Richard Levitte*
* Added EVP_MAC, an EVP layer MAC API, to simplify adding MAC
implementations. This includes a generic EVP_PKEY to EVP_MAC bridge,
to facilitate the continued use of MACs through raw private keys in
functionality such as `EVP_DigestSign*` and `EVP_DigestVerify*`.
*Richard Levitte*
* Deprecate ECDH_KDF_X9_62().
*Antoine Salon*
* 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*
* AES-XTS mode now enforces that its two keys are different to mitigate
the attacked described in "Efficient Instantiations of Tweakable
Blockciphers and Refinements to Modes OCB and PMAC" by Phillip Rogaway.
Details of this attack can be obtained from:
<http://web.cs.ucdavis.edu/%7Erogaway/papers/offsets.pdf>
*Paul Dale*
* Rename the object files, i.e. give them other names than in previous
versions. Their names now include the name of the final product, as
well as its type mnemonic (bin, lib, shlib).
*Richard Levitte*
* Added new option for 'openssl list', '-objects', which will display the
list of built in objects, i.e. OIDs with names.
*Richard Levitte*
* Added the options `-crl_lastupdate` and `-crl_nextupdate` to `openssl ca`,
allowing the `lastUpdate` and `nextUpdate` fields in the generated CRL to
be set explicitly.
*Chris Novakovic*
* Added support for Linux Kernel TLS data-path. The Linux Kernel data-path
improves application performance by removing data copies and providing
applications with zero-copy system calls such as sendfile and splice.
*Boris Pismenny*
* The SSL option SSL_OP_CLEANSE_PLAINTEXT is introduced.
*Martin Elshuber*
* `PKCS12_parse` now maintains the order of the parsed certificates
when outputting them via `*ca` (rather than reversing it).
*David von Oheimb*
* Deprecated pthread fork support methods.
*Randall S. Becker*
* Added support for FFDHE key exchange in TLS 1.3.
*Raja Ashok*
* Added a new concept for OpenSSL plugability: providers. This
functionality is designed to replace the ENGINE API and ENGINE
implementations, and to be much more dynamic, allowing provider
authors to introduce new algorithms among other things, as long as
there's an API that supports the algorithm type.
With this concept comes a new core API for interaction between
libcrypto and provider implementations. Public libcrypto functions
that want to use providers do so through this core API.
The main documentation for this core API is found in
doc/man7/provider.pod, doc/man7/provider-base.pod, and they in turn
refer to other manuals describing the API specific for supported
algorithm types (also called operations).
*The OpenSSL team*
OpenSSL 1.1.1
-------------
### Changes between 1.1.1l and 1.1.1m [xx XXX xxxx]
* Avoid loading of a dynamic engine twice.
*Bernd Edlinger*
* Prioritise DANE TLSA issuer certs over peer certs
*Viktor Dukhovni*
* Fixed random API for MacOS prior to 10.12
These MacOS versions don't support the CommonCrypto APIs
*Lenny Primak*
### Changes between 1.1.1k and 1.1.1l [24 Aug 2021]
* Fixed an SM2 Decryption Buffer Overflow.
In order to decrypt SM2 encrypted data an application is expected to
call the API function EVP_PKEY_decrypt(). Typically an application will
call this function twice. The first time, on entry, the "out" parameter
can be NULL and, on exit, the "outlen" parameter is populated with the
buffer size required to hold the decrypted plaintext. The application
can then allocate a sufficiently sized buffer and call EVP_PKEY_decrypt()
again, but this time passing a non-NULL value for the "out" parameter.
A bug in the implementation of the SM2 decryption code means that the
calculation of the buffer size required to hold the plaintext returned
by the first call to EVP_PKEY_decrypt() can be smaller than the actual
size required by the second call. This can lead to a buffer overflow
when EVP_PKEY_decrypt() is called by the application a second time with
a buffer that is too small.
A malicious attacker who is able present SM2 content for decryption to
an application could cause attacker chosen data to overflow the buffer
by up to a maximum of 62 bytes altering the contents of other data held
after the buffer, possibly changing application behaviour or causing
the application to crash. The location of the buffer is application
dependent but is typically heap allocated.
([CVE-2021-3711])
*Matt Caswell*
* Fixed various read buffer overruns processing ASN.1 strings
ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING
structure which contains a buffer holding the string data and a field
holding the buffer length. This contrasts with normal C strings which
are repesented as a buffer for the string data which is terminated
with a NUL (0) byte.
Although not a strict requirement, ASN.1 strings that are parsed using
OpenSSL's own "d2i" functions (and other similar parsing functions) as
well as any string whose value has been set with the ASN1_STRING_set()
function will additionally NUL terminate the byte array in the
ASN1_STRING structure.
However, it is possible for applications to directly construct valid
ASN1_STRING structures which do not NUL terminate the byte array by
directly setting the "data" and "length" fields in the ASN1_STRING
array. This can also happen by using the ASN1_STRING_set0() function.
Numerous OpenSSL functions that print ASN.1 data have been found to
assume that the ASN1_STRING byte array will be NUL terminated, even
though this is not guaranteed for strings that have been directly
constructed. Where an application requests an ASN.1 structure to be
printed, and where that ASN.1 structure contains ASN1_STRINGs that have
been directly constructed by the application without NUL terminating
the "data" field, then a read buffer overrun can occur.
The same thing can also occur during name constraints processing
of certificates (for example if a certificate has been directly
constructed by the application instead of loading it via the OpenSSL
parsing functions, and the certificate contains non NUL terminated
ASN1_STRING structures). It can also occur in the X509_get1_email(),
X509_REQ_get1_email() and X509_get1_ocsp() functions.
If a malicious actor can cause an application to directly construct an
ASN1_STRING and then process it through one of the affected OpenSSL
functions then this issue could be hit. This might result in a crash
(causing a Denial of Service attack). It could also result in the
disclosure of private memory contents (such as private keys, or
sensitive plaintext).
([CVE-2021-3712])
*Matt Caswell*
### Changes between 1.1.1j and 1.1.1k [25 Mar 2021]
* Fixed a problem with verifying a certificate chain when using the
X509_V_FLAG_X509_STRICT flag. This flag enables additional security checks of
the certificates present in a certificate chain. It is not set by default.
Starting from OpenSSL version 1.1.1h a check to disallow certificates in
the chain that have explicitly encoded elliptic curve parameters was added
as an additional strict check.
An error in the implementation of this check meant that the result of a
previous check to confirm that certificates in the chain are valid CA
certificates was overwritten. This effectively bypasses the check
that non-CA certificates must not be able to issue other certificates.
If a "purpose" has been configured then there is a subsequent opportunity
for checks that the certificate is a valid CA. All of the named "purpose"
values implemented in libcrypto perform this check. Therefore, where
a purpose is set the certificate chain will still be rejected even when the
strict flag has been used. A purpose is set by default in libssl client and
server certificate verification routines, but it can be overridden or
removed by an application.
In order to be affected, an application must explicitly set the
X509_V_FLAG_X509_STRICT verification flag and either not set a purpose
for the certificate verification or, in the case of TLS client or server
applications, override the default purpose.
([CVE-2021-3450])
*Tomáš Mráz*
* Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously
crafted renegotiation ClientHello message from a client. If a TLSv1.2
renegotiation ClientHello omits the signature_algorithms extension (where it
was present in the initial ClientHello), but includes a
signature_algorithms_cert extension then a NULL pointer dereference will
result, leading to a crash and a denial of service attack.
A server is only vulnerable if it has TLSv1.2 and renegotiation enabled
(which is the default configuration). OpenSSL TLS clients are not impacted by
this issue.
([CVE-2021-3449])
*Peter Kästle and Samuel Sapalski*
### Changes between 1.1.1i and 1.1.1j [16 Feb 2021]
* Fixed the X509_issuer_and_serial_hash() function. It attempts to
create a unique hash value based on the issuer and serial number data
contained within an X509 certificate. However it was failing to correctly
handle any errors that may occur while parsing the issuer field (which might
occur if the issuer field is maliciously constructed). This may subsequently
result in a NULL pointer deref and a crash leading to a potential denial of
service attack.
([CVE-2021-23841])
*Matt Caswell*
* Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING
padding mode to correctly check for rollback attacks. This is considered a
bug in OpenSSL 1.1.1 because it does not support SSLv2. In 1.0.2 this is
CVE-2021-23839.
*Matt Caswell*
Fixed the EVP_CipherUpdate, EVP_EncryptUpdate and EVP_DecryptUpdate
functions. Previously they could overflow the output length argument in some
cases where the input length is close to the maximum permissable length for
an integer on the platform. In such cases the return value from the function
call would be 1 (indicating success), but the output length value would be
negative. This could cause applications to behave incorrectly or crash.
([CVE-2021-23840])
*Matt Caswell*
* Fixed SRP_Calc_client_key so that it runs in constant time. The previous
implementation called BN_mod_exp without setting BN_FLG_CONSTTIME. This
could be exploited in a side channel attack to recover the password. Since
the attack is local host only this is outside of the current OpenSSL
threat model and therefore no CVE is assigned.
Thanks to Mohammed Sabt and Daniel De Almeida Braga for reporting this
issue.
*Matt Caswell*
### Changes between 1.1.1h and 1.1.1i [8 Dec 2020]
* Fixed NULL pointer deref in the GENERAL_NAME_cmp function
This function could crash if both GENERAL_NAMEs contain an EDIPARTYNAME.
If an attacker can control both items being compared then this could lead
to a possible denial of service attack. OpenSSL itself uses the
GENERAL_NAME_cmp function for two purposes:
1) Comparing CRL distribution point names between an available CRL and a
CRL distribution point embedded in an X509 certificate
2) When verifying that a timestamp response token signer matches the
timestamp authority name (exposed via the API functions
TS_RESP_verify_response and TS_RESP_verify_token)
([CVE-2020-1971])
*Matt Caswell*
### Changes between 1.1.1g and 1.1.1h [22 Sep 2020]
* Certificates with explicit curve parameters are now disallowed in
verification chains if the X509_V_FLAG_X509_STRICT flag is used.
*Tomáš Mráz*
* The 'MinProtocol' and 'MaxProtocol' configuration commands now silently
ignore TLS protocol version bounds when configuring DTLS-based contexts, and
conversely, silently ignore DTLS protocol version bounds when configuring
TLS-based contexts. The commands can be repeated to set bounds of both
types. The same applies with the corresponding "min_protocol" and
"max_protocol" command-line switches, in case some application uses both TLS
and DTLS.
SSL_CTX instances that are created for a fixed protocol version (e.g.
TLSv1_server_method()) also silently ignore version bounds. Previously
attempts to apply bounds to these protocol versions would result in an
error. Now only the "version-flexible" SSL_CTX instances are subject to
limits in configuration files in command-line options.
*Viktor Dukhovni*
* Handshake now fails if Extended Master Secret extension is dropped
on renegotiation.
*Tomáš Mráz*
* The Oracle Developer Studio compiler will start reporting deprecated APIs
### Changes between 1.1.1f and 1.1.1g [21 Apr 2020]
* Fixed segmentation fault in SSL_check_chain()
Server or client applications that call the SSL_check_chain() function
during or after a TLS 1.3 handshake may crash due to a NULL pointer
dereference as a result of incorrect handling of the
"signature_algorithms_cert" TLS extension. The crash occurs if an invalid
or unrecognised signature algorithm is received from the peer. This could
be exploited by a malicious peer in a Denial of Service attack.
([CVE-2020-1967])
*Benjamin Kaduk*
* Added AES consttime code for no-asm configurations
an optional constant time support for AES was added
when building openssl for no-asm.
Enable with: ./config no-asm -DOPENSSL_AES_CONST_TIME
Disable with: ./config no-asm -DOPENSSL_NO_AES_CONST_TIME
At this time this feature is by default disabled.
It will be enabled by default in 3.0.
*Bernd Edlinger*
### Changes between 1.1.1e and 1.1.1f [31 Mar 2020]
* Revert the change of EOF detection while reading in libssl to avoid
regressions in applications depending on the current way of reporting
the EOF. As the existing method is not fully accurate the change to
reporting the EOF via SSL_ERROR_SSL is kept on the current development
branch and will be present in the 3.0 release.
*Tomáš Mráz*
* Revised BN_generate_prime_ex to not avoid factors 3..17863 in p-1
when primes for RSA keys are computed.
Since we previously always generated primes == 2 (mod 3) for RSA keys,
the 2-prime and 3-prime RSA modules were easy to distinguish, since
N = p*q = 1 (mod 3), but N = p*q*r = 2 (mod 3). Therefore fingerprinting
2-prime vs. 3-prime RSA keys was possible by computing N mod 3.
This avoids possible fingerprinting of newly generated RSA modules.
*Bernd Edlinger*
### Changes between 1.1.1d and 1.1.1e [17 Mar 2020]
* Properly detect EOF while reading in libssl. Previously if we hit an EOF
while reading in libssl then we would report an error back to the
application (SSL_ERROR_SYSCALL) but errno would be 0. We now add
an error to the stack (which means we instead return SSL_ERROR_SSL) and
therefore give a hint as to what went wrong.
*Matt Caswell*
* Check that ed25519 and ed448 are allowed by the security level. Previously
signature algorithms not using an MD were not being checked that they were
allowed by the security level.
*Kurt Roeckx*
* Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername()
was not quite right. The behaviour was not consistent between resumption
and normal handshakes, and also not quite consistent with historical
behaviour. The behaviour in various scenarios has been clarified and
it has been updated to make it match historical behaviour as closely as
possible.
*Matt Caswell*
* *[VMS only]* The header files that the VMS compilers include automatically,
`__DECC_INCLUDE_PROLOGUE.H` and `__DECC_INCLUDE_EPILOGUE.H`, use pragmas
that the C++ compiler doesn't understand. This is a shortcoming in the
compiler, but can be worked around with `__cplusplus` guards.
C++ applications that use OpenSSL libraries must be compiled using the
qualifier `/NAMES=(AS_IS,SHORTENED)` to be able to use all the OpenSSL
functions. Otherwise, only functions with symbols of less than 31
characters can be used, as the linker will not be able to successfully
resolve symbols with longer names.
*Richard Levitte*
* Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY.
The presence of this system service is determined at run-time.
*Richard Levitte*
* Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just
the first value.
*Jon Spillett*
### Changes between 1.1.1c and 1.1.1d [10 Sep 2019]
* Fixed a fork protection issue. OpenSSL 1.1.1 introduced a rewritten random
number generator (RNG). This was intended to include protection in the
event of a fork() system call in order to ensure that the parent and child
processes did not share the same RNG state. However this protection was not
being used in the default case.
A partial mitigation for this issue is that the output from a high
precision timer is mixed into the RNG state so the likelihood of a parent
and child process sharing state is significantly reduced.
If an application already calls OPENSSL_init_crypto() explicitly using
OPENSSL_INIT_ATFORK then this problem does not occur at all.
([CVE-2019-1549])
*Matthias St. Pierre*
* For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters, when loading a encoded key
or calling `EC_GROUP_new_from_ecpkparameters()`/
`EC_GROUP_new_from_ecparameters()`.
This prevents bypass of security hardening and performance gains,
especially for curves with specialized EC_METHODs.
By default, if a key encoded with explicit parameters is loaded and later
encoded, the output is still encoded with explicit parameters, even if
internally a "named" EC_GROUP is used for computation.
*Nicola Tuveri*
* Compute ECC cofactors if not provided during EC_GROUP construction. Before
this change, EC_GROUP_set_generator would accept order and/or cofactor as
NULL. After this change, only the cofactor parameter can be NULL. It also
does some minimal sanity checks on the passed order.
([CVE-2019-1547])
*Billy Bob Brumley*
* Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
An attack is simple, if the first CMS_recipientInfo is valid but the
second CMS_recipientInfo is chosen ciphertext. If the second
recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
encryption key will be replaced by garbage, and the message cannot be
decoded, but if the RSA decryption fails, the correct encryption key is
used and the recipient will not notice the attack.
As a work around for this potential attack the length of the decrypted
key must be equal to the cipher default key length, in case the
certifiate is not given and all recipientInfo are tried out.
The old behaviour can be re-enabled in the CMS code by setting the
CMS_DEBUG_DECRYPT flag.
([CVE-2019-1563])
*Bernd Edlinger*
* Early start up entropy quality from the DEVRANDOM seed source has been
improved for older Linux systems. The RAND subsystem will wait for
/dev/random to be producing output before seeding from /dev/urandom.
The seeded state is stored for future library initialisations using
a system global shared memory segment. The shared memory identifier
can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to
the desired value. The default identifier is 114.
*Paul Dale*
* Correct the extended master secret constant on EBCDIC systems. Without this
fix TLS connections between an EBCDIC system and a non-EBCDIC system that
negotiate EMS will fail. Unfortunately this also means that TLS connections
between EBCDIC systems with this fix, and EBCDIC systems without this
fix will fail if they negotiate EMS.
*Matt Caswell*
* Use Windows installation paths in the mingw builds
Mingw isn't a POSIX environment per se, which means that Windows
paths should be used for installation.
([CVE-2019-1552])
*Richard Levitte*
* Changed DH_check to accept parameters with order q and 2q subgroups.
With order 2q subgroups the bit 0 of the private key is not secret
but DH_generate_key works around that by clearing bit 0 of the
private key for those. This avoids leaking bit 0 of the private key.
*Bernd Edlinger*
* Significantly reduce secure memory usage by the randomness pools.
*Paul Dale*
* Revert the DEVRANDOM_WAIT feature for Linux systems
The DEVRANDOM_WAIT feature added a select() call to wait for the
/dev/random device to become readable before reading from the
/dev/urandom device.
It turned out that this change had negative side effects on
performance which were not acceptable. After some discussion it
was decided to revert this feature and leave it up to the OS
resp. the platform maintainer to ensure a proper initialization
during early boot time.
*Matthias St. Pierre*
### Changes between 1.1.1b and 1.1.1c [28 May 2019]
* Add build tests for C++. These are generated files that only do one
thing, to include one public OpenSSL head file each. This tests that
the public header files can be usefully included in a C++ application.
This test isn't enabled by default. It can be enabled with the option
'enable-buildtest-c++'.
*Richard Levitte*
* Enable SHA3 pre-hashing for ECDSA and DSA.
*Patrick Steuer*
* Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
This changes the size when using the `genpkey` command when no size is given.
It fixes an omission in earlier changes that changed all RSA, DSA and DH
generation commands to use 2048 bits by default.
*Kurt Roeckx*
* Reorganize the manual pages to consistently have RETURN VALUES,
EXAMPLES, SEE ALSO and HISTORY come in that order, and adjust
util/fix-doc-nits accordingly.
*Paul Yang, Joshua Lock*
* Add the missing accessor EVP_PKEY_get0_engine()
*Matt Caswell*
* Have commands like `s_client` and `s_server` output the signature scheme
along with other cipher suite parameters when debugging.
*Lorinczy Zsigmond*
* Make OPENSSL_config() error agnostic again.
*Richard Levitte*
* Do the error handling in RSA decryption constant time.
*Bernd Edlinger*
* Prevent over long nonces in ChaCha20-Poly1305.
ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input
for every encryption operation. RFC 7539 specifies that the nonce value
(IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length
and front pads the nonce with 0 bytes if it is less than 12
bytes. However it also incorrectly allows a nonce to be set of up to 16
bytes. In this case only the last 12 bytes are significant and any
additional leading bytes are ignored.
It is a requirement of using this cipher that nonce values are
unique. Messages encrypted using a reused nonce value are susceptible to
serious confidentiality and integrity attacks. If an application changes
the default nonce length to be longer than 12 bytes and then makes a
change to the leading bytes of the nonce expecting the new value to be a
new unique nonce then such an application could inadvertently encrypt
messages with a reused nonce.
Additionally the ignored bytes in a long nonce are not covered by the
integrity guarantee of this cipher. Any application that relies on the
integrity of these ignored leading bytes of a long nonce may be further
affected. Any OpenSSL internal use of this cipher, including in SSL/TLS,
is safe because no such use sets such a long nonce value. However user
applications that use this cipher directly and set a non-default nonce
length to be longer than 12 bytes may be vulnerable.
This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk
Greef of Ronomon.
([CVE-2019-1543])
*Matt Caswell*
* Add DEVRANDOM_WAIT feature for Linux systems
On older Linux systems where the getrandom() system call is not available,
OpenSSL normally uses the /dev/urandom device for seeding its CSPRNG.
Contrary to getrandom(), the /dev/urandom device will not block during
early boot when the kernel CSPRNG has not been seeded yet.
To mitigate this known weakness, use select() to wait for /dev/random to
become readable before reading from /dev/urandom.
* Ensure that SM2 only uses SM3 as digest algorithm
*Paul Yang*
### Changes between 1.1.1a and 1.1.1b [26 Feb 2019]
* Change the info callback signals for the start and end of a post-handshake
message exchange in TLSv1.3. In 1.1.1/1.1.1a we used SSL_CB_HANDSHAKE_START
and SSL_CB_HANDSHAKE_DONE. Experience has shown that many applications get
confused by this and assume that a TLSv1.2 renegotiation has started. This
can break KeyUpdate handling. Instead we no longer signal the start and end
of a post handshake message exchange (although the messages themselves are
still signalled). This could break some applications that were expecting
the old signals. However without this KeyUpdate is not usable for many
applications.
*Matt Caswell*
### 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*
* 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 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 consistently 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:
- Support for multiple DRBG instances with seed chaining.
- The default RAND method makes use of a DRBG.
- There is a public and private DRBG instance.
- The DRBG instances are fork-safe.
- Keep all global DRBG instances on the secure heap if it is enabled.
- 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.
*Tomáš Mráz <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
prohibits 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 interoperability
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*
OpenSSL 1.1.0
-------------
### Changes between 1.1.0k and 1.1.0l [10 Sep 2019]
* For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters, when loading a encoded key
or calling `EC_GROUP_new_from_ecpkparameters()`/
`EC_GROUP_new_from_ecparameters()`.
This prevents bypass of security hardening and performance gains,
especially for curves with specialized EC_METHODs.
By default, if a key encoded with explicit parameters is loaded and later
encoded, the output is still encoded with explicit parameters, even if
internally a "named" EC_GROUP is used for computation.
*Nicola Tuveri*
* Compute ECC cofactors if not provided during EC_GROUP construction. Before
this change, EC_GROUP_set_generator would accept order and/or cofactor as
NULL. After this change, only the cofactor parameter can be NULL. It also
does some minimal sanity checks on the passed order.
([CVE-2019-1547])
*Billy Bob Brumley*
* Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
An attack is simple, if the first CMS_recipientInfo is valid but the
second CMS_recipientInfo is chosen ciphertext. If the second
recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
encryption key will be replaced by garbage, and the message cannot be
decoded, but if the RSA decryption fails, the correct encryption key is
used and the recipient will not notice the attack.
As a work around for this potential attack the length of the decrypted
key must be equal to the cipher default key length, in case the
certifiate is not given and all recipientInfo are tried out.
The old behaviour can be re-enabled in the CMS code by setting the
CMS_DEBUG_DECRYPT flag.
([CVE-2019-1563])
*Bernd Edlinger*
* Use Windows installation paths in the mingw builds
Mingw isn't a POSIX environment per se, which means that Windows
paths should be used for installation.
([CVE-2019-1552])
*Richard Levitte*
### Changes between 1.1.0j and 1.1.0k [28 May 2019]
* Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
This changes the size when using the `genpkey` command when no size is given.
It fixes an omission in earlier changes that changed all RSA, DSA and DH
generation commands to use 2048 bits by default.
*Kurt Roeckx*
* Prevent over long nonces in ChaCha20-Poly1305.
ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input
for every encryption operation. RFC 7539 specifies that the nonce value
(IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length
and front pads the nonce with 0 bytes if it is less than 12
bytes. However it also incorrectly allows a nonce to be set of up to 16
bytes. In this case only the last 12 bytes are significant and any
additional leading bytes are ignored.
It is a requirement of using this cipher that nonce values are
unique. Messages encrypted using a reused nonce value are susceptible to
serious confidentiality and integrity attacks. If an application changes
the default nonce length to be longer than 12 bytes and then makes a
change to the leading bytes of the nonce expecting the new value to be a
new unique nonce then such an application could inadvertently encrypt
messages with a reused nonce.
Additionally the ignored bytes in a long nonce are not covered by the
integrity guarantee of this cipher. Any application that relies on the
integrity of these ignored leading bytes of a long nonce may be further
affected. Any OpenSSL internal use of this cipher, including in SSL/TLS,
is safe because no such use sets such a long nonce value. However user
applications that use this cipher directly and set a non-default nonce
length to be longer than 12 bytes may be vulnerable.
This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk
Greef of Ronomon.
([CVE-2019-1543])
*Matt Caswell*
* Added SCA hardening for modular field inversion in EC_GROUP through
a new dedicated field_inv() pointer in EC_METHOD.
This also addresses a leakage affecting conversions from projective
to affine coordinates.
*Billy Bob Brumley, Nicola Tuveri*
* Fix a use after free bug in d2i_X509_PUBKEY when overwriting a
re-used X509_PUBKEY object if the second PUBKEY is malformed.
*Bernd Edlinger*
* Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
*Richard Levitte*
* Remove the 'dist' target and add a tarball building script. The
'dist' target has fallen out of use, and it shouldn't be
necessary to configure just to create a source distribution.
*Richard Levitte*
### Changes between 1.1.0i and 1.1.0j [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*
* 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*
### Changes between 1.1.0h and 1.1.0i [14 Aug 2018]
* 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.md](ssl/statem/README.md) 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>*
OpenSSL 1.0.2
-------------
### Changes between 1.0.2s and 1.0.2t [10 Sep 2019]
* For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters, when loading a encoded key
or calling `EC_GROUP_new_from_ecpkparameters()`/
`EC_GROUP_new_from_ecparameters()`.
This prevents bypass of security hardening and performance gains,
especially for curves with specialized EC_METHODs.
By default, if a key encoded with explicit parameters is loaded and later
encoded, the output is still encoded with explicit parameters, even if
internally a "named" EC_GROUP is used for computation.
*Nicola Tuveri*
* Compute ECC cofactors if not provided during EC_GROUP construction. Before
this change, EC_GROUP_set_generator would accept order and/or cofactor as
NULL. After this change, only the cofactor parameter can be NULL. It also
does some minimal sanity checks on the passed order.
([CVE-2019-1547])
*Billy Bob Brumley*
* Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
An attack is simple, if the first CMS_recipientInfo is valid but the
second CMS_recipientInfo is chosen ciphertext. If the second
recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
encryption key will be replaced by garbage, and the message cannot be
decoded, but if the RSA decryption fails, the correct encryption key is
used and the recipient will not notice the attack.
As a work around for this potential attack the length of the decrypted
key must be equal to the cipher default key length, in case the
certifiate is not given and all recipientInfo are tried out.
The old behaviour can be re-enabled in the CMS code by setting the
CMS_DEBUG_DECRYPT flag.
([CVE-2019-1563])
*Bernd Edlinger*
* Document issue with installation paths in diverse Windows builds
'/usr/local/ssl' is an unsafe prefix for location to install OpenSSL
binaries and run-time config file.
([CVE-2019-1552])
*Richard Levitte*
### Changes between 1.0.2r and 1.0.2s [28 May 2019]
* Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
This changes the size when using the `genpkey` command when no size is given.
It fixes an omission in earlier changes that changed all RSA, DSA and DH
generation commands to use 2048 bits by default.
*Kurt Roeckx*
* Add FIPS support for Android Arm 64-bit
Support for Android Arm 64-bit was added to the OpenSSL FIPS Object
Module in Version 2.0.10. For some reason, the corresponding target
'android64-aarch64' was missing OpenSSL 1.0.2, whence it could not be
built with FIPS support on Android Arm 64-bit. This omission has been
fixed.
*Matthias St. Pierre*
### Changes between 1.0.2q and 1.0.2r [26 Feb 2019]
* 0-byte record padding oracle
If an application encounters a fatal protocol error and then calls
SSL_shutdown() twice (once to send a close_notify, and once to receive one)
then OpenSSL can respond differently to the calling application if a 0 byte
record is received with invalid padding compared to if a 0 byte record is
received with an invalid MAC. If the application then behaves differently
based on that in a way that is detectable to the remote peer, then this
amounts to a padding oracle that could be used to decrypt data.
In order for this to be exploitable "non-stitched" ciphersuites must be in
use. Stitched ciphersuites are optimised implementations of certain
commonly used ciphersuites. Also the application must call SSL_shutdown()
twice even if a protocol error has occurred (applications should not do
this but some do anyway).
This issue was discovered by Juraj Somorovsky, Robert Merget and Nimrod
Aviram, with additional investigation by Steven Collison and Andrew
Hourselt. It was reported to OpenSSL on 10th December 2018.
([CVE-2019-1559])
*Matt Caswell*
* Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
*Richard Levitte*
### Changes between 1.0.2p and 1.0.2q [20 Nov 2018]
* Microarchitecture timing vulnerability in ECC scalar multiplication
OpenSSL ECC scalar multiplication, used in e.g. ECDSA and ECDH, has been
shown to be vulnerable to a microarchitecture timing side channel attack.
An attacker with sufficient access to mount local timing attacks during
ECDSA signature generation could recover the private key.
This issue was reported to OpenSSL on 26th October 2018 by Alejandro
Cabrera Aldaya, Billy Brumley, Sohaib ul Hassan, Cesar Pereida Garcia and
Nicola Tuveri.
([CVE-2018-5407])
*Billy Brumley*
* 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*
* Resolve a compatibility issue in EC_GROUP handling with the FIPS Object
Module, accidentally introduced while backporting security fixes from the
development branch and hindering the use of ECC in FIPS mode.
*Nicola Tuveri*
### Changes between 1.0.2o and 1.0.2p [14 Aug 2018]
* 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*
### Changes between 1.0.2n and 1.0.2o [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*
### Changes between 1.0.2m and 1.0.2n [7 Dec 2017]
* Read/write after SSL object in error state
OpenSSL 1.0.2 (starting from version 1.0.2b) introduced an "error state"
mechanism. The intent was that if a fatal error occurred during a handshake
then OpenSSL would move into the error state and would immediately fail if
you attempted to continue the handshake. This works as designed for the
explicit handshake functions (SSL_do_handshake(), SSL_accept() and
SSL_connect()), however due to a bug it does not work correctly if
SSL_read() or SSL_write() is called directly. In that scenario, if the
handshake fails then a fatal error will be returned in the initial function
call. If SSL_read()/SSL_write() is subsequently called by the application
for the same SSL object then it will succeed and the data is passed without
being decrypted/encrypted directly from the SSL/TLS record layer.
In order to exploit this issue an application bug would have to be present
that resulted in a call to SSL_read()/SSL_write() being issued after having
already received a fatal error.
This issue was reported to OpenSSL by David Benjamin (Google).
([CVE-2017-3737])
*Matt Caswell*
* 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.0.2l and 1.0.2m [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.
*Rich Salz*
### Changes between 1.0.2k and 1.0.2l [25 May 2017]
* Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target
platform rather than 'mingw'.
*Richard Levitte*
### Changes between 1.0.2j and 1.0.2k [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*
* 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*
* 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*
* 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*
### Changes between 1.0.2i and 1.0.2j [26 Sep 2016]
* Missing CRL sanity check
A bug fix which included a CRL sanity check was added to OpenSSL 1.1.0
but was omitted from OpenSSL 1.0.2i. As a result any attempt to use
CRLs in OpenSSL 1.0.2i will crash with a null pointer exception.
This issue only affects the OpenSSL 1.0.2i
([CVE-2016-7052])
*Matt Caswell*
### Changes between 1.0.2h and 1.0.2i [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*
* In order to mitigate the SWEET32 attack, the DES ciphers were moved from
HIGH to MEDIUM.
This issue was reported to OpenSSL Karthikeyan Bhargavan and Gaetan
Leurent (INRIA)
([CVE-2016-2183])
*Rich Salz*
* OOB write in MDC2_Update()
An overflow can occur in MDC2_Update() either if called directly or
through the EVP_DigestUpdate() function using MDC2. 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.
The amount of data needed is comparable to SIZE_MAX which is impractical
on most platforms.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-6303])
*Stephen Henson*
* Malformed SHA512 ticket DoS
If a server uses SHA512 for TLS session ticket HMAC it is vulnerable to a
DoS attack where a malformed ticket will result in an OOB read which will
ultimately crash.
The use of SHA512 in TLS session tickets is comparatively rare as it requires
a custom server callback and ticket lookup mechanism.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-6302])
*Stephen Henson*
* OOB write in BN_bn2dec()
The function BN_bn2dec() does not check the return value of BN_div_word().
This can cause an OOB write if an application uses this function with an
overly large BIGNUM. This could be a problem if an overly large certificate
or CRL is printed out from an untrusted source. TLS is not affected because
record limits will reject an oversized certificate before it is parsed.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-2182])
*Stephen Henson*
* OOB read in TS_OBJ_print_bio()
The function TS_OBJ_print_bio() misuses OBJ_obj2txt(): the return value is
the total length the OID text representation would use and not the amount
of data written. This will result in OOB reads when large OIDs are
presented.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-2180])
*Stephen Henson*
* Pointer arithmetic undefined behaviour
Avoid some undefined pointer arithmetic
A common idiom in the codebase is to check limits in the following manner:
"p + len > limit"
Where "p" points to some malloc'd data of SIZE bytes and
limit == p + SIZE
"len" here could be from some externally supplied data (e.g. from a TLS
message).
The rules of C pointer arithmetic are such that "p + len" is only well
defined where len <= SIZE. Therefore the above idiom is actually
undefined behaviour.
For example this could cause problems if some malloc implementation
provides an address for "p" such that "p + len" actually overflows for
values of len that are too big and therefore p + len < limit.
This issue was reported to OpenSSL by Guido Vranken
([CVE-2016-2177])
*Matt Caswell*
* Constant time flag not preserved in DSA signing
Operations in the DSA signing algorithm should run in constant time in
order to avoid side channel attacks. A flaw in the OpenSSL DSA
implementation means that a non-constant time codepath is followed for
certain operations. This has been demonstrated through a cache-timing
attack to be sufficient for an attacker to recover the private DSA key.
This issue was reported by César Pereida (Aalto University), Billy Brumley
(Tampere University of Technology), and Yuval Yarom (The University of
Adelaide and NICTA).
([CVE-2016-2178])
*César Pereida*
* DTLS buffered message DoS
In a DTLS connection where handshake messages are delivered out-of-order
those messages that OpenSSL is not yet ready to process will be buffered
for later use. Under certain circumstances, a flaw in the logic means that
those messages do not get removed from the buffer even though the handshake
has been completed. An attacker could force up to approx. 15 messages to
remain in the buffer when they are no longer required. These messages will
be cleared when the DTLS connection is closed. The default maximum size for
a message is 100k. Therefore the attacker could force an additional 1500k
to be consumed per connection. By opening many simulataneous connections an
attacker could cause a DoS attack through memory exhaustion.
This issue was reported to OpenSSL by Quan Luo.
([CVE-2016-2179])
*Matt Caswell*
* DTLS replay protection DoS
A flaw in the DTLS replay attack protection mechanism means that records
that arrive for future epochs update the replay protection "window" before
the MAC for the record has been validated. This could be exploited by an
attacker by sending a record for the next epoch (which does not have to
decrypt or have a valid MAC), with a very large sequence number. This means
that all subsequent legitimate packets are dropped causing a denial of
service for a specific DTLS connection.
This issue was reported to OpenSSL by the OCAP audit team.
([CVE-2016-2181])
*Matt Caswell*
* Certificate message OOB reads
In OpenSSL 1.0.2 and earlier some missing message length checks can result
in OOB reads of up to 2 bytes beyond an allocated buffer. There is a
theoretical DoS risk but this has not been observed in practice on common
platforms.
The messages affected are client certificate, client certificate request
and server certificate. As a result the attack can only be performed
against a client or a server which enables client authentication.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-6306])
*Stephen Henson*
### 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.
*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` command 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
commands 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.
OpenSSL 1.0.1
-------------
### Changes between 1.0.1t and 1.0.1u [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*
* In order to mitigate the SWEET32 attack, the DES ciphers were moved from
HIGH to MEDIUM.
This issue was reported to OpenSSL Karthikeyan Bhargavan and Gaetan
Leurent (INRIA)
([CVE-2016-2183])
*Rich Salz*
* OOB write in MDC2_Update()
An overflow can occur in MDC2_Update() either if called directly or
through the EVP_DigestUpdate() function using MDC2. 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.
The amount of data needed is comparable to SIZE_MAX which is impractical
on most platforms.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-6303])
*Stephen Henson*
* Malformed SHA512 ticket DoS
If a server uses SHA512 for TLS session ticket HMAC it is vulnerable to a
DoS attack where a malformed ticket will result in an OOB read which will
ultimately crash.
The use of SHA512 in TLS session tickets is comparatively rare as it requires
a custom server callback and ticket lookup mechanism.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-6302])
*Stephen Henson*
* OOB write in BN_bn2dec()
The function BN_bn2dec() does not check the return value of BN_div_word().
This can cause an OOB write if an application uses this function with an
overly large BIGNUM. This could be a problem if an overly large certificate
or CRL is printed out from an untrusted source. TLS is not affected because
record limits will reject an oversized certificate before it is parsed.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-2182])
*Stephen Henson*
* OOB read in TS_OBJ_print_bio()
The function TS_OBJ_print_bio() misuses OBJ_obj2txt(): the return value is
the total length the OID text representation would use and not the amount
of data written. This will result in OOB reads when large OIDs are
presented.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-2180])
*Stephen Henson*
* Pointer arithmetic undefined behaviour
Avoid some undefined pointer arithmetic
A common idiom in the codebase is to check limits in the following manner:
"p + len > limit"
Where "p" points to some malloc'd data of SIZE bytes and
limit == p + SIZE
"len" here could be from some externally supplied data (e.g. from a TLS
message).
The rules of C pointer arithmetic are such that "p + len" is only well
defined where len <= SIZE. Therefore the above idiom is actually
undefined behaviour.
For example this could cause problems if some malloc implementation
provides an address for "p" such that "p + len" actually overflows for
values of len that are too big and therefore p + len < limit.
This issue was reported to OpenSSL by Guido Vranken
([CVE-2016-2177])
*Matt Caswell*
* Constant time flag not preserved in DSA signing
Operations in the DSA signing algorithm should run in constant time in
order to avoid side channel attacks. A flaw in the OpenSSL DSA
implementation means that a non-constant time codepath is followed for
certain operations. This has been demonstrated through a cache-timing
attack to be sufficient for an attacker to recover the private DSA key.
This issue was reported by César Pereida (Aalto University), Billy Brumley
(Tampere University of Technology), and Yuval Yarom (The University of
Adelaide and NICTA).
([CVE-2016-2178])
*César Pereida*
* DTLS buffered message DoS
In a DTLS connection where handshake messages are delivered out-of-order
those messages that OpenSSL is not yet ready to process will be buffered
for later use. Under certain circumstances, a flaw in the logic means that
those messages do not get removed from the buffer even though the handshake
has been completed. An attacker could force up to approx. 15 messages to
remain in the buffer when they are no longer required. These messages will
be cleared when the DTLS connection is closed. The default maximum size for
a message is 100k. Therefore the attacker could force an additional 1500k
to be consumed per connection. By opening many simulataneous connections an
attacker could cause a DoS attack through memory exhaustion.
This issue was reported to OpenSSL by Quan Luo.
([CVE-2016-2179])
*Matt Caswell*
* DTLS replay protection DoS
A flaw in the DTLS replay attack protection mechanism means that records
that arrive for future epochs update the replay protection "window" before
the MAC for the record has been validated. This could be exploited by an
attacker by sending a record for the next epoch (which does not have to
decrypt or have a valid MAC), with a very large sequence number. This means
that all subsequent legitimate packets are dropped causing a denial of
service for a specific DTLS connection.
This issue was reported to OpenSSL by the OCAP audit team.
([CVE-2016-2181])
*Matt Caswell*
* Certificate message OOB reads
In OpenSSL 1.0.2 and earlier some missing message length checks can result
in OOB reads of up to 2 bytes beyond an allocated buffer. There is a
theoretical DoS risk but this has not been observed in practice on common
platforms.
The messages affected are client certificate, client certificate request
and server certificate. As a result the attack can only be performed
against a client or a server which enables client authentication.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
([CVE-2016-6306])
*Stephen Henson*
### Changes between 1.0.1s and 1.0.1t [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 primarly 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 casuse 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.1r and 1.0.1s [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 command 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
commands to use 2048 bits by default.
*Emilia Käsper*
### Changes between 1.0.1q and 1.0.1r [28 Jan 2016]
* Protection for DH small subgroup attacks
As a precautionary measure the SSL_OP_SINGLE_DH_USE option has been
switched on by default and cannot be disabled. This could have some
performance impact.
*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*
* Reject DH handshakes with parameters shorter than 1024 bits.
*Kurt Roeckx*
### Changes between 1.0.1p and 1.0.1q [3 Dec 2015]
* 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,
use a random seed, as already documented.
*Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>*
### Changes between 1.0.1o and 1.0.1p [9 Jul 2015]
* Alternate chains certificate forgery
During certificate verfification, 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).
([CVE-2015-1793])
*Matt Caswell*
* Race condition handling PSK identify hint
If PSK identity hints are received by a multi-threaded client then
the values are wrongly updated in the parent SSL_CTX structure. This can
result in a race condition potentially leading to a double free of the
identify hint data.
([CVE-2015-3196])
*Stephen Henson*
### Changes between 1.0.1n and 1.0.1o [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.
### Changes between 1.0.1m and 1.0.1n [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*
* Reject DH handshakes with parameters shorter than 768 bits.
*Kurt Roeckx and Emilia Kasper*
* dhparam: generate 2048-bit parameters by default.
*Kurt Roeckx and Emilia Kasper*
### Changes between 1.0.1l and 1.0.1m [19 Mar 2015]
* 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*
* 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*
* 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.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 instead 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*
OpenSSL 1.0.0
-------------
### Changes between 1.0.0s and 1.0.0t [3 Dec 2015]
* 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*
* Race condition handling PSK identify hint
If PSK identity hints are received by a multi-threaded client then
the values are wrongly updated in the parent SSL_CTX structure. This can
result in a race condition potentially leading to a double free of the
identify hint data.
([CVE-2015-3196])
*Stephen Henson*
### Changes between 1.0.0r and 1.0.0s [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*
### Changes between 1.0.0q and 1.0.0r [19 Mar 2015]
* 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*
* 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*
* 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.0p and 1.0.0q [15 Jan 2015]
* Build fixes for the Windows and OpenVMS platforms
*Matt Caswell and Richard Levitte*
### Changes between 1.0.0o and 1.0.0p [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*
* 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*
* 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.
Reencode 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*
### Changes between 1.0.0n and 1.0.0o [15 Oct 2014]
* 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.
Reencode 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.0m and 1.0.0n [6 Aug 2014]
* 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 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.0l and 1.0.0m [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>*
* 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*
### Changes between 1.0.0k and 1.0.0l [6 Jan 2014]
* 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.0j and 1.0.0k [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*
* Return an error when checking OCSP signatures when key is NULL.
This fixes a DoS attack. ([CVE-2013-0166])
*Steve Henson*
* 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>.
(This is a backport)
*Rob Stradling <rob.stradling@comodo.com>*
* Fix possible deadlock when decoding public keys.
*Steve Henson*
### Changes between 1.0.0i and 1.0.0j [10 May 2012]
[NB: OpenSSL 1.0.0i and later 1.0.0 patch levels were released after
OpenSSL 1.0.1.]
* Sanity check record length before skipping explicit IV in 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*
### Changes between 1.0.0h and 1.0.0i [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*
### 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 commands 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*
OpenSSL 0.9.x
-------------
### 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` commands.
*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 its
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.md](crypto/engine/README.md)
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.md](README-Engine.md)).
*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.md](README-Engine.md) 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:
crypt
pe 8 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
s-cbc 4408.85k 5560.51k 5778.46k 5862.20k 5825.16k
s-cbc 4389.55k 5571.17k 5792.23k 5846.91k 5832.11k
s-cbc 4394.32k 5575.92k 5807.44k 5848.37k 5841.30k
crypt
s-cbc 3482.66k 5069.49k 5496.39k 5614.16k 5639.28k
s-cbc 3480.74k 5068.76k 5510.34k 5609.87k 5635.52k
s-cbc 3483.72k 5067.62k 5504.60k 5708.01k 5724.80k
After:
crypt
s-cbc 4660.16k 5650.19k 5807.19k 5827.13k 5783.32k
crypt
s-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 commands 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 w.rt. 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, outputted 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*
<!--
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*
-->
* 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 its 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
specifically 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 [crypto/objects/README.md](crypto/objects/README.md).
- 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 with the exception of the
first that must be a `CONF *` instead of a `LHASH *`.
To make it easier 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 ASN1_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*
* DES CBC did not update the IV. Weird.
*Ben Laurie*
lse
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.
ndif
* 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 embedded
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 every time: 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 is 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 commands. 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:
- 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` command working and add it to the `list` command. 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 an 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>*
<!-- Links -->
+[CVE-2024-13176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-13176
+[CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
[CVE-2024-6119]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-6119
[CVE-2024-5535]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-5535
[CVE-2024-4741]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-4741
[CVE-2024-4603]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-4603
[CVE-2024-2511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-2511
[CVE-2024-0727]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-0727
[CVE-2023-6237]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6237
[CVE-2023-6129]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6129
[CVE-2023-5678]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-5678
[CVE-2023-5363]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-5363
[CVE-2023-4807]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-4807
[CVE-2023-3817]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-3817
[CVE-2023-3446]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-3446
[CVE-2023-2975]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-2975
[RFC 2578 (STD 58), section 3.5]: https://datatracker.ietf.org/doc/html/rfc2578#section-3.5
[CVE-2023-2650]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-2650
[CVE-2023-1255]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-1255
[CVE-2023-0466]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0466
[CVE-2023-0465]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0465
[CVE-2023-0464]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0464
[CVE-2023-0401]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0401
[CVE-2023-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0286
[CVE-2023-0217]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0217
[CVE-2023-0216]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0216
[CVE-2023-0215]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0215
[CVE-2022-4450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4450
[CVE-2022-4304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4304
[CVE-2022-4203]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4203
[CVE-2022-3996]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-3996
[CVE-2022-2274]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274
[CVE-2022-2097]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2097
[CVE-2020-1971]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1971
[CVE-2020-1967]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1967
[CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563
[CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559
[CVE-2019-1552]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1552
[CVE-2019-1551]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1551
[CVE-2019-1549]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1549
[CVE-2019-1547]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1547
[CVE-2019-1543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1543
[CVE-2018-5407]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-5407
[CVE-2018-0739]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0739
[CVE-2018-0737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0737
[CVE-2018-0735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0735
[CVE-2018-0734]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0734
[CVE-2018-0733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0733
[CVE-2018-0732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0732
[CVE-2017-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3738
[CVE-2017-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3737
[CVE-2017-3736]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3736
[CVE-2017-3735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3735
[CVE-2017-3733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3733
[CVE-2017-3732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3732
[CVE-2017-3731]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3731
[CVE-2017-3730]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3730
[CVE-2016-7055]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7055
[CVE-2016-7054]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7054
[CVE-2016-7053]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7053
[CVE-2016-7052]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7052
[CVE-2016-6309]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6309
[CVE-2016-6308]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6308
[CVE-2016-6307]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6307
[CVE-2016-6306]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6306
[CVE-2016-6305]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6305
[CVE-2016-6304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6304
[CVE-2016-6303]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6303
[CVE-2016-6302]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6302
[CVE-2016-2183]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2183
[CVE-2016-2182]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2182
[CVE-2016-2181]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2181
[CVE-2016-2180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2180
[CVE-2016-2179]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2179
[CVE-2016-2178]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2178
[CVE-2016-2177]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2177
[CVE-2016-2176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2176
[CVE-2016-2109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2109
[CVE-2016-2107]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2107
[CVE-2016-2106]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2106
[CVE-2016-2105]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2105
[CVE-2016-0800]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0800
[CVE-2016-0799]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0799
[CVE-2016-0798]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0798
[CVE-2016-0797]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0797
[CVE-2016-0705]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0705
[CVE-2016-0702]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0702
[CVE-2016-0701]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0701
[CVE-2015-3197]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3197
[CVE-2015-3196]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3196
[CVE-2015-3195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3195
[CVE-2015-3194]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3194
[CVE-2015-3193]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3193
[CVE-2015-1793]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1793
[CVE-2015-1792]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1792
[CVE-2015-1791]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1791
[CVE-2015-1790]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1790
[CVE-2015-1789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1789
[CVE-2015-1788]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1788
[CVE-2015-1787]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1787
[CVE-2015-0293]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0293
[CVE-2015-0291]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0291
[CVE-2015-0290]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0290
[CVE-2015-0289]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0289
[CVE-2015-0288]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0288
[CVE-2015-0287]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0287
[CVE-2015-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0286
[CVE-2015-0285]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0285
[CVE-2015-0209]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0209
[CVE-2015-0208]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0208
[CVE-2015-0207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0207
[CVE-2015-0206]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0206
[CVE-2015-0205]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0205
[CVE-2015-0204]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0204
[CVE-2014-8275]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-8275
[CVE-2014-5139]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-5139
[CVE-2014-3572]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3572
[CVE-2014-3571]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3571
[CVE-2014-3570]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3570
[CVE-2014-3569]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3569
[CVE-2014-3568]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3568
[CVE-2014-3567]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3567
[CVE-2014-3566]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3566
[CVE-2014-3513]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3513
[CVE-2014-3512]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3512
[CVE-2014-3511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3511
[CVE-2014-3510]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3510
[CVE-2014-3509]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3509
[CVE-2014-3508]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3508
[CVE-2014-3507]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3507
[CVE-2014-3506]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3506
[CVE-2014-3505]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3505
[CVE-2014-3470]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3470
[CVE-2014-0224]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0224
[CVE-2014-0221]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0221
[CVE-2014-0195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0195
[CVE-2014-0160]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0160
[CVE-2014-0076]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0076
[CVE-2013-6450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6450
[CVE-2013-4353]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-4353
[CVE-2013-0169]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0169
[CVE-2013-0166]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0166
[CVE-2012-2686]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2686
[CVE-2012-2333]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2333
[CVE-2012-2110]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2110
[CVE-2012-0884]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0884
[CVE-2012-0050]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0050
[CVE-2012-0027]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0027
[CVE-2011-4619]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4619
[CVE-2011-4577]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4577
[CVE-2011-4576]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4576
[CVE-2011-4109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4109
[CVE-2011-4108]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4108
[CVE-2011-3210]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3210
[CVE-2011-3207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3207
[CVE-2011-0014]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-0014
[CVE-2010-4252]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4252
[CVE-2010-4180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4180
[CVE-2010-3864]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-3864
[CVE-2010-1633]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-1633
[CVE-2010-0740]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0740
[CVE-2010-0433]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0433
[CVE-2009-4355]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-4355
[CVE-2009-3555]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3555
[CVE-2009-3245]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3245
[CVE-2009-1386]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1386
[CVE-2009-1379]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1379
[CVE-2009-1378]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1378
[CVE-2009-1377]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1377
[CVE-2009-0789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0789
[CVE-2009-0591]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0591
[CVE-2009-0590]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0590
[CVE-2008-5077]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-5077
[CVE-2008-1678]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-1678
[CVE-2008-1672]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-1672
[CVE-2008-0891]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-0891
[CVE-2007-5135]: https://www.openssl.org/news/vulnerabilities.html#CVE-2007-5135
[CVE-2007-4995]: https://www.openssl.org/news/vulnerabilities.html#CVE-2007-4995
[CVE-2006-4343]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4343
[CVE-2006-4339]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4339
[CVE-2006-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-3738
[CVE-2006-2940]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2940
[CVE-2006-2937]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2937
[CVE-2005-2969]: https://www.openssl.org/news/vulnerabilities.html#CVE-2005-2969
[CVE-2004-0112]: https://www.openssl.org/news/vulnerabilities.html#CVE-2004-0112
[CVE-2004-0079]: https://www.openssl.org/news/vulnerabilities.html#CVE-2004-0079
[CVE-2003-0851]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0851
[CVE-2003-0545]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0545
[CVE-2003-0544]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0544
[CVE-2003-0543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0543
[CVE-2003-0078]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0078
[CVE-2002-0659]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0659
[CVE-2002-0657]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0657
[CVE-2002-0656]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0656
[CVE-2002-0655]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0655
diff --git a/crypto/openssl/Configurations/unix-Makefile.tmpl b/crypto/openssl/Configurations/unix-Makefile.tmpl
index 644540397de5..d2b0797a7edf 100644
--- a/crypto/openssl/Configurations/unix-Makefile.tmpl
+++ b/crypto/openssl/Configurations/unix-Makefile.tmpl
@@ -1,1996 +1,1996 @@
##
## Makefile for OpenSSL
##
## {- join("\n## ", @autowarntext) -}
{-
use OpenSSL::Util;
our $makedep_scheme = $config{makedep_scheme};
our $makedepcmd = platform->makedepcmd();
sub windowsdll { $config{target} =~ /^(?:Cygwin|mingw)/ }
# Shared AIX support is special. We put libcrypto[64].so.ver into
# libcrypto.a and use libcrypto_a.a as static one.
sub sharedaix { !$disabled{shared} && $config{target} =~ /^aix/ }
our $sover_dirname = platform->shlib_version_as_filename();
# This makes sure things get built in the order they need
# to. You're welcome.
sub dependmagic {
my $target = shift;
return "$target: build_generated\n\t\"\$(MAKE)\" depend && \"\$(MAKE)\" _$target\n_$target";
}
our $COLUMNS = $ENV{COLUMNS};
if ($COLUMNS =~ /^\d+$/) {
$COLUMNS = int($COLUMNS) - 2; # 2 to leave space for ending ' \'
} else {
$COLUMNS = 76;
}
sub fill_lines {
my $item_sep = shift; # string
my $line_length = shift; # number of chars
my @result = ();
my $resultpos = 0;
foreach (@_) {
my $fill_line = $result[$resultpos] // '';
my $newline =
($fill_line eq '' ? '' : $fill_line . $item_sep) . $_;
if (length($newline) > $line_length) {
# If this is a single item and the intended result line
# is empty, we put it there anyway
if ($fill_line eq '') {
$result[$resultpos++] = $newline;
} else {
$result[++$resultpos] = $_;
}
} else {
$result[$resultpos] = $newline;
}
}
return @result;
}
'';
-}
PLATFORM={- $config{target} -}
OPTIONS={- $config{options} -}
CONFIGURE_ARGS=({- join(", ",quotify_l(@{$config{perlargv}})) -})
SRCDIR={- $config{sourcedir} -}
BLDDIR={- $config{builddir} -}
FIPSKEY={- $config{FIPSKEY} -}
VERSION={- "$config{full_version}" -}
VERSION_NUMBER={- "$config{version}" -}
MAJOR={- $config{major} -}
MINOR={- $config{minor} -}
SHLIB_VERSION_NUMBER={- $config{shlib_version} -}
SHLIB_TARGET={- $target{shared_target} -}
LIBS={- join(" \\\n" . ' ' x 5,
fill_lines(" ", $COLUMNS - 5,
map { platform->staticlib($_) // () }
@{$unified_info{libraries}})) -}
SHLIBS={- join(" \\\n" . ' ' x 7,
fill_lines(" ", $COLUMNS - 7,
map { platform->sharedlib($_) // () }
@{$unified_info{libraries}})) -}
SHLIB_INFO={- join(" \\\n" . ' ' x 11,
fill_lines(" ", $COLUMNS - 11,
map { my $x = platform->sharedlib($_);
my $y = platform->sharedlib_simple($_) // '';
my $z = platform->sharedlib_import($_) // '';
$x ? "\"$x;$y;$z\"" : () }
@{$unified_info{libraries}})) -}
MODULES={- join(" \\\n" . ' ' x 8,
fill_lines(" ", $COLUMNS - 8,
map { platform->dso($_) }
# Drop all modules that are dependencies, they will
# be processed through their dependents
grep { my $x = $_;
!grep { grep { $_ eq $x } @$_ }
values %{$unified_info{depends}} }
@{$unified_info{modules}})) -}
FIPSMODULE={- # We do some extra checking here, as there should be only one
use File::Basename;
our @fipsmodules =
grep { !$unified_info{attributes}->{modules}->{$_}->{noinst}
&& $unified_info{attributes}->{modules}->{$_}->{fips} }
@{$unified_info{modules}};
die "More that one FIPS module" if scalar @fipsmodules > 1;
join(" ", map { platform->dso($_) } @fipsmodules) -}
FIPSMODULENAME={- die "More that one FIPS module" if scalar @fipsmodules > 1;
join(" ", map { basename(platform->dso($_)) } @fipsmodules) -}
PROGRAMS={- join(" \\\n" . ' ' x 9,
fill_lines(" ", $COLUMNS - 9,
map { platform->bin($_) }
@{$unified_info{programs}})) -}
SCRIPTS={- join(" \\\n" . ' ' x 8,
fill_lines(" ", $COLUMNS - 8, @{$unified_info{scripts}})) -}
{- output_off() if $disabled{makedepend}; "" -}
DEPS={- join(" \\\n" . ' ' x 5,
fill_lines(" ", $COLUMNS - 5,
map { platform->isobj($_) ? platform->dep($_) : () }
grep { $unified_info{sources}->{$_}->[0] =~ /\.c$/ }
keys %{$unified_info{sources}})); -}
{- output_on() if $disabled{makedepend}; "" -}
GENERATED_MANDATORY={- join(" \\\n" . ' ' x 20,
fill_lines(" ", $COLUMNS - 20,
@{$unified_info{depends}->{""}})) -}
GENERATED_PODS={- # common0.tmpl provides @generated
join(" \\\n" . ' ' x 15,
fill_lines(" ", $COLUMNS - 15,
map { my $x = $_;
(
grep {
$unified_info{attributes}->{depends}
->{$x}->{$_}->{pod} // 0
}
keys %{$unified_info{attributes}->{depends}->{$x}}
) ? $x : ();
}
@generated)) -}
GENERATED={- # common0.tmpl provides @generated
join(" \\\n" . ' ' x 5,
fill_lines(" ", $COLUMNS - 5,
map { platform->convertext($_) } @generated )) -}
INSTALL_LIBS={-
join(" \\\n" . ' ' x 13,
fill_lines(" ", $COLUMNS - 13,
map { platform->staticlib($_) // () }
grep { !$unified_info{attributes}->{libraries}->{$_}->{noinst} }
@{$unified_info{libraries}}))
-}
INSTALL_SHLIBS={-
join(" \\\n" . ' ' x 15,
fill_lines(" ", $COLUMNS - 15,
map { platform->sharedlib($_) // () }
grep { !$unified_info{attributes}->{libraries}->{$_}->{noinst} }
@{$unified_info{libraries}}))
-}
INSTALL_SHLIB_INFO={-
join(" \\\n" . ' ' x 19,
fill_lines(" ", $COLUMNS - 19,
map { my $x = platform->sharedlib($_);
my $y = platform->sharedlib_simple($_) // '';
my $z = platform->sharedlib_import($_) // '';
$x ? "\"$x;$y;$z\"" : () }
grep { !$unified_info{attributes}->{libraries}->{$_}->{noinst} }
@{$unified_info{libraries}}))
-}
INSTALL_ENGINES={-
join(" \\\n" . ' ' x 16,
fill_lines(" ", $COLUMNS - 16,
map { platform->dso($_) }
grep { !$unified_info{attributes}->{modules}->{$_}->{noinst}
&& $unified_info{attributes}->{modules}->{$_}->{engine} }
@{$unified_info{modules}}))
-}
INSTALL_MODULES={-
join(" \\\n" . ' ' x 16,
fill_lines(" ", $COLUMNS - 16,
map { platform->dso($_) }
grep { !$unified_info{attributes}->{modules}->{$_}->{noinst}
&& !$unified_info{attributes}->{modules}->{$_}->{engine}
&& !$unified_info{attributes}->{modules}->{$_}->{fips} }
@{$unified_info{modules}}))
-}
INSTALL_FIPSMODULE={-
join(" \\\n" . ' ' x 16,
fill_lines(" ", $COLUMNS - 16,
map { platform->dso($_) }
grep { !$unified_info{attributes}->{modules}->{$_}->{noinst}
&& $unified_info{attributes}->{modules}->{$_}->{fips} }
@{$unified_info{modules}}))
-}
INSTALL_FIPSMODULECONF=providers/fipsmodule.cnf
INSTALL_PROGRAMS={-
join(" \\\n" . ' ' x 16,
fill_lines(" ", $COLUMNS - 16, map { platform->bin($_) }
grep { !$unified_info{attributes}->{programs}->{$_}->{noinst} }
@{$unified_info{programs}}))
-}
BIN_SCRIPTS={-
join(" \\\n" . ' ' x 12,
fill_lines(" ", $COLUMNS - 12,
map { my $x = $unified_info{attributes}->{scripts}->{$_}->{linkname};
$x ? "$_:$x" : $_ }
grep { !$unified_info{attributes}->{scripts}->{$_}->{noinst}
&& !$unified_info{attributes}->{scripts}->{$_}->{misc} }
@{$unified_info{scripts}}))
-}
MISC_SCRIPTS={-
join(" \\\n" . ' ' x 13,
fill_lines(" ", $COLUMNS - 13,
map { my $x = $unified_info{attributes}->{scripts}->{$_}->{linkname};
$x ? "$_:$x" : $_ }
grep { !$unified_info{attributes}->{scripts}->{$_}->{noinst}
&& $unified_info{attributes}->{scripts}->{$_}->{misc} }
@{$unified_info{scripts}}))
-}
IMAGEDOCS1={-
join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$unified_info{imagedocs}->{man1}})) -}
IMAGEDOCS3={-
join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$unified_info{imagedocs}->{man3}})) -}
IMAGEDOCS5={-
join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$unified_info{imagedocs}->{man5}})) -}
IMAGEDOCS7={-
join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$unified_info{imagedocs}->{man7}})) -}
HTMLDOCS1={-
join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$unified_info{htmldocs}->{man1}})) -}
HTMLDOCS3={-
join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$unified_info{htmldocs}->{man3}})) -}
HTMLDOCS5={-
join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$unified_info{htmldocs}->{man5}})) -}
HTMLDOCS7={-
join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$unified_info{htmldocs}->{man7}})) -}
MANDOCS1={-
join(" \\\n" . ' ' x 9,
fill_lines(" ", $COLUMNS - 9,
@{$unified_info{mandocs}->{man1}})) -}
MANDOCS3={-
join(" \\\n" . ' ' x 9,
fill_lines(" ", $COLUMNS - 9,
@{$unified_info{mandocs}->{man3}})) -}
MANDOCS5={-
join(" \\\n" . ' ' x 9,
fill_lines(" ", $COLUMNS - 9,
@{$unified_info{mandocs}->{man5}})) -}
MANDOCS7={-
join(" \\\n" . ' ' x 9,
fill_lines(" ", $COLUMNS - 9,
@{$unified_info{mandocs}->{man7}})) -}
APPS_OPENSSL="{- use File::Spec::Functions;
catfile("apps","openssl") -}"
# DESTDIR is for package builders so that they can configure for, say,
# /usr/ and yet have everything installed to /tmp/somedir/usr/.
# Normally it is left empty.
DESTDIR=
# Do not edit these manually. Use Configure with --prefix or --openssldir
# to change this! Short explanation in the top comment in Configure
INSTALLTOP={- # $prefix is used in the OPENSSLDIR perl snippet
#
our $prefix = $config{prefix} || "/usr/local";
$prefix -}
OPENSSLDIR={- #
# The logic here is that if no --openssldir was given,
# OPENSSLDIR will get the value from $prefix plus "/ssl".
# If --openssldir was given and the value is an absolute
# path, OPENSSLDIR will get its value without change.
# If the value from --openssldir is a relative path,
# OPENSSLDIR will get $prefix with the --openssldir
# value appended as a subdirectory.
#
use File::Spec::Functions;
our $openssldir =
$config{openssldir} ?
(file_name_is_absolute($config{openssldir}) ?
$config{openssldir}
: catdir($prefix, $config{openssldir}))
: catdir($prefix, "ssl");
$openssldir -}
LIBDIR={- our $libdir = $config{libdir};
unless ($libdir) {
$libdir = "lib$target{multilib}";
}
file_name_is_absolute($libdir) ? "" : $libdir -}
# $(libdir) is chosen to be compatible with the GNU coding standards
libdir={- file_name_is_absolute($libdir)
? $libdir : '$(INSTALLTOP)/$(LIBDIR)' -}
ENGINESDIR=$(libdir)/engines-{- $sover_dirname -}
MODULESDIR=$(libdir)/ossl-modules
# Convenience variable for those who want to set the rpath in shared
# libraries and applications
LIBRPATH=$(libdir)
MANDIR=$(INSTALLTOP)/share/man
DOCDIR=$(INSTALLTOP)/share/doc/$(BASENAME)
HTMLDIR=$(DOCDIR)/html
# MANSUFFIX is for the benefit of anyone who may want to have a suffix
# appended after the manpage file section number. "ssl" is popular,
# resulting in files such as config.5ssl rather than config.5.
MANSUFFIX=ossl
HTMLSUFFIX=html
# For "optional" echo messages, to get "real" silence
ECHO = echo
##### User defined commands and flags ################################
# We let the C compiler driver to take care of .s files. This is done in
# order to be excused from maintaining a separate set of architecture
# dependent assembler flags. E.g. if you throw -mcpu=ultrasparc at SPARC
# gcc, then the driver will automatically translate it to -xarch=v8plus
# and pass it down to assembler. In any case, we do not define AS or
# ASFLAGS for this reason.
CROSS_COMPILE={- $config{CROSS_COMPILE} -}
CC=$(CROSS_COMPILE){- $config{CC} -}
CXX={- $config{CXX} ? "\$(CROSS_COMPILE)$config{CXX}" : '' -}
CPPFLAGS={- our $cppflags1 = join(" ",
(map { "-D".$_} @{$config{CPPDEFINES}}),
(map { "-I".$_} @{$config{CPPINCLUDES}}),
@{$config{CPPFLAGS}}) -}
CFLAGS={- join(' ', @{$config{CFLAGS}}) -}
CXXFLAGS={- join(' ', @{$config{CXXFLAGS}}) -}
LDFLAGS= {- join(' ', @{$config{LDFLAGS}}) -}
EX_LIBS= {- join(' ', @{$config{LDLIBS}}) -}
MAKEDEPEND={- $config{makedepcmd} -}
PERL={- $config{PERL} -}
AR=$(CROSS_COMPILE){- $config{AR} -}
ARFLAGS= {- join(' ', @{$config{ARFLAGS}}) -}
RANLIB={- $config{RANLIB} ? "\$(CROSS_COMPILE)$config{RANLIB}" : "true"; -}
RC= $(CROSS_COMPILE){- $config{RC} -}
RCFLAGS={- join(' ', @{$config{RCFLAGS}}) -} {- $target{shared_rcflag} -}
RM= rm -f
RMDIR= rmdir
TAR= {- $target{TAR} || "tar" -}
TARFLAGS= {- $target{TARFLAGS} -}
BASENAME= openssl
NAME= $(BASENAME)-$(VERSION)
# Relative to $(SRCDIR)
TARFILE= ../$(NAME).tar
##### Project flags ##################################################
# Variables starting with CNF_ are common variables for all product types
CNF_CPPFLAGS={- our $cppflags2 =
join(' ', $target{cppflags} || (),
(map { "-D".$_} @{$target{defines}},
@{$config{defines}}),
(map { "-I".$_} @{$target{includes}},
@{$config{includes}}),
@{$config{cppflags}}) -}
CNF_CFLAGS={- join(' ', $target{cflags} || (),
@{$config{cflags}}) -}
CNF_CXXFLAGS={- join(' ', $target{cxxflags} || (),
@{$config{cxxflags}}) -}
CNF_LDFLAGS={- join(' ', $target{lflags} || (),
@{$config{lflags}}) -}
CNF_EX_LIBS={- join(' ', $target{ex_libs} || (),
@{$config{ex_libs}}) -}
# Variables starting with LIB_ are used to build library object files
# and shared libraries.
# Variables starting with DSO_ are used to build DSOs and their object files.
# Variables starting with BIN_ are used to build programs and their object
# files.
LIB_CPPFLAGS={- our $lib_cppflags =
join(' ', $target{lib_cppflags} || (),
$target{shared_cppflag} || (),
(map { '-D'.$_ }
@{$target{lib_defines} || ()},
@{$target{shared_defines} || ()},
@{$config{lib_defines} || ()},
@{$config{shared_defines} || ()}),
(map { '-I'.quotify1($_) }
@{$target{lib_includes}},
@{$target{shared_includes}},
@{$config{lib_includes}},
@{$config{shared_includes}}),
@{$config{lib_cppflags}},
@{$config{shared_cppflag}});
join(' ', $lib_cppflags,
(map { '-D'.$_ }
'OPENSSLDIR="\"$(OPENSSLDIR)\""',
'ENGINESDIR="\"$(ENGINESDIR)\""',
'MODULESDIR="\"$(MODULESDIR)\""'),
'$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -}
LIB_CFLAGS={- join(' ', $target{lib_cflags} || (),
$target{shared_cflag} || (),
@{$config{lib_cflags}},
@{$config{shared_cflag}},
'$(CNF_CFLAGS)', '$(CFLAGS)') -}
LIB_CXXFLAGS={- join(' ', $target{lib_cxxflags} || (),
$target{shared_cxxflag} || (),
@{$config{lib_cxxflags}},
@{$config{shared_cxxflag}},
'$(CNF_CXXFLAGS)', '$(CXXFLAGS)') -}
LIB_LDFLAGS={- join(' ', $target{shared_ldflag} || (),
$config{shared_ldflag} || (),
'$(CNF_LDFLAGS)', '$(LDFLAGS)') -}
LIB_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS)
DSO_CPPFLAGS={- join(' ', $target{dso_cppflags} || (),
$target{module_cppflags} || (),
(map { '-D'.$_ }
@{$target{dso_defines}},
@{$target{module_defines}},
@{$config{dso_defines} || ()},
@{$config{module_defines} || ()}),
(map { '-I'.quotify1($_) }
@{$target{dso_includes}},
@{$target{module_includes}},
@{$config{dso_includes}},
@{$config{module_includes}}),
@{$config{dso_cppflags}},
@{$config{module_cppflags}},
'$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -}
DSO_CFLAGS={- join(' ', $target{dso_cflags} || (),
$target{module_cflags} || (),
@{$config{dso_cflags}},
@{$config{module_cflags}},
'$(CNF_CFLAGS)', '$(CFLAGS)') -}
DSO_CXXFLAGS={- join(' ', $target{dso_cxxflags} || (),
$target{module_cxxflags} || (),
@{$config{dso_cxxflags}},
@{$config{module_cxxflag}},
'$(CNF_CXXFLAGS)', '$(CXXFLAGS)') -}
DSO_LDFLAGS={- join(' ', $target{dso_ldflags} || (),
$target{module_ldflags} || (),
@{$config{dso_ldflags}},
@{$config{module_ldflags}},
'$(CNF_LDFLAGS)', '$(LDFLAGS)') -}
DSO_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS)
BIN_CPPFLAGS={- join(' ', $target{bin_cppflags} || (),
(map { '-D'.$_ } @{$config{bin_defines} || ()}),
@{$config{bin_cppflags}},
'$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -}
BIN_CFLAGS={- join(' ', $target{bin_cflags} || (),
@{$config{bin_cflags}},
'$(CNF_CFLAGS)', '$(CFLAGS)') -}
BIN_CXXFLAGS={- join(' ', $target{bin_cxxflags} || (),
@{$config{bin_cxxflags}},
'$(CNF_CXXFLAGS)', '$(CXXFLAGS)') -}
BIN_LDFLAGS={- join(' ', $target{bin_lflags} || (),
@{$config{bin_lflags}},
'$(CNF_LDFLAGS)', '$(LDFLAGS)') -}
BIN_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS)
# CPPFLAGS_Q is used for one thing only: to build up buildinf.h
CPPFLAGS_Q={- $cppflags1 =~ s|([\\"])|\\$1|g;
$cppflags2 =~ s|([\\"])|\\$1|g;
$lib_cppflags =~ s|([\\"])|\\$1|g;
join(' ', $lib_cppflags || (), $cppflags2 || (),
$cppflags1 || ()) -}
PERLASM_SCHEME= {- $target{perlasm_scheme} -}
# For x86 assembler: Set PROCESSOR to 386 if you want to support
# the 80386.
PROCESSOR= {- $config{processor} -}
# We want error [and other] messages in English. Trouble is that make(1)
# doesn't pass macros down as environment variables unless there already
# was corresponding variable originally set. In other words we can only
# reassign environment variables, but not set new ones, not in portable
# manner that is. That's why we reassign several, just to be sure...
LC_ALL=C
LC_MESSAGES=C
LANG=C
# The main targets ###################################################
{- dependmagic('build_sw'); -}: build_libs_nodep build_modules_nodep build_programs_nodep link-utils
{- dependmagic('build_libs'); -}: build_libs_nodep
{- dependmagic('build_modules'); -}: build_modules_nodep
{- dependmagic('build_programs'); -}: build_programs_nodep
build_generated_pods: $(GENERATED_PODS)
build_docs: build_man_docs build_html_docs
build_man_docs: $(MANDOCS1) $(MANDOCS3) $(MANDOCS5) $(MANDOCS7)
build_html_docs: $(HTMLDOCS1) $(HTMLDOCS3) $(HTMLDOCS5) $(HTMLDOCS7)
build_generated: $(GENERATED_MANDATORY)
build_libs_nodep: libcrypto.pc libssl.pc openssl.pc
build_modules_nodep: $(MODULES)
build_programs_nodep: $(PROGRAMS) $(SCRIPTS)
# Kept around for backward compatibility
build_apps build_tests: build_programs
# Convenience target to prebuild all generated files, not just the mandatory
# ones
build_all_generated: $(GENERATED_MANDATORY) $(GENERATED) build_docs
@ : {- output_off() if $disabled{makedepend}; "" -}
@echo "Warning: consider configuring with no-makedepend, because if"
@echo " target system doesn't have $(PERL),"
@echo " then make will fail..."
@ : {- output_on() if $disabled{makedepend}; "" -}
all: build_sw build_docs
test: tests
{- dependmagic('tests'); -}: build_programs_nodep build_modules_nodep link-utils
"$(MAKE)" run_tests
run_tests: FORCE
@ : {- output_off() if $disabled{tests}; "" -}
( SRCTOP=$(SRCDIR) \
BLDTOP=$(BLDDIR) \
PERL="$(PERL)" \
FIPSKEY="$(FIPSKEY)" \
EXE_EXT={- platform->binext() -} \
$(PERL) $(SRCDIR)/test/run_tests.pl $(TESTS) )
@ : {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}
@echo "Tests are not supported with your chosen Configure options"
@ : {- output_on() if !$disabled{tests}; "" -}
list-tests:
@ : {- output_off() if $disabled{tests}; "" -}
"$(MAKE)" run_tests TESTS=list
@ : {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}
@echo "Tests are not supported with your chosen Configure options"
@ : {- output_on() if !$disabled{tests}; "" -}
install: install_sw install_ssldirs install_docs {- $disabled{fips} ? "" : "install_fips" -}
uninstall: uninstall_docs uninstall_sw {- $disabled{fips} ? "" : "uninstall_fips" -}
libclean:
@set -e; for s in $(SHLIB_INFO); do \
if [ "$$s" = ";" ]; then continue; fi; \
s1=`echo "$$s" | cut -f1 -d";"`; \
s2=`echo "$$s" | cut -f2 -d";"`; \
s3=`echo "$$s" | cut -f3 -d";"`; \
$(ECHO) $(RM) $$s1; {- output_off() unless windowsdll(); "" -}\
$(RM) apps/$$s1; \
$(RM) test/$$s1; \
$(RM) fuzz/$$s1; {- output_on() unless windowsdll(); "" -}\
$(RM) $$s1; \
if [ "$$s2" != "" ]; then \
$(ECHO) $(RM) $$s2; \
$(RM) $$s2; \
fi; \
if [ "$$s3" != "" ]; then \
$(ECHO) $(RM) $$s3; \
$(RM) $$s3; \
fi; \
done
$(RM) $(LIBS)
$(RM) *{- platform->defext() -}
clean: libclean
$(RM) $(HTMLDOCS1)
$(RM) $(HTMLDOCS3)
$(RM) $(HTMLDOCS5)
$(RM) $(HTMLDOCS7)
$(RM) $(MANDOCS1)
$(RM) $(MANDOCS3)
$(RM) $(MANDOCS5)
$(RM) $(MANDOCS7)
$(RM) $(PROGRAMS) $(TESTPROGS) $(MODULES) $(FIPSMODULE) $(SCRIPTS)
$(RM) $(GENERATED_MANDATORY) $(GENERATED)
-find . -name '*{- platform->depext() -}' \! -name '.*' \! -type d -exec $(RM) {} \;
-find . -name '*{- platform->objext() -}' \! -name '.*' \! -type d -exec $(RM) {} \;
$(RM) core
$(RM) tags TAGS doc-nits md-nits
$(RM) -r test/test-runs
$(RM) providers/fips*.new
$(RM) openssl.pc libcrypto.pc libssl.pc
-find . -type l \! -name '.*' -exec $(RM) {} \;
distclean: clean
$(RM) include/openssl/configuration.h
$(RM) configdata.pm
$(RM) Makefile
# We check if any depfile is newer than Makefile and decide to
# concatenate only if that is true.
depend: Makefile
@: {- output_off() if $disabled{makedepend}; "" -}
@$(PERL) $(SRCDIR)/util/add-depends.pl "{- $makedep_scheme -}"
@: {- output_on() if $disabled{makedepend}; "" -}
# Install helper targets #############################################
install_sw: install_dev install_engines install_modules install_runtime
uninstall_sw: uninstall_runtime uninstall_modules uninstall_engines uninstall_dev
install_docs: install_man_docs install_html_docs
uninstall_docs: uninstall_man_docs uninstall_html_docs
$(RM) -r "$(DESTDIR)$(DOCDIR)"
{- output_off() if $disabled{fips}; "" -}
install_fips: build_sw $(INSTALL_FIPSMODULECONF)
@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MODULESDIR)"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(OPENSSLDIR)"
@$(ECHO) "*** Installing FIPS module"
@$(ECHO) "install $(INSTALL_FIPSMODULE) -> $(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME)"
@cp "$(INSTALL_FIPSMODULE)" "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new"
@chmod 755 "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new"
@mv -f "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new" \
"$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME)"
@$(ECHO) "*** Installing FIPS module configuration"
@$(ECHO) "install $(INSTALL_FIPSMODULECONF) -> $(DESTDIR)$(OPENSSLDIR)/fipsmodule.cnf"
@cp $(INSTALL_FIPSMODULECONF) "$(DESTDIR)$(OPENSSLDIR)/fipsmodule.cnf"
uninstall_fips:
@$(ECHO) "*** Uninstalling FIPS module configuration"
$(RM) "$(DESTDIR)$(OPENSSLDIR)/fipsmodule.cnf"
@$(ECHO) "*** Uninstalling FIPS module"
$(RM) "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME)"
{- if ($disabled{fips}) { output_on(); } else { output_off(); } "" -}
install_fips:
@$(ECHO) "The 'install_fips' target requires the 'enable-fips' option"
uninstall_fips:
@$(ECHO) "The 'uninstall_fips' target requires the 'enable-fips' option"
{- output_on() if !$disabled{fips}; "" -}
install_ssldirs:
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(OPENSSLDIR)/certs"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(OPENSSLDIR)/private"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(OPENSSLDIR)/misc"
@set -e; for x in dummy $(MISC_SCRIPTS); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
x1=`echo "$$x" | cut -f1 -d:`; \
x2=`echo "$$x" | cut -f2 -d:`; \
fn=`basename $$x1`; \
$(ECHO) "install $$x1 -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \
cp $$x1 "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new"; \
chmod 755 "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new"; \
mv -f "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new" \
"$(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \
if [ "$$x1" != "$$x2" ]; then \
ln=`basename "$$x2"`; \
: {- output_off() unless windowsdll(); "" -}; \
$(ECHO) "copy $(DESTDIR)$(OPENSSLDIR)/misc/$$ln -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \
cp "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn" "$(DESTDIR)$(OPENSSLDIR)/misc/$$ln"; \
: {- output_on() unless windowsdll();
output_off() if windowsdll(); "" -}; \
$(ECHO) "link $(DESTDIR)$(OPENSSLDIR)/misc/$$ln -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \
ln -sf $$fn "$(DESTDIR)$(OPENSSLDIR)/misc/$$ln"; \
: {- output_on() if windowsdll(); "" -}; \
fi; \
done
@$(ECHO) "install $(SRCDIR)/apps/openssl.cnf -> $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.dist"
@cp $(SRCDIR)/apps/openssl.cnf "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new"
@chmod 644 "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new"
@mv -f "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new" "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf.dist"
@if [ ! -f "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf" ]; then \
$(ECHO) "install $(SRCDIR)/apps/openssl.cnf -> $(DESTDIR)$(OPENSSLDIR)/openssl.cnf"; \
cp $(SRCDIR)/apps/openssl.cnf "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf"; \
chmod 644 "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf"; \
fi
@$(ECHO) "install $(SRCDIR)/apps/ct_log_list.cnf -> $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.dist"
@cp $(SRCDIR)/apps/ct_log_list.cnf "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new"
@chmod 644 "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new"
@mv -f "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new" "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.dist"
@if [ ! -f "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf" ]; then \
$(ECHO) "install $(SRCDIR)/apps/ct_log_list.cnf -> $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf"; \
cp $(SRCDIR)/apps/ct_log_list.cnf "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf"; \
chmod 644 "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf"; \
fi
install_dev: install_runtime_libs
@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
@$(ECHO) "*** Installing development files"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(INSTALLTOP)/include/openssl"
@ : {- output_off() if $disabled{uplink}; "" -}
@$(ECHO) "install $(SRCDIR)/ms/applink.c -> $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
@cp $(SRCDIR)/ms/applink.c "$(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
@chmod 644 "$(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
@ : {- output_on() if $disabled{uplink}; "" -}
@set -e; for i in $(SRCDIR)/include/openssl/*.h \
$(BLDDIR)/include/openssl/*.h; do \
fn=`basename $$i`; \
$(ECHO) "install $$i -> $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
cp $$i "$(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
chmod 644 "$(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
done
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)"
@set -e; for l in $(INSTALL_LIBS); do \
fn=`basename $$l`; \
$(ECHO) "install $$l -> $(DESTDIR)$(libdir)/$$fn"; \
cp $$l "$(DESTDIR)$(libdir)/$$fn.new"; \
$(RANLIB) "$(DESTDIR)$(libdir)/$$fn.new"; \
chmod 644 "$(DESTDIR)$(libdir)/$$fn.new"; \
mv -f "$(DESTDIR)$(libdir)/$$fn.new" \
"$(DESTDIR)$(libdir)/$$fn"; \
done
@ : {- output_off() if $disabled{shared}; "" -}
@set -e; for s in $(INSTALL_SHLIB_INFO); do \
s1=`echo "$$s" | cut -f1 -d";"`; \
s2=`echo "$$s" | cut -f2 -d";"`; \
s3=`echo "$$s" | cut -f3 -d";"`; \
fn1=`basename "$$s1"`; \
fn2=`basename "$$s2"`; \
fn3=`basename "$$s3"`; \
: {- output_off(); output_on() unless windowsdll() or sharedaix(); "" -}; \
if [ "$$fn2" != "" ]; then \
$(ECHO) "link $(DESTDIR)$(libdir)/$$fn2 -> $(DESTDIR)$(libdir)/$$fn1"; \
ln -sf $$fn1 "$(DESTDIR)$(libdir)/$$fn2"; \
fi; \
: {- output_off() unless windowsdll() or sharedaix(); output_on() if windowsdll(); "" -}; \
if [ "$$fn3" != "" ]; then \
$(ECHO) "install $$s3 -> $(DESTDIR)$(libdir)/$$fn3"; \
cp $$s3 "$(DESTDIR)$(libdir)/$$fn3.new"; \
chmod 755 "$(DESTDIR)$(libdir)/$$fn3.new"; \
mv -f "$(DESTDIR)$(libdir)/$$fn3.new" \
"$(DESTDIR)$(libdir)/$$fn3"; \
fi; \
: {- output_off() if windowsdll(); output_on() if sharedaix(); "" -}; \
a="$(DESTDIR)$(libdir)/$$fn2"; \
$(ECHO) "install $$s1 -> $$a"; \
if [ -f $$a ]; then ( trap "rm -rf /tmp/ar.$$$$" INT 0; \
mkdir /tmp/ar.$$$$; ( cd /tmp/ar.$$$$; \
cp -f $$a $$a.new; \
for so in `$(AR) t $$a`; do \
$(AR) x $$a $$so; \
chmod u+w $$so; \
strip -X32_64 -e $$so; \
$(AR) r $$a.new $$so; \
done; \
)); fi; \
$(AR) r $$a.new $$s1; \
mv -f $$a.new $$a; \
: {- output_off() if sharedaix(); output_on(); "" -}; \
done
@ : {- output_on() if $disabled{shared}; "" -}
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)/pkgconfig"
@$(ECHO) "install libcrypto.pc -> $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
@cp libcrypto.pc "$(DESTDIR)$(libdir)/pkgconfig"
@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
@$(ECHO) "install libssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
@cp libssl.pc "$(DESTDIR)$(libdir)/pkgconfig"
@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
@$(ECHO) "install openssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
@cp openssl.pc "$(DESTDIR)$(libdir)/pkgconfig"
@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
uninstall_dev: uninstall_runtime_libs
@$(ECHO) "*** Uninstalling development files"
@ : {- output_off() if $disabled{uplink}; "" -}
@$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
@$(RM) "$(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
@ : {- output_on() if $disabled{uplink}; "" -}
@set -e; for i in $(SRCDIR)/include/openssl/*.h \
$(BLDDIR)/include/openssl/*.h; do \
fn=`basename $$i`; \
$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
$(RM) "$(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
done
-$(RMDIR) "$(DESTDIR)$(INSTALLTOP)/include/openssl"
-$(RMDIR) "$(DESTDIR)$(INSTALLTOP)/include"
@set -e; for l in $(INSTALL_LIBS); do \
fn=`basename $$l`; \
$(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn"; \
$(RM) "$(DESTDIR)$(libdir)/$$fn"; \
done
@ : {- output_off() if $disabled{shared}; "" -}
@set -e; for s in $(INSTALL_SHLIB_INFO); do \
s1=`echo "$$s" | cut -f1 -d";"`; \
s2=`echo "$$s" | cut -f2 -d";"`; \
s3=`echo "$$s" | cut -f3 -d";"`; \
fn1=`basename "$$s1"`; \
fn2=`basename "$$s2"`; \
fn3=`basename "$$s3"`; \
: {- output_off() if windowsdll(); "" -}; \
$(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn1"; \
$(RM) "$(DESTDIR)$(libdir)/$$fn1"; \
if [ -n "$$fn2" ]; then \
$(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn2"; \
$(RM) "$(DESTDIR)$(libdir)/$$fn2"; \
fi; \
: {- output_on() if windowsdll(); "" -}{- output_off() unless windowsdll(); "" -}; \
if [ -n "$$fn3" ]; then \
$(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn3"; \
$(RM) "$(DESTDIR)$(libdir)/$$fn3"; \
fi; \
: {- output_on() unless windowsdll(); "" -}; \
done
@ : {- output_on() if $disabled{shared}; "" -}
$(RM) "$(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
$(RM) "$(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
$(RM) "$(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
-$(RMDIR) "$(DESTDIR)$(libdir)/pkgconfig"
-$(RMDIR) "$(DESTDIR)$(libdir)"
_install_modules_deps: install_runtime_libs build_modules
install_engines: _install_modules_deps
@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(ENGINESDIR)/"
@$(ECHO) "*** Installing engines"
@set -e; for e in dummy $(INSTALL_ENGINES); do \
if [ "$$e" = "dummy" ]; then continue; fi; \
fn=`basename $$e`; \
$(ECHO) "install $$e -> $(DESTDIR)$(ENGINESDIR)/$$fn"; \
cp $$e "$(DESTDIR)$(ENGINESDIR)/$$fn.new"; \
chmod 755 "$(DESTDIR)$(ENGINESDIR)/$$fn.new"; \
mv -f "$(DESTDIR)$(ENGINESDIR)/$$fn.new" \
"$(DESTDIR)$(ENGINESDIR)/$$fn"; \
done
uninstall_engines:
@$(ECHO) "*** Uninstalling engines"
@set -e; for e in dummy $(INSTALL_ENGINES); do \
if [ "$$e" = "dummy" ]; then continue; fi; \
fn=`basename $$e`; \
$(ECHO) "$(RM) $(DESTDIR)$(ENGINESDIR)/$$fn"; \
$(RM) "$(DESTDIR)$(ENGINESDIR)/$$fn"; \
done
-$(RMDIR) "$(DESTDIR)$(ENGINESDIR)"
install_modules: _install_modules_deps
@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MODULESDIR)/"
@$(ECHO) "*** Installing modules"
@set -e; for e in dummy $(INSTALL_MODULES); do \
if [ "$$e" = "dummy" ]; then continue; fi; \
fn=`basename $$e`; \
$(ECHO) "install $$e -> $(DESTDIR)$(MODULESDIR)/$$fn"; \
cp $$e "$(DESTDIR)$(MODULESDIR)/$$fn.new"; \
chmod 755 "$(DESTDIR)$(MODULESDIR)/$$fn.new"; \
mv -f "$(DESTDIR)$(MODULESDIR)/$$fn.new" \
"$(DESTDIR)$(MODULESDIR)/$$fn"; \
done
uninstall_modules:
@$(ECHO) "*** Uninstalling modules"
@set -e; for e in dummy $(INSTALL_MODULES); do \
if [ "$$e" = "dummy" ]; then continue; fi; \
fn=`basename $$e`; \
$(ECHO) "$(RM) $(DESTDIR)$(MODULESDIR)/$$fn"; \
$(RM) "$(DESTDIR)$(MODULESDIR)/$$fn"; \
done
-$(RMDIR) "$(DESTDIR)$(MODULESDIR)"
install_runtime: install_programs
install_runtime_libs: build_libs
@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
@ : {- output_off() if windowsdll(); "" -}
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)"
@ : {- output_on() if windowsdll(); output_off() unless windowsdll(); "" -}
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(INSTALLTOP)/bin"
@ : {- output_on() unless windowsdll(); "" -}
@$(ECHO) "*** Installing runtime libraries"
@set -e; for s in dummy $(INSTALL_SHLIBS); do \
if [ "$$s" = "dummy" ]; then continue; fi; \
fn=`basename $$s`; \
: {- output_off() unless windowsdll(); "" -}; \
$(ECHO) "install $$s -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
cp $$s "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \
"$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
: {- output_on() unless windowsdll(); "" -}{- output_off() if windowsdll(); "" -}; \
$(ECHO) "install $$s -> $(DESTDIR)$(libdir)/$$fn"; \
cp $$s "$(DESTDIR)$(libdir)/$$fn.new"; \
chmod 755 "$(DESTDIR)$(libdir)/$$fn.new"; \
mv -f "$(DESTDIR)$(libdir)/$$fn.new" \
"$(DESTDIR)$(libdir)/$$fn"; \
: {- output_on() if windowsdll(); "" -}; \
done
install_programs: install_runtime_libs build_programs
@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(INSTALLTOP)/bin"
@$(ECHO) "*** Installing runtime programs"
@set -e; for x in dummy $(INSTALL_PROGRAMS); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
cp $$x "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \
"$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
done
@set -e; for x in dummy $(BIN_SCRIPTS); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
cp $$x "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \
"$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
done
uninstall_runtime: uninstall_programs uninstall_runtime_libs
uninstall_programs:
@$(ECHO) "*** Uninstalling runtime programs"
@set -e; for x in dummy $(INSTALL_PROGRAMS); \
do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
$(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
done;
@set -e; for x in dummy $(BIN_SCRIPTS); \
do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
$(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
done
-$(RMDIR) "$(DESTDIR)$(INSTALLTOP)/bin"
uninstall_runtime_libs:
@$(ECHO) "*** Uninstalling runtime libraries"
@ : {- output_off() unless windowsdll(); "" -}
@set -e; for s in dummy $(INSTALL_SHLIBS); do \
if [ "$$s" = "dummy" ]; then continue; fi; \
fn=`basename $$s`; \
$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
$(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
done
@ : {- output_on() unless windowsdll(); "" -}
install_man_docs: build_man_docs
@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MANDIR)/man1"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MANDIR)/man3"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MANDIR)/man5"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MANDIR)/man7"
@$(ECHO) "*** Installing manpages"
@set -e; for x in dummy $(MANDOCS1); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
cp $$x "$(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
chmod 644 "$(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man1 $(BLDDIR)/doc/man1 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man1"; \
done
@set -e; for x in dummy $(MANDOCS3); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
cp $$x "$(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
chmod 644 "$(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man3 $(BLDDIR)/doc/man3 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man3"; \
done
@set -e; for x in dummy $(MANDOCS5); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
cp $$x "$(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
chmod 644 "$(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man5 $(BLDDIR)/doc/man5 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man5"; \
done
@set -e; for x in dummy $(MANDOCS7); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
cp $$x "$(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
chmod 644 "$(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man7 $(BLDDIR)/doc/man7 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man7"; \
done
uninstall_man_docs: build_man_docs
@$(ECHO) "*** Uninstalling manpages"
@set -e; for x in dummy $(MANDOCS1); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
$(RM) "$(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man1 $(BLDDIR)/doc/man1 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man1"; \
done
@set -e; for x in dummy $(MANDOCS3); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
$(RM) "$(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man3 $(BLDDIR)/doc/man3 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man3"; \
done
@set -e; for x in dummy $(MANDOCS5); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
$(RM) "$(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man5 $(BLDDIR)/doc/man5 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man5"; \
done
@set -e; for x in dummy $(MANDOCS7); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
$(RM) "$(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man7 $(BLDDIR)/doc/man7 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man7"; \
done
install_html_docs: install_image_docs build_html_docs
@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man1"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man3"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man5"
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man7"
@$(ECHO) "*** Installing HTML manpages"
@set -e; for x in dummy $(HTMLDOCS1); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
cp $$x "$(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
chmod 644 "$(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
done
@set -e; for x in dummy $(HTMLDOCS3); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
cp $$x "$(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
chmod 644 "$(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
done
@set -e; for x in dummy $(HTMLDOCS5); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
cp $$x "$(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
chmod 644 "$(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
done
@set -e; for x in dummy $(HTMLDOCS7); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
cp $$x "$(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
chmod 644 "$(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
done
uninstall_html_docs: uninstall_image_docs
@$(ECHO) "*** Uninstalling HTML manpages"
@set -e; for x in dummy $(HTMLDOCS1); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
$(RM) "$(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
done
@set -e; for x in dummy $(HTMLDOCS3); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
$(RM) "$(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
done
@set -e; for x in dummy $(HTMLDOCS5); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
$(RM) "$(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
done
@set -e; for x in dummy $(HTMLDOCS7); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
$(RM) "$(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
done
install_image_docs:
@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man7/img"
@set -e; for x in dummy $(IMAGEDOCS7); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
cp $(SRCDIR)/$$x "$(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
chmod 644 "$(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
done
uninstall_image_docs:
@set -e; for x in dummy $(IMAGEDOCS7); do \
if [ "$$x" = "dummy" ]; then continue; fi; \
fn=`basename $$x`; \
$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
$(RM) "$(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
done
# Developer targets (note: these are only available on Unix) #########
# It's important that generate_buildinfo comes after ordinals, as ordinals
# is sensitive to build.info changes.
update: generate errors ordinals generate_buildinfo
generate: generate_apps generate_crypto_bn generate_crypto_objects \
generate_crypto_conf generate_crypto_asn1 generate_fuzz_oids
generate_buildinfo: generate_doc_buildinfo
.PHONY: doc-nits md-nits
doc-nits: build_generated_pods
$(PERL) $(SRCDIR)/util/find-doc-nits -c -n -l -e
# This uses "mdl", the markdownlint application, which is written in ruby.
# The source is at https://github.com/markdownlint/markdownlint
# If you have ruby installed, "gem install mdl" should work.
# Another option is at https://snapcraft.io/install/mdl/debian
# Finally, there's a Node.js version, which we haven't tried, that
# can be found at https://github.com/DavidAnson/markdownlint
md-nits:
mdl -s util/markdownlint.rb .
# Test coverage is a good idea for the future
#coverage: $(PROGRAMS) $(TESTPROGRAMS)
# ...
lint:
lint -DLINT $(INCLUDES) $(SRCS)
generate_apps:
( cd $(SRCDIR); $(PERL) VMS/VMSify-conf.pl \
< apps/openssl.cnf > apps/openssl-vms.cnf )
generate_crypto_bn:
( cd $(SRCDIR); $(PERL) crypto/bn/bn_prime.pl > crypto/bn/bn_prime.h )
generate_crypto_objects:
( cd $(SRCDIR); $(PERL) crypto/objects/objects.pl -n \
crypto/objects/objects.txt \
crypto/objects/obj_mac.num \
> crypto/objects/obj_mac.new && \
mv crypto/objects/obj_mac.new crypto/objects/obj_mac.num )
( cd $(SRCDIR); $(PERL) crypto/objects/objects.pl \
crypto/objects/objects.txt \
crypto/objects/obj_mac.num \
> include/openssl/obj_mac.h )
( cd $(SRCDIR); $(PERL) crypto/objects/obj_dat.pl \
include/openssl/obj_mac.h \
> crypto/objects/obj_dat.h )
( cd $(SRCDIR); $(PERL) crypto/objects/objxref.pl \
crypto/objects/obj_mac.num \
crypto/objects/obj_xref.txt \
> crypto/objects/obj_xref.h )
( cd $(SRCDIR); sed -e '1,8d' crypto/objects/obj_compat.h >> include/openssl/obj_mac.h )
generate_crypto_conf:
( cd $(SRCDIR); $(PERL) crypto/conf/keysets.pl \
> crypto/conf/conf_def.h )
generate_crypto_asn1:
( cd $(SRCDIR); $(PERL) crypto/asn1/charmap.pl \
> crypto/asn1/charmap.h )
generate_fuzz_oids:
( cd $(SRCDIR); $(PERL) fuzz/mkfuzzoids.pl \
crypto/objects/obj_dat.h \
> fuzz/oids.txt )
generate_doc_buildinfo:
( $(PERL) -I$(BLDDIR) -Mconfigdata \
$(SRCDIR)/util/dofile.pl -o Makefile \
$(SRCDIR)/doc/build.info.in \
> $(SRCDIR)/doc/build.info.new; \
if ( test -e $(SRCDIR)/doc/build.info \
&& cmp $(SRCDIR)/doc/build.info.new $(SRCDIR)/doc/build.info \
> /dev/null ); \
then \
rm $(SRCDIR)/doc/build.info.new; \
else \
mv $(SRCDIR)/doc/build.info.new $(SRCDIR)/doc/build.info; \
fi )
generate_fips_sources: providers/fips.module.sources.new
providers/fips.module.sources.new: configdata.pm
rm -rf sources-tmp
mkdir sources-tmp
( \
srcdir=`cd $(SRCDIR); pwd`; \
cd sources-tmp \
&& $$srcdir/Configure --banner=Configured enable-fips -O0 \
&& ./configdata.pm --query 'get_sources("providers/fips")' > sources1 \
&& "$(MAKE)" -sj 4 build_generated providers/fips.so \
&& find . -name '*.d' | xargs cat > dep1 \
&& "$(MAKE)" distclean \
&& $$srcdir/Configure --banner=Configured enable-fips no-asm -O0 \
&& ./configdata.pm --query 'get_sources("providers/fips")' > sources2 \
&& "$(MAKE)" -sj 4 build_generated providers/fips.so \
&& find . -name '*.d' | xargs cat > dep2 \
&& cat sources1 sources2 \
| grep -v ' : \\$$' | grep -v util/providers.num \
| sed -e 's/^ *//' -e 's/ *\\$$//' \
| sort | uniq > sources \
&& cat dep1 dep2 \
| $(PERL) -p -e 's/\\\n//' \
| sed -e 's/^.*: *//' -e 's/ */ /g' \
| fgrep -f sources \
| tr ' ' '\n' \
| sort | uniq > deps.raw \
&& cat deps.raw \
| xargs ./configdata.pm --query 'get_sources(@ARGV)' \
| $(PERL) -p -e 's/\\\n//' \
| sed -e 's/\./\\\./g' -e 's/ : */:/' -e 's/^/s:/' -e 's/$$/:/' \
> deps.sed \
&& cat deps.raw | sed -f deps.sed > deps \
)
( \
cat sources-tmp/sources sources-tmp/deps \
| $(PERL) -p -e 's:^ *\Q../\E:: ;' \
-e 's:^\Q$(SRCDIR)/\E:: if "$(SRCDIR)" ne "." ;' \
-e 'my $$x; do { $$x = $$_; s:(^|/)((?!\Q../\E)[^/]*/)\Q..\E($$|/):$$1: } while ($$x ne $$_) ;' ; \
cd $(SRCDIR); \
for x in crypto/bn/asm/*.pl crypto/bn/asm/*.S \
crypto/aes/asm/*.pl crypto/aes/asm/*.S \
crypto/ec/asm/*.pl \
crypto/modes/asm/*.pl \
crypto/sha/asm/*.pl \
crypto/*cpuid.pl crypto/*cpuid.S \
crypto/*cap.c; do \
echo "$$x"; \
done \
) | sort | uniq > providers/fips.module.sources.new
rm -rf sources-tmp
# Set to -force to force a rebuild
ERROR_REBUILD=
errors:
( b=`pwd`; set -e; cd $(SRCDIR); \
$(PERL) util/ck_errf.pl -strict -internal; \
$(PERL) -I$$b util/mkerr.pl $(ERROR_REBUILD) -internal )
( b=`pwd`; set -e; cd $(SRCDIR)/engines; \
for E in *.ec ; do \
$(PERL) ../util/ck_errf.pl -strict \
-conf $$E `basename $$E .ec`.c; \
$(PERL) -I$$b ../util/mkerr.pl $(ERROR_REBUILD) -static \
-conf $$E `basename $$E .ec`.c ; \
done )
{- use File::Basename;
my @sslheaders_tmpl =
qw( include/openssl/ssl.h
include/openssl/ssl2.h
include/openssl/ssl3.h
include/openssl/sslerr.h
include/openssl/tls1.h
include/openssl/dtls1.h
include/openssl/srtp.h
include/openssl/sslerr_legacy.h );
my @cryptoheaders_tmpl =
qw( include/internal/dso.h
include/internal/o_dir.h
include/internal/err.h
include/internal/evp.h
include/internal/pem.h
include/internal/asn1.h
include/internal/sslconf.h );
my @cryptoskipheaders = ( @sslheaders_tmpl,
qw( include/openssl/conf_api.h
include/openssl/ebcdic.h
include/openssl/opensslconf.h
include/openssl/symhacks.h ) );
our %cryptoheaders = ();
our %sslheaders = ();
foreach my $d ( qw( include/openssl include/internal ) ) {
my @header_patterns =
map { catfile($config{sourcedir}, $d, $_) } ( '*.h', '*.h.in' );
foreach my $f ( map { glob($_) } @header_patterns ) {
my $base = basename($f);
my $base_in = basename($f, '.in');
my $dir = catfile($config{sourcedir}, $d);
if ($base ne $base_in) {
# We have a .h.in file, which means the header file is in the
# build tree.
$base = $base_in;
$dir = catfile($config{builddir}, $d);
}
my $new_f = catfile($dir, $base);
my $fn = "$d/$base";
# The logic to add files to @cryptoheaders is a bit complex. The
# file to be added must be either in the public header directory
# or one of the pre-declared internal headers, and must under no
# circumstances be one of those that must be skipped.
$cryptoheaders{$new_f} = 1
if (($d eq 'include/openssl'
|| ( grep { $_ eq $fn } @cryptoheaders_tmpl ))
&& !( grep { $_ eq $fn } @cryptoskipheaders ));
# The logic to add files to @sslheaders is much simpler...
$sslheaders{$new_f} = 1 if grep { $_ eq $fn } @sslheaders_tmpl;
}
}
"";
-}
CRYPTOHEADERS={- join(" \\\n" . ' ' x 14,
fill_lines(" ", $COLUMNS - 14, sort keys %cryptoheaders)) -}
SSLHEADERS={- join(" \\\n" . ' ' x 11,
fill_lines(" ", $COLUMNS - 11, sort keys %sslheaders)) -}
renumber: build_generated
$(PERL) $(SRCDIR)/util/mknum.pl --version $(VERSION_NUMBER) --no-warnings \
--ordinals $(SRCDIR)/util/libcrypto.num \
--symhacks $(SRCDIR)/include/openssl/symhacks.h \
--renumber \
$(CRYPTOHEADERS)
$(PERL) $(SRCDIR)/util/mknum.pl --version $(VERSION_NUMBER) --no-warnings \
--ordinals $(SRCDIR)/util/libssl.num \
--symhacks $(SRCDIR)/include/openssl/symhacks.h \
--renumber \
$(SSLHEADERS)
ordinals: build_generated
$(PERL) $(SRCDIR)/util/mknum.pl --version $(VERSION_NUMBER) --no-warnings \
--ordinals $(SRCDIR)/util/libcrypto.num \
--symhacks $(SRCDIR)/include/openssl/symhacks.h \
$(CRYPTOHEADERS)
$(PERL) $(SRCDIR)/util/mknum.pl --version $(VERSION_NUMBER) --no-warnings \
--ordinals $(SRCDIR)/util/libssl.num \
--symhacks $(SRCDIR)/include/openssl/symhacks.h \
$(SSLHEADERS)
test_ordinals:
"$(MAKE)" run_tests TESTS=test_ordinals
tags TAGS: FORCE
rm -f TAGS tags
-ctags -R .
-etags `find . -name '*.[ch]' -o -name '*.pm'`
providers/fips.checksum.new: providers/fips.module.sources.new
@which unifdef > /dev/null || \
( echo >&2 "ERROR: unifdef not in your \$$PATH, FIPS checksums not calculated"; \
false )
( sources=`pwd`/providers/fips.module.sources.new; \
cd $(SRCDIR) \
&& cat $$sources \
| xargs ./util/fips-checksums.sh ) \
> providers/fips-sources.checksums.new \
&& sha256sum providers/fips-sources.checksums.new \
| sed -e 's|\.new||' > providers/fips.checksum.new
fips-checksums: providers/fips.checksum.new
$(SRCDIR)/providers/fips.checksum: providers/fips.checksum.new
cp -p providers/fips.module.sources.new $(SRCDIR)/providers/fips.module.sources
cp -p providers/fips-sources.checksums.new $(SRCDIR)/providers/fips-sources.checksums
cp -p providers/fips.checksum.new $(SRCDIR)/providers/fips.checksum
update-fips-checksums: $(SRCDIR)/providers/fips.checksum
diff-fips-checksums: fips-checksums
diff -u $(SRCDIR)/providers/fips.module.sources providers/fips.module.sources.new
diff -u $(SRCDIR)/providers/fips-sources.checksums providers/fips-sources.checksums.new
diff -u $(SRCDIR)/providers/fips.checksum providers/fips.checksum.new
# Release targets (note: only available on Unix) #####################
tar:
(cd $(SRCDIR); ./util/mktar.sh --name='$(NAME)' --tarfile='$(TARFILE)')
# Helper targets #####################################################
link-utils: $(BLDDIR)/util/opensslwrap.sh $(BLDDIR)/apps/openssl.cnf
$(BLDDIR)/util/opensslwrap.sh: Makefile
@if [ "$(SRCDIR)" != "$(BLDDIR)" ]; then \
mkdir -p "$(BLDDIR)/util"; \
ln -sf "../$(SRCDIR)/util/`basename "$@"`" "$(BLDDIR)/util"; \
fi
$(BLDDIR)/apps/openssl.cnf: Makefile
@if [ "$(SRCDIR)" != "$(BLDDIR)" ]; then \
mkdir -p "$(BLDDIR)/apps"; \
ln -sf "../$(SRCDIR)/apps/`basename "$@"`" "$(BLDDIR)/apps"; \
fi
FORCE:
# Building targets ###################################################
libcrypto.pc libssl.pc openssl.pc: Makefile $(LIBS) {- join(" ",map { platform->sharedlib_simple($_) // platform->sharedlib_import($_) // platform->sharedlib($_) // () } @{$unified_info{libraries}}) -}
libcrypto.pc:
@ ( echo 'prefix=$(INSTALLTOP)'; \
echo 'exec_prefix=$${prefix}'; \
if [ -n "$(LIBDIR)" ]; then \
echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \
else \
echo 'libdir=$(libdir)'; \
fi; \
echo 'includedir=$${prefix}/include'; \
echo 'enginesdir=$${libdir}/engines-{- $sover_dirname -}'; \
echo 'modulesdir=$${libdir}/ossl-modules'; \
echo ''; \
echo 'Name: OpenSSL-libcrypto'; \
echo 'Description: OpenSSL cryptography library'; \
echo 'Version: '$(VERSION); \
echo 'Libs: -L$${libdir} -lcrypto'; \
echo 'Libs.private: $(LIB_EX_LIBS)'; \
echo 'Cflags: -I$${includedir}' ) > libcrypto.pc
libssl.pc:
@ ( echo 'prefix=$(INSTALLTOP)'; \
echo 'exec_prefix=$${prefix}'; \
if [ -n "$(LIBDIR)" ]; then \
echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \
else \
echo 'libdir=$(libdir)'; \
fi; \
echo 'includedir=$${prefix}/include'; \
echo ''; \
echo 'Name: OpenSSL-libssl'; \
echo 'Description: Secure Sockets Layer and cryptography libraries'; \
echo 'Version: '$(VERSION); \
echo 'Requires.private: libcrypto'; \
echo 'Libs: -L$${libdir} -lssl'; \
echo 'Cflags: -I$${includedir}' ) > libssl.pc
openssl.pc:
@ ( echo 'prefix=$(INSTALLTOP)'; \
echo 'exec_prefix=$${prefix}'; \
if [ -n "$(LIBDIR)" ]; then \
echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \
else \
echo 'libdir=$(libdir)'; \
fi; \
echo 'includedir=$${prefix}/include'; \
echo ''; \
echo 'Name: OpenSSL'; \
echo 'Description: Secure Sockets Layer and cryptography libraries and tools'; \
echo 'Version: '$(VERSION); \
echo 'Requires: libssl libcrypto' ) > openssl.pc
Makefile: configdata.pm \
{- join(" \\\n" . ' ' x 10,
fill_lines(" ", $COLUMNS - 10,
@{$config{build_file_templates}})) -}
@echo "Detected changed: $?"
$(PERL) configdata.pm
@echo "**************************************************"
@echo "*** ***"
@echo "*** Please run the same make command again ***"
@echo "*** ***"
@echo "**************************************************"
@false
configdata.pm: $(SRCDIR)/Configure $(SRCDIR)/config \
{- join(" \\\n" . ' ' x 15,
fill_lines(" ", $COLUMNS - 15,
@{$config{build_infos}},
@{$config{conf_files}})) -}
@echo "Detected changed: $?"
$(PERL) configdata.pm -r
@echo "**************************************************"
@echo "*** ***"
@echo "*** Please run the same make command again ***"
@echo "*** ***"
@echo "**************************************************"
@false
reconfigure reconf:
$(PERL) configdata.pm -r
{-
use File::Basename;
use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/;
# Helper function to convert dependencies in platform agnostic form to
# dependencies in platform form.
sub compute_platform_depends {
map { my $x = $_;
grep { $x eq $_ } @{$unified_info{programs}} and platform->bin($x)
or grep { $x eq $_ } @{$unified_info{modules}} and platform->dso($x)
or grep { $x eq $_ } @{$unified_info{libraries}} and platform->lib($x)
or platform->convertext($x); } @_;
}
# Helper function to figure out dependencies on libraries
# It takes a list of library names and outputs a list of dependencies
sub compute_lib_depends {
# Depending on shared libraries:
# On Windows POSIX layers, we depend on {libname}.dll.a
# On Unix platforms, we depend on {shlibname}.so
return map { platform->sharedlib_simple($_)
// platform->sharedlib_import($_)
// platform->sharedlib($_)
// platform->staticlib($_)
} @_;
}
sub generatetarget {
my %args = @_;
my $deps = join(" ", compute_platform_depends(@{$args{deps}}));
return <<"EOF";
$args{target}: $deps
EOF
}
sub generatesrc {
my %args = @_;
my $gen0 = $args{generator}->[0];
my $gen_args = join('', map { " $_" }
@{$args{generator}}[1..$#{$args{generator}}]);
my $gen_incs = join("", map { " -I".$_ } @{$args{generator_incs}});
my $incs = join("", map { " -I".$_ } @{$args{incs}});
my $defs = join("", map { " -D".$_ } @{$args{defs}});
my $deps = join(" ", compute_platform_depends(@{$args{generator_deps}},
@{$args{deps}}));
if ($args{src} =~ /\.html$/) {
#
# HTML generator
#
my $title = basename($args{src}, ".html");
my $pod = $gen0;
return <<"EOF";
$args{src}: $pod
\$(PERL) \$(SRCDIR)/util/mkpod2html.pl -i "$pod" -o \$\@ -t "$title" -r "\$(SRCDIR)/doc"
EOF
} elsif ($args{src} =~ /\.(\d)$/) {
#
# Man-page generator
#
my $section = $1;
my $name = uc basename($args{src}, ".$section");
my $pod = $gen0;
return <<"EOF";
$args{src}: $pod
pod2man --name=$name --section=$section\$(MANSUFFIX) --center=OpenSSL \\
--release=\$(VERSION) $pod >\$\@
EOF
} elsif (platform->isdef($args{src})) {
#
# Linker script-ish generator
#
my $target = platform->def($args{src});
(my $mkdef_os = $target{shared_target}) =~ s|-shared$||;
my $ord_ver = $args{intent} eq 'lib' ? ' --version $(VERSION_NUMBER)' : '';
my $ord_name = $args{generator}->[1] || $args{product};
return <<"EOF";
$target: $gen0 $deps \$(SRCDIR)/util/mkdef.pl
\$(PERL) \$(SRCDIR)/util/mkdef.pl$ord_ver --type $args{intent} --ordinals $gen0 --name $ord_name --OS $mkdef_os > $target
EOF
} elsif (platform->isasm($args{src})
|| platform->iscppasm($args{src})) {
#
# Assembler generator
#
my $cppflags = {
shlib => '$(LIB_CFLAGS) $(LIB_CPPFLAGS)',
lib => '$(LIB_CFLAGS) $(LIB_CPPFLAGS)',
dso => '$(DSO_CFLAGS) $(DSO_CPPFLAGS)',
bin => '$(BIN_CFLAGS) $(BIN_CPPFLAGS)'
} -> {$args{intent}};
my $generator;
if ($gen0 =~ /\.pl$/) {
$generator = 'CC="$(CC)" $(PERL)'.$gen_incs.' '.$gen0.$gen_args
.' "$(PERLASM_SCHEME)"'.$incs.' '.$cppflags.$defs.' $(PROCESSOR)';
} elsif ($gen0 =~ /\.m4$/) {
$generator = 'm4 -B 8192'.$gen_incs.' '.$gen0.$gen_args.' >'
} elsif ($gen0 =~ /\.S$/) {
$generator = undef;
} else {
die "Generator type for $args{src} unknown: $gen0\n";
}
if (defined($generator)) {
return <<"EOF";
$args{src}: $gen0 $deps
$generator \$@
EOF
}
return <<"EOF";
$args{src}: $gen0 $deps
\$(CC) $incs $cppflags $defs -E $gen0 | \\
\$(PERL) -ne '/^#(line)?\\s*[0-9]+/ or print' > \$@
EOF
} elsif ($gen0 =~ m|^.*\.in$|) {
#
# "dofile" generator (file.in -> file)
#
my $dofile = abs2rel(rel2abs(catfile($config{sourcedir},
"util", "dofile.pl")),
rel2abs($config{builddir}));
my @perlmodules = ( 'configdata.pm',
grep { $_ =~ m|\.pm$| } @{$args{deps}} );
my %perlmoduleincs = map { '"-I'.dirname($_).'"' => 1 } @perlmodules;
$deps = join(' ', $deps, compute_platform_depends(@perlmodules));
@perlmodules = map { "-M".basename($_, '.pm') } @perlmodules;
my $perlmodules = join(' ', '', sort keys %perlmoduleincs, @perlmodules);
return <<"EOF";
$args{src}: $gen0 $deps
\$(PERL)$perlmodules "$dofile" "-o$target{build_file}" $gen0$gen_args > \$@
EOF
} elsif (grep { $_ eq $gen0 } @{$unified_info{programs}}) {
#
# Generic generator using OpenSSL programs
#
# Redo $gen0, to ensure that we have the proper extension where
# necessary.
$gen0 = platform->bin($gen0);
# Use $(PERL) to execute wrap.pl directly to avoid calling env
return <<"EOF";
$args{src}: $gen0 $deps \$(BLDDIR)/util/wrap.pl
\$(PERL) \$(BLDDIR)/util/wrap.pl $gen0$gen_args > \$@
EOF
} else {
#
# Generic generator using Perl
#
return <<"EOF";
$args{src}: $gen0 $deps
\$(PERL)$gen_incs $gen0$gen_args > \$@
EOF
}
}
# Should one wonder about the end of the Perl snippet, it's because this
# second regexp eats up line endings as well, if the removed path is the
# last in the line. We may therefore need to put back a line ending.
sub src2obj {
my %args = @_;
my $obj = platform->convertext($args{obj});
my $dep = platform->dep($args{obj});
my @srcs = @{$args{srcs}};
my $srcs = join(" ", @srcs);
my $deps = join(" ", @srcs, @{$args{deps}});
my $incs = join("", map { " -I".$_ } @{$args{incs}});
my $defs = join("", map { " -D".$_ } @{$args{defs}});
my $cmd;
my $cmdflags;
my $cmdcompile;
if (grep /\.rc$/, @srcs) {
$cmd = '$(RC)';
$cmdflags = '$(RCFLAGS)';
$cmdcompile = '';
} elsif (grep /\.(cc|cpp)$/, @srcs) {
$cmd = '$(CXX)';
$cmdcompile = ' -c';
$cmdflags = {
shlib => '$(LIB_CXXFLAGS) $(LIB_CPPFLAGS)',
lib => '$(LIB_CXXFLAGS) $(LIB_CPPFLAGS)',
dso => '$(DSO_CXXFLAGS) $(DSO_CPPFLAGS)',
bin => '$(BIN_CXXFLAGS) $(BIN_CPPFLAGS)'
} -> {$args{intent}};
} else {
$cmd = '$(CC)';
$cmdcompile = ' -c';
$cmdflags = {
shlib => '$(LIB_CFLAGS) $(LIB_CPPFLAGS)',
lib => '$(LIB_CFLAGS) $(LIB_CPPFLAGS)',
dso => '$(DSO_CFLAGS) $(DSO_CPPFLAGS)',
bin => '$(BIN_CFLAGS) $(BIN_CPPFLAGS)'
} -> {$args{intent}};
}
my $recipe;
# extension-specific rules
if (grep /\.s$/, @srcs) {
$recipe .= <<"EOF";
$obj: $deps
$cmd $cmdflags -c -o \$\@ $srcs
EOF
} elsif (grep /\.S$/, @srcs) {
# Originally there was multi-step rule with $(CC) -E file.S
# followed by $(CC) -c file.s. It compensated for one of
# legacy platform compiler's inability to handle .S files.
# The platform is long discontinued by vendor so there is
# hardly a point to drag it along...
$recipe .= <<"EOF";
$obj: $deps
$cmd $incs $defs $cmdflags -c -o \$\@ $srcs
EOF
} elsif ($makedep_scheme eq 'gcc' && !grep /\.rc$/, @srcs) {
$recipe .= <<"EOF";
$obj: $deps
- $cmd $incs $defs $cmdflags -MMD -MF $dep.tmp -MT \$\@ -c -o \$\@ $srcs
+ $cmd $incs $defs $cmdflags -MMD -MF $dep.tmp -c -o \$\@ $srcs
\@touch $dep.tmp
\@if cmp $dep.tmp $dep > /dev/null 2> /dev/null; then \\
rm -f $dep.tmp; \\
else \\
mv $dep.tmp $dep; \\
fi
EOF
} else {
$recipe .= <<"EOF";
$obj: $deps
$cmd $incs $defs $cmdflags $cmdcompile -o \$\@ $srcs
EOF
if ($makedep_scheme eq 'makedepend') {
$recipe .= <<"EOF";
\$(MAKEDEPEND) -f- -Y -- $incs $cmdflags -- $srcs 2>/dev/null \\
> $dep
EOF
}
}
return $recipe;
}
# We *know* this routine is only called when we've configure 'shared'.
sub obj2shlib {
my %args = @_;
my @linkdirs = ();
my @linklibs = ();
foreach (@{$args{deps}}) {
if (platform->isstaticlib($_)) {
push @linklibs, platform->convertext($_);
} else {
my $d = "-L" . dirname($_);
my $l = basename($_);
$l =~ s/^lib//;
$l = "-l" . $l;
push @linklibs, $l;
push @linkdirs, $d unless grep { $d eq $_ } @linkdirs;
}
}
my $linkflags = join("", map { $_." " } @linkdirs);
my $linklibs = join("", map { $_." " } @linklibs);
my @objs = map { platform->convertext($_) }
grep { !platform->isdef($_) }
@{$args{objs}};
my @defs = map { platform->def($_) }
grep { platform->isdef($_) }
@{$args{objs}};
my @deps = compute_lib_depends(@{$args{deps}});
die "More than one exported symbol map" if scalar @defs > 1;
my $full = platform->sharedlib($args{lib});
# $import is for Windows and subsystems thereof, where static import
# libraries for DLLs are a thing. On platforms that have this mechanism,
# $import has the name of this import library. On platforms that don't
# have this mechanism, $import will be |undef|.
my $import = platform->sharedlib_import($args{lib});
# $simple is for platforms where full shared library names include the
# shared library version, and there's a simpler name that doesn't include
# that version. On such platforms, $simple has the simpler name. On
# other platforms, it will be |undef|.
my $simple = platform->sharedlib_simple($args{lib});
my $argfile = defined $target{shared_argfileflag} ? $full.".args" : undef;
my $shared_soname = "";
$shared_soname .= ' '.$target{shared_sonameflag}.basename($full)
if defined $target{shared_sonameflag};
my $shared_imp = "";
$shared_imp .= ' '.$target{shared_impflag}.basename($import)
if defined $target{shared_impflag} && defined $import;
my $shared_def = join("", map { ' '.$target{shared_defflag}.$_ } @defs);
# There is at least one platform where the compiler-as-linker needs to
# have one object file directly on the command line. That won't hurt
# any other platform, so we do that for everyone when there's an argfile
# to be had. This depends heavily on splice, which removes elements from
# the given array, and returns them so they can be captured.
my @argfileobjs = $argfile
? splice(@objs, 1)
: ();
my $argfilecmds = $argfile
? join("\n\t", map { "echo $_ >> $argfile" } @argfileobjs)
: undef;
my $argfiledeps = $argfile
? join(" \\\n" . ' ' x (length($argfile) + 2),
fill_lines(' ', $COLUMNS - length($full) - 2, @argfileobjs))
: undef;
my @fulldeps = (@objs, ($argfile ? $argfile : ()), @defs, @deps);
my @fullobjs = (
@objs,
($argfile ? $target{shared_argfileflag}.$argfile : ())
);
my $fulldeps =
join(" \\\n" . ' ' x (length($full) + 2),
fill_lines(' ', $COLUMNS - length($full) - 2, @fulldeps));
my $fullobjs =
join(" \\\n\t\t", fill_lines(' ', $COLUMNS - 16, @fullobjs));
my $recipe = '';
if (defined $simple && $simple ne $full) {
if (sharedaix()) {
$recipe .= <<"EOF";
$simple: $full
rm -f $simple && \\
\$(AR) r $simple $full
EOF
} else {
$recipe .= <<"EOF";
$simple: $full
rm -f $simple && \\
ln -s $full $simple
EOF
}
}
if (defined $import) {
$recipe .= <<"EOF";
$import: $full
EOF
}
$recipe .= <<"EOF";
$full: $fulldeps
\$(CC) \$(LIB_CFLAGS) $linkflags\$(LIB_LDFLAGS)$shared_soname$shared_imp \\
-o $full$shared_def \\
$fullobjs \\
$linklibs \$(LIB_EX_LIBS)
EOF
if (windowsdll()) {
$recipe .= <<"EOF";
rm -f apps/$full
rm -f fuzz/$full
cp -p $full apps/
cp -p $full fuzz/
EOF
if (!$disabled{tests}) {
$recipe .= <<"EOF";
rm -f test/$full
cp -p $full test/
EOF
}
}
$recipe .= <<"EOF" if defined $argfile;
$argfile: $argfiledeps
\$(RM) $argfile
$argfilecmds
EOF
return $recipe;
}
sub obj2dso {
my %args = @_;
my $dso = platform->dso($args{module});
my @linkdirs = ();
my @linklibs = ();
foreach (@{$args{deps}}) {
next unless defined $_;
if (platform->isstaticlib($_)) {
push @linklibs, platform->convertext($_);
} else {
my $d = "-L" . dirname($_);
my $l = basename($_);
$l =~ s/^lib//;
$l = "-l" . $l;
push @linklibs, $l;
push @linkdirs, $d unless grep { $d eq $_ } @linkdirs;
}
}
my $linkflags = join("", map { $_." " } @linkdirs);
my $linklibs = join("", map { $_." " } @linklibs);
my @objs = map { platform->convertext($_) }
grep { !platform->isdef($_) }
@{$args{objs}};
my @defs = map { platform->def($_) }
grep { platform->isdef($_) }
@{$args{objs}};
my @deps = compute_lib_depends(@{$args{deps}});
my $shared_def = join("", map { ' '.$target{shared_defflag}.$_ } @defs);
# Next line needs to become "less magic" (see PR #11950)
$shared_def .= ' '.$target{shared_fipsflag} if (defined $target{shared_fipsflag} && $shared_def =~ m/providers\/fips/);
my $objs = join(" \\\n\t\t", fill_lines(' ', $COLUMNS - 16, @objs));
my $deps = join(" \\\n" . ' ' x (length($dso) + 2),
fill_lines(' ', $COLUMNS - length($dso) - 2,
@objs, @defs, @deps));
return <<"EOF";
$dso: $deps
\$(CC) \$(DSO_CFLAGS) $linkflags\$(DSO_LDFLAGS) \\
-o $dso$shared_def \\
$objs \\
$linklibs\$(DSO_EX_LIBS)
EOF
}
sub obj2lib {
my %args = @_;
my $lib = platform->staticlib($args{lib});
my @objs = map { platform->obj($_) } @{$args{objs}};
my $deps = join(" \\\n" . ' ' x (length($lib) + 2),
fill_lines(' ', $COLUMNS - length($lib) - 2, @objs));
my $max_per_call = 500;
my @objs_grouped;
push @objs_grouped, join(" ", splice @objs, 0, $max_per_call) while @objs;
my $fill_lib =
join("\n\t", (map { "\$(AR) \$(ARFLAGS) $lib $_" } @objs_grouped));
return <<"EOF";
$lib: $deps
\$(RM) $lib
$fill_lib
\$(RANLIB) \$\@ || echo Never mind.
EOF
}
sub obj2bin {
my %args = @_;
my $bin = platform->bin($args{bin});
my @objs = map { platform->obj($_) } @{$args{objs}};
my @deps = compute_lib_depends(@{$args{deps}});
my $objs = join(" \\\n" . ' ' x (length($bin) + 2),
fill_lines(' ', $COLUMNS - length($bin) - 2, @objs));
my @linkdirs = ();
my @linklibs = ();
foreach (@{$args{deps}}) {
next unless defined $_;
if (platform->isstaticlib($_)) {
push @linklibs, platform->convertext($_);
} else {
my $d = "-L" . dirname($_);
my $l = basename($_);
$l =~ s/^lib//;
$l = "-l" . $l;
push @linklibs, $l;
push @linkdirs, $d unless grep { $d eq $_ } @linkdirs;
}
}
my $linkflags = join("", map { $_." " } @linkdirs);
my $linklibs = join("", map { $_." " } @linklibs);
my $cmd = '$(CC)';
my $cmdflags = '$(BIN_CFLAGS)';
if (grep /_cc\.o$/, @{$args{objs}}) {
$cmd = '$(CXX)';
$cmdflags = '$(BIN_CXXFLAGS)';
}
my $objs = join(" \\\n\t\t", fill_lines(' ', $COLUMNS - 16, @objs));
my $deps = join(" \\\n" . ' ' x (length($bin) + 2),
fill_lines(' ', $COLUMNS - length($bin) - 2,
@objs, @deps));
return <<"EOF";
$bin: $deps
rm -f $bin
\$\${LDCMD:-$cmd} $cmdflags $linkflags\$(BIN_LDFLAGS) \\
-o $bin \\
$objs \\
$linklibs\$(BIN_EX_LIBS)
EOF
}
sub in2script {
my %args = @_;
my $script = $args{script};
my $sources = join(" ", @{$args{sources}});
my $dofile = abs2rel(rel2abs(catfile($config{sourcedir},
"util", "dofile.pl")),
rel2abs($config{builddir}));
return <<"EOF";
$script: $sources configdata.pm
\$(RM) "$script"
\$(PERL) "-I\$(BLDDIR)" -Mconfigdata "$dofile" \\
"-o$target{build_file}" $sources > "$script"
chmod a+x $script
EOF
}
sub generatedir {
my %args = @_;
my $dir = $args{dir};
my @deps = compute_platform_depends(@{$args{deps}});
my @comments = ();
# We already have a 'test' target, and the top directory is just plain
# silly
return if $dir eq "test" || $dir eq ".";
foreach my $type (("dso", "lib", "bin", "script")) {
next unless defined($unified_info{dirinfo}->{$dir}->{products}->{$type});
# For lib object files, we could update the library. However, it
# was decided that it's enough to build the directory local object
# files, so we don't need to add any actions, and the dependencies
# are already taken care of.
if ($type ne "lib") {
foreach my $prod (@{$unified_info{dirinfo}->{$dir}->{products}->{$type}}) {
if (dirname($prod) eq $dir) {
push @deps, compute_platform_depends($prod);
} else {
push @comments, "# No support to produce $type ".join(", ", @{$unified_info{dirinfo}->{$dir}->{products}->{$type}});
}
}
}
}
my $target = "$dir $dir/";
my $deps = join(" \\\n\t",
fill_lines(' ', $COLUMNS - 8, @deps));
my $comments = join("\n", "", @comments);
return <<"EOF";
$target: \\
$deps$comments
EOF
}
"" # Important! This becomes part of the template result.
-}
diff --git a/crypto/openssl/NEWS.md b/crypto/openssl/NEWS.md
index e0a81703ee8d..007fc9786ef8 100644
--- a/crypto/openssl/NEWS.md
+++ b/crypto/openssl/NEWS.md
@@ -1,1670 +1,1686 @@
NEWS
====
This file gives a brief overview of the major changes between each OpenSSL
release. For more details please read the CHANGES file.
OpenSSL Releases
----------------
- [OpenSSL 3.0](#openssl-30)
- [OpenSSL 1.1.1](#openssl-111)
- [OpenSSL 1.1.0](#openssl-110)
- [OpenSSL 1.0.2](#openssl-102)
- [OpenSSL 1.0.1](#openssl-101)
- [OpenSSL 1.0.0](#openssl-100)
- [OpenSSL 0.9.x](#openssl-09x)
OpenSSL 3.0
-----------
+### Major changes between OpenSSL 3.0.15 and OpenSSL 3.0.16 [11 Feb 2025]
+
+OpenSSL 3.0.16 is a security patch release. The most severe CVE fixed in this
+release is Low.
+
+This release incorporates the following bug fixes and mitigations:
+
+ * Fixed timing side-channel in ECDSA signature computation.
+ ([CVE-2024-13176])
+
+ * Fixed possible OOB memory access with invalid low-level GF(2^m) elliptic
+ curve parameters.
+ ([CVE-2024-9143])
+
### Major changes between OpenSSL 3.0.14 and OpenSSL 3.0.15 [3 Sep 2024]
OpenSSL 3.0.15 is a security patch release. The most severe CVE fixed in this
release is Moderate.
This release incorporates the following bug fixes and mitigations:
* Fixed possible denial of service in X.509 name checks
([CVE-2024-6119])
* Fixed possible buffer overread in SSL_select_next_proto()
([CVE-2024-5535])
### Major changes between OpenSSL 3.0.13 and OpenSSL 3.0.14 [4 Jun 2024]
* Fixed potential use after free after SSL_free_buffers() is called
([CVE-2024-4741])
* Fixed an issue where checking excessively long DSA keys or parameters may
be very slow
([CVE-2024-4603])
* Fixed unbounded memory growth with session handling in TLSv1.3
([CVE-2024-2511])
### Major changes between OpenSSL 3.0.12 and OpenSSL 3.0.13 [30 Jan 2024]
* Fixed PKCS12 Decoding crashes
([CVE-2024-0727])
* Fixed Excessive time spent checking invalid RSA public keys
([CVE-2023-6237])
* Fixed POLY1305 MAC implementation corrupting vector registers on PowerPC
CPUs which support PowerISA 2.07
([CVE-2023-6129])
* Fix excessive time spent in DH check / generation with large Q parameter
value ([CVE-2023-5678])
### Major changes between OpenSSL 3.0.11 and OpenSSL 3.0.12 [24 Oct 2023]
* Mitigate incorrect resize handling for symmetric cipher keys and IVs.
([CVE-2023-5363])
### Major changes between OpenSSL 3.0.10 and OpenSSL 3.0.11 [19 Sep 2023]
* Fix POLY1305 MAC implementation corrupting XMM registers on Windows
([CVE-2023-4807])
### Major changes between OpenSSL 3.0.9 and OpenSSL 3.0.10 [1 Aug 2023]
* Fix excessive time spent checking DH q parameter value ([CVE-2023-3817])
* Fix DH_check() excessive time with over sized modulus ([CVE-2023-3446])
* Do not ignore empty associated data entries with AES-SIV ([CVE-2023-2975])
### Major changes between OpenSSL 3.0.8 and OpenSSL 3.0.9 [30 May 2023]
* Mitigate for very slow `OBJ_obj2txt()` performance with gigantic OBJECT
IDENTIFIER sub-identities. ([CVE-2023-2650])
* Fixed buffer overread in AES-XTS decryption on ARM 64 bit platforms
([CVE-2023-1255])
* Fixed documentation of X509_VERIFY_PARAM_add0_policy() ([CVE-2023-0466])
* Fixed handling of invalid certificate policies in leaf certificates
([CVE-2023-0465])
* Limited the number of nodes created in a policy tree ([CVE-2023-0464])
### Major changes between OpenSSL 3.0.7 and OpenSSL 3.0.8 [7 Feb 2023]
* Fixed NULL dereference during PKCS7 data verification ([CVE-2023-0401])
* Fixed X.400 address type confusion in X.509 GeneralName ([CVE-2023-0286])
* Fixed NULL dereference validating DSA public key ([CVE-2023-0217])
* Fixed Invalid pointer dereference in d2i_PKCS7 functions ([CVE-2023-0216])
* Fixed Use-after-free following BIO_new_NDEF ([CVE-2023-0215])
* Fixed Double free after calling PEM_read_bio_ex ([CVE-2022-4450])
* Fixed Timing Oracle in RSA Decryption ([CVE-2022-4304])
* Fixed X.509 Name Constraints Read Buffer Overflow ([CVE-2022-4203])
* Fixed X.509 Policy Constraints Double Locking ([CVE-2022-3996])
### Major changes between OpenSSL 3.0.6 and OpenSSL 3.0.7 [1 Nov 2022]
* Added RIPEMD160 to the default provider.
* Fixed regressions introduced in 3.0.6 version.
* Fixed two buffer overflows in punycode decoding functions.
([CVE-2022-3786]) and ([CVE-2022-3602])
### Major changes between OpenSSL 3.0.5 and OpenSSL 3.0.6 [11 Oct 2022]
* Fix for custom ciphers to prevent accidental use of NULL encryption
([CVE-2022-3358])
### Major changes between OpenSSL 3.0.4 and OpenSSL 3.0.5 [5 Jul 2022]
* Fixed heap memory corruption with RSA private key operation
([CVE-2022-2274])
* Fixed AES OCB failure to encrypt some bytes on 32-bit x86 platforms
([CVE-2022-2097])
### Major changes between OpenSSL 3.0.3 and OpenSSL 3.0.4 [21 Jun 2022]
* Fixed additional bugs in the c_rehash script which was not properly
sanitising shell metacharacters to prevent command injection
([CVE-2022-2068])
### Major changes between OpenSSL 3.0.2 and OpenSSL 3.0.3 [3 May 2022]
* Fixed a bug in the c_rehash script which was not properly sanitising shell
metacharacters to prevent command injection ([CVE-2022-1292])
* Fixed a bug in the function `OCSP_basic_verify` that verifies the signer
certificate on an OCSP response ([CVE-2022-1343])
* Fixed a bug where the RC4-MD5 ciphersuite incorrectly used the
AAD data as the MAC key ([CVE-2022-1434])
* Fix a bug in the OPENSSL_LH_flush() function that breaks reuse of the memory
occuppied by the removed hash table entries ([CVE-2022-1473])
### Major changes between OpenSSL 3.0.1 and OpenSSL 3.0.2 [15 Mar 2022]
* Fixed a bug in the BN_mod_sqrt() function that can cause it to loop forever
for non-prime moduli ([CVE-2022-0778])
### Major changes between OpenSSL 3.0.0 and OpenSSL 3.0.1 [14 Dec 2021]
* Fixed invalid handling of X509_verify_cert() internal errors in libssl
([CVE-2021-4044])
* Allow fetching an operation from the provider that owns an unexportable key
as a fallback if that is still allowed by the property query.
### Major changes between OpenSSL 1.1.1 and OpenSSL 3.0.0 [7 sep 2021]
* Enhanced 'openssl list' with many new options.
* Added migration guide to man7.
* Implemented support for fully "pluggable" TLSv1.3 groups.
* Added suport for Kernel TLS (KTLS).
* Changed the license to the Apache License v2.0.
* Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2,
RC4, RC5, and DES to the legacy provider.
* Moved the EVP digests MD2, MD4, MDC2, WHIRLPOOL and RIPEMD-160 to the legacy
provider.
* Added convenience functions for generating asymmetric key pairs.
* Deprecated the `OCSP_REQ_CTX` type and functions.
* Deprecated the `EC_KEY` and `EC_KEY_METHOD` types and functions.
* Deprecated the `RSA` and `RSA_METHOD` types and functions.
* Deprecated the `DSA` and `DSA_METHOD` types and functions.
* Deprecated the `DH` and `DH_METHOD` types and functions.
* Deprecated the `ERR_load_` functions.
* Remove the `RAND_DRBG` API.
* Deprecated the `ENGINE` API.
* Added `OSSL_LIB_CTX`, a libcrypto library context.
* Added various `_ex` functions to the OpenSSL API that support using
a non-default `OSSL_LIB_CTX`.
* Interactive mode is removed from the 'openssl' program.
* The X25519, X448, Ed25519, Ed448, SHAKE128 and SHAKE256 algorithms are
included in the FIPS provider.
* X509 certificates signed using SHA1 are no longer allowed at security
level 1 or higher. The default security level for TLS is 1, so
certificates signed using SHA1 are by default no longer trusted to
authenticate servers or clients.
* enable-crypto-mdebug and enable-crypto-mdebug-backtrace were mostly
disabled; the project uses address sanitize/leak-detect instead.
* Added a Certificate Management Protocol (CMP, RFC 4210) implementation
also covering CRMF (RFC 4211) and HTTP transfer (RFC 6712).
It is part of the crypto lib and adds a 'cmp' app with a demo configuration.
All widely used CMP features are supported for both clients and servers.
* Added a proper HTTP client supporting GET with optional redirection, POST,
arbitrary request and response content types, TLS, persistent connections,
connections via HTTP(s) proxies, connections and exchange via user-defined
BIOs (allowing implicit connections), and timeout checks.
* Added util/check-format.pl for checking adherence to the coding guidelines.
* Added OSSL_ENCODER, a generic encoder API.
* Added OSSL_DECODER, a generic decoder API.
* Added OSSL_PARAM_BLD, an easier to use API to OSSL_PARAM.
* Added error raising macros, ERR_raise() and ERR_raise_data().
* Deprecated ERR_put_error(), ERR_get_error_line(), ERR_get_error_line_data(),
ERR_peek_error_line_data(), ERR_peek_last_error_line_data() and
ERR_func_error_string().
* Added OSSL_PROVIDER_available(), to check provider availibility.
* Added 'openssl mac' that uses the EVP_MAC API.
* Added 'openssl kdf' that uses the EVP_KDF API.
* Add OPENSSL_info() and 'openssl info' to get built-in data.
* Add support for enabling instrumentation through trace and debug
output.
* Changed our version number scheme and set the next major release to
3.0.0
* Added EVP_MAC, an EVP layer MAC API, and a generic EVP_PKEY to EVP_MAC
bridge. Supported MACs are: BLAKE2, CMAC, GMAC, HMAC, KMAC, POLY1305
and SIPHASH.
* Removed the heartbeat message in DTLS feature.
* Added EVP_KDF, an EVP layer KDF and PRF API, and a generic EVP_PKEY to
EVP_KDF bridge. Supported KDFs are: HKDF, KBKDF, KRB5 KDF, PBKDF2,
PKCS12 KDF, SCRYPT, SSH KDF, SSKDF, TLS1 PRF, X9.42 KDF and X9.63 KDF.
* All of the low-level MD2, MD4, MD5, MDC2, RIPEMD160, SHA1, SHA224,
SHA256, SHA384, SHA512 and Whirlpool digest functions have been
deprecated.
* All of the low-level AES, Blowfish, Camellia, CAST, DES, IDEA, RC2,
RC4, RC5 and SEED cipher functions have been deprecated.
* All of the low-level DH, DSA, ECDH, ECDSA and RSA public key functions
have been deprecated.
* SSL 3, TLS 1.0, TLS 1.1, and DTLS 1.0 only work at security level 0,
except when RSA key exchange without SHA1 is used.
* Added providers, a new pluggability concept that will replace the
ENGINE API and ENGINE implementations.
OpenSSL 1.1.1
-------------
### Major changes between OpenSSL 1.1.1k and OpenSSL 1.1.1l [24 Aug 2021]
* Fixed an SM2 Decryption Buffer Overflow ([CVE-2021-3711])
* Fixed various read buffer overruns processing ASN.1 strings ([CVE-2021-3712])
### Major changes between OpenSSL 1.1.1j and OpenSSL 1.1.1k [25 Mar 2021]
* Fixed a problem with verifying a certificate chain when using the
X509_V_FLAG_X509_STRICT flag ([CVE-2021-3450])
* Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously
crafted renegotiation ClientHello message from a client ([CVE-2021-3449])
### Major changes between OpenSSL 1.1.1i and OpenSSL 1.1.1j [16 Feb 2021]
* Fixed a NULL pointer deref in the X509_issuer_and_serial_hash()
function ([CVE-2021-23841])
* Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING
padding mode to correctly check for rollback attacks
* Fixed an overflow in the EVP_CipherUpdate, EVP_EncryptUpdate and
EVP_DecryptUpdate functions ([CVE-2021-23840])
* Fixed SRP_Calc_client_key so that it runs in constant time
### Major changes between OpenSSL 1.1.1h and OpenSSL 1.1.1i [8 Dec 2020]
* Fixed NULL pointer deref in GENERAL_NAME_cmp ([CVE-2020-1971])
### Major changes between OpenSSL 1.1.1g and OpenSSL 1.1.1h [22 Sep 2020]
* Disallow explicit curve parameters in verifications chains when
X509_V_FLAG_X509_STRICT is used
* Enable 'MinProtocol' and 'MaxProtocol' to configure both TLS and DTLS
contexts
* Oracle Developer Studio will start reporting deprecation warnings
### Major changes between OpenSSL 1.1.1f and OpenSSL 1.1.1g [21 Apr 2020]
* Fixed segmentation fault in SSL_check_chain() ([CVE-2020-1967])
### Major changes between OpenSSL 1.1.1e and OpenSSL 1.1.1f [31 Mar 2020]
* Revert the unexpected EOF reporting via SSL_ERROR_SSL
### Major changes between OpenSSL 1.1.1d and OpenSSL 1.1.1e [17 Mar 2020]
* Fixed an overflow bug in the x64_64 Montgomery squaring procedure
used in exponentiation with 512-bit moduli ([CVE-2019-1551])
### Major changes between OpenSSL 1.1.1c and OpenSSL 1.1.1d [10 Sep 2019]
* Fixed a fork protection issue ([CVE-2019-1549])
* Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey
([CVE-2019-1563])
* For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters
* Compute ECC cofactors if not provided during EC_GROUP construction
([CVE-2019-1547])
* Early start up entropy quality from the DEVRANDOM seed source has been
improved for older Linux systems
* Correct the extended master secret constant on EBCDIC systems
* Use Windows installation paths in the mingw builds ([CVE-2019-1552])
* Changed DH_check to accept parameters with order q and 2q subgroups
* Significantly reduce secure memory usage by the randomness pools
* Revert the DEVRANDOM_WAIT feature for Linux systems
### Major changes between OpenSSL 1.1.1b and OpenSSL 1.1.1c [28 May 2019]
* Prevent over long nonces in ChaCha20-Poly1305 ([CVE-2019-1543])
### Major changes between OpenSSL 1.1.1a and OpenSSL 1.1.1b [26 Feb 2019]
* Change the info callback signals for the start and end of a post-handshake
message exchange in TLSv1.3.
* Fix a bug in DTLS over SCTP. This breaks interoperability with older
versions of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2.
### Major changes between OpenSSL 1.1.1 and OpenSSL 1.1.1a [20 Nov 2018]
* Timing vulnerability in DSA signature generation ([CVE-2018-0734])
* Timing vulnerability in ECDSA signature generation ([CVE-2018-0735])
### Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.1 [11 Sep 2018]
* Support for TLSv1.3 added. The TLSv1.3 implementation includes:
* Fully compliant implementation of RFC8446 (TLSv1.3) on by default
* Early data (0-RTT)
* Post-handshake authentication and key update
* Middlebox Compatibility Mode
* TLSv1.3 PSKs
* Support for all five RFC8446 ciphersuites
* RSA-PSS signature algorithms (backported to TLSv1.2)
* Configurable session ticket support
* Stateless server support
* Rewrite of the packet construction code for "safer" packet handling
* Rewrite of the extension handling code
For further important information, see the [TLS1.3 page](
https://wiki.openssl.org/index.php/TLS1.3) in the OpenSSL Wiki.
* Complete rewrite of the OpenSSL random number generator to introduce the
following capabilities
* The default RAND method now utilizes an AES-CTR DRBG according to
NIST standard SP 800-90Ar1.
* Support for multiple DRBG instances with seed chaining.
* There is a public and private DRBG instance.
* The DRBG instances are fork-safe.
* Keep all global DRBG instances on the secure heap if it is enabled.
* The public and private DRBG instance are per thread for lock free
operation
* Support for various new cryptographic algorithms including:
* SHA3
* SHA512/224 and SHA512/256
* EdDSA (both Ed25519 and Ed448) including X509 and TLS support
* X448 (adding to the existing X25519 support in 1.1.0)
* Multi-prime RSA
* SM2
* SM3
* SM4
* SipHash
* ARIA (including TLS support)
* Significant Side-Channel attack security improvements
* Add a new ClientHello callback to provide the ability to adjust the SSL
object at an early stage.
* Add 'Maximum Fragment Length' TLS extension negotiation and support
* A new STORE module, which implements a uniform and URI based reader of
stores that can contain keys, certificates, CRLs and numerous other
objects.
* Move the display of configuration data to configdata.pm.
* Allow GNU style "make variables" to be used with Configure.
* Claim the namespaces OSSL and OPENSSL, represented as symbol prefixes
* Rewrite of devcrypto engine
OpenSSL 1.1.0
-------------
### Major changes between OpenSSL 1.1.0k and OpenSSL 1.1.0l [10 Sep 2019]
* Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey
([CVE-2019-1563])
* For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters
* Compute ECC cofactors if not provided during EC_GROUP construction
([CVE-2019-1547])
* Use Windows installation paths in the mingw builds ([CVE-2019-1552])
### Major changes between OpenSSL 1.1.0j and OpenSSL 1.1.0k [28 May 2019]
* Prevent over long nonces in ChaCha20-Poly1305 ([CVE-2019-1543])
### Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.0j [20 Nov 2018]
* Timing vulnerability in DSA signature generation ([CVE-2018-0734])
* Timing vulnerability in ECDSA signature generation ([CVE-2018-0735])
### Major changes between OpenSSL 1.1.0h and OpenSSL 1.1.0i [14 Aug 2018]
* Client DoS due to large DH parameter ([CVE-2018-0732])
* Cache timing vulnerability in RSA Key Generation ([CVE-2018-0737])
### Major changes between OpenSSL 1.1.0g and OpenSSL 1.1.0h [27 Mar 2018]
* Constructed ASN.1 types with a recursive definition could exceed the
stack ([CVE-2018-0739])
* Incorrect CRYPTO_memcmp on HP-UX PA-RISC ([CVE-2018-0733])
* 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]
* bn_sqrx8x_internal carry bug on x86_64 ([CVE-2017-3736])
* 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]
* 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]
* Encrypt-Then-Mac renegotiation crash ([CVE-2017-3733])
### Major changes between OpenSSL 1.1.0c and OpenSSL 1.1.0d [26 Jan 2017]
* Truncated packet could crash via OOB read ([CVE-2017-3731])
* Bad (EC)DHE parameters cause a client crash ([CVE-2017-3730])
* 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]
* ChaCha20/Poly1305 heap-buffer-overflow ([CVE-2016-7054])
* CMS Null dereference ([CVE-2016-7053])
* Montgomery multiplication may produce incorrect results ([CVE-2016-7055])
### Major changes between OpenSSL 1.1.0a and OpenSSL 1.1.0b [26 Sep 2016]
* 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]
* OCSP Status Request extension unbounded memory growth ([CVE-2016-6304])
* SSL_peek() hang on empty record ([CVE-2016-6305])
* Excessive allocation of memory in tls_get_message_header()
([CVE-2016-6307])
* 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]
* Copyright text was shrunk to a boilerplate that points to the license
* "shared" builds are now the default when possible
* Added support for "pipelining"
* Added the AFALG engine
* New threading API implemented
* Support for ChaCha20 and Poly1305 added to libcrypto and libssl
* Support for extended master secret
* CCM ciphersuites
* Reworked test suite, now based on perl, Test::Harness and Test::More
* *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
* libssl internal structures made opaque
* SSLv2 support removed
* Kerberos ciphersuite support removed
* RC4 removed from DEFAULT ciphersuites in libssl
* 40 and 56 bit cipher support removed from libssl
* All public header files moved to include/openssl, no more symlinking
* SSL/TLS state machine, version negotiation and record layer rewritten
* EC revision: now operations use new EC_KEY_METHOD.
* Support for OCB mode added to libcrypto
* Support for asynchronous crypto operations added to libcrypto and libssl
* 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.
* Application software can be compiled with -DOPENSSL_API_COMPAT=version
to ensure that features deprecated in that version are not exposed.
* Support for RFC6698/RFC7671 DANE TLSA peer authentication
* 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.
* Reworked BIO networking library, with full support for IPv6.
* New "unified" build system
* New security levels
* Support for scrypt algorithm
* Support for X25519
* Extended SSL_CONF support using configuration files
* KDF algorithm support. Implement TLS PRF as a KDF.
* Support for Certificate Transparency
* HKDF support.
OpenSSL 1.0.2
-------------
### Major changes between OpenSSL 1.0.2s and OpenSSL 1.0.2t [10 Sep 2019]
* Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey
([CVE-2019-1563])
* For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters
* Compute ECC cofactors if not provided during EC_GROUP construction
([CVE-2019-1547])
* Document issue with installation paths in diverse Windows builds
([CVE-2019-1552])
### Major changes between OpenSSL 1.0.2r and OpenSSL 1.0.2s [28 May 2019]
* None
### Major changes between OpenSSL 1.0.2q and OpenSSL 1.0.2r [26 Feb 2019]
* 0-byte record padding oracle ([CVE-2019-1559])
### Major changes between OpenSSL 1.0.2p and OpenSSL 1.0.2q [20 Nov 2018]
* Microarchitecture timing vulnerability in ECC scalar multiplication ([CVE-2018-5407])
* Timing vulnerability in DSA signature generation ([CVE-2018-0734])
### Major changes between OpenSSL 1.0.2o and OpenSSL 1.0.2p [14 Aug 2018]
* Client DoS due to large DH parameter ([CVE-2018-0732])
* Cache timing vulnerability in RSA Key Generation ([CVE-2018-0737])
### Major changes between OpenSSL 1.0.2n and OpenSSL 1.0.2o [27 Mar 2018]
* Constructed ASN.1 types with a recursive definition could exceed the
stack ([CVE-2018-0739])
### Major changes between OpenSSL 1.0.2m and OpenSSL 1.0.2n [7 Dec 2017]
* Read/write after SSL object in error state ([CVE-2017-3737])
* rsaz_1024_mul_avx2 overflow bug on x86_64 ([CVE-2017-3738])
### Major changes between OpenSSL 1.0.2l and OpenSSL 1.0.2m [2 Nov 2017]
* bn_sqrx8x_internal carry bug on x86_64 ([CVE-2017-3736])
* Malformed X.509 IPAddressFamily could cause OOB read ([CVE-2017-3735])
### Major changes between OpenSSL 1.0.2k and OpenSSL 1.0.2l [25 May 2017]
* config now recognises 64-bit mingw and chooses mingw64 instead of mingw
### Major changes between OpenSSL 1.0.2j and OpenSSL 1.0.2k [26 Jan 2017]
* Truncated packet could crash via OOB read ([CVE-2017-3731])
* BN_mod_exp may produce incorrect results on x86_64 ([CVE-2017-3732])
* Montgomery multiplication may produce incorrect results ([CVE-2016-7055])
### Major changes between OpenSSL 1.0.2i and OpenSSL 1.0.2j [26 Sep 2016]
* Missing CRL sanity check ([CVE-2016-7052])
### Major changes between OpenSSL 1.0.2h and OpenSSL 1.0.2i [22 Sep 2016]
* OCSP Status Request extension unbounded memory growth ([CVE-2016-6304])
* SWEET32 Mitigation ([CVE-2016-2183])
* OOB write in MDC2_Update() ([CVE-2016-6303])
* Malformed SHA512 ticket DoS ([CVE-2016-6302])
* OOB write in BN_bn2dec() ([CVE-2016-2182])
* OOB read in TS_OBJ_print_bio() ([CVE-2016-2180])
* Pointer arithmetic undefined behaviour ([CVE-2016-2177])
* Constant time flag not preserved in DSA signing ([CVE-2016-2178])
* DTLS buffered message DoS ([CVE-2016-2179])
* DTLS replay protection DoS ([CVE-2016-2181])
* Certificate message OOB reads ([CVE-2016-6306])
### Major changes between OpenSSL 1.0.2g and OpenSSL 1.0.2h [3 May 2016]
* Prevent padding oracle in AES-NI CBC MAC check ([CVE-2016-2107])
* Fix EVP_EncodeUpdate overflow ([CVE-2016-2105])
* Fix EVP_EncryptUpdate overflow ([CVE-2016-2106])
* Prevent ASN.1 BIO excessive memory allocation ([CVE-2016-2109])
* EBCDIC overread ([CVE-2016-2176])
* Modify behavior of ALPN to invoke callback after SNI/servername
callback, such that updates to the SSL_CTX affect ALPN.
* Remove LOW from the DEFAULT cipher list. This removes singles DES from
the default.
* 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]
* Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
* Disable SSLv2 default build, default negotiation and weak ciphers
([CVE-2016-0800])
* Fix a double-free in DSA code ([CVE-2016-0705])
* Disable SRP fake user seed to address a server memory leak
([CVE-2016-0798])
* Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
([CVE-2016-0797])
* Fix memory issues in BIO_*printf functions ([CVE-2016-0799])
* 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]
* DH small subgroups ([CVE-2016-0701])
* SSLv2 doesn't block disabled ciphers ([CVE-2015-3197])
### Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015]
* BN_mod_exp may produce incorrect results on x86_64 ([CVE-2015-3193])
* Certificate verify crash with missing PSS parameter ([CVE-2015-3194])
* X509_ATTRIBUTE memory leak ([CVE-2015-3195])
* Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
* 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]
* Alternate chains certificate forgery ([CVE-2015-1793])
* Race condition handling PSK identify hint ([CVE-2015-3196])
### Major changes between OpenSSL 1.0.2b and OpenSSL 1.0.2c [12 Jun 2015]
* Fix HMAC ABI incompatibility
### Major changes between OpenSSL 1.0.2a and OpenSSL 1.0.2b [11 Jun 2015]
* Malformed ECParameters causes infinite loop ([CVE-2015-1788])
* Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789])
* PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790])
* CMS verify infinite loop with unknown hash function ([CVE-2015-1792])
* Race condition handling NewSessionTicket ([CVE-2015-1791])
### Major changes between OpenSSL 1.0.2 and OpenSSL 1.0.2a [19 Mar 2015]
* OpenSSL 1.0.2 ClientHello sigalgs DoS fix ([CVE-2015-0291])
* Multiblock corrupted pointer fix ([CVE-2015-0290])
* Segmentation fault in DTLSv1_listen fix ([CVE-2015-0207])
* Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286])
* Segmentation fault for invalid PSS parameters fix ([CVE-2015-0208])
* ASN.1 structure reuse memory corruption fix ([CVE-2015-0287])
* PKCS7 NULL pointer dereferences fix ([CVE-2015-0289])
* DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293])
* Empty CKE with client auth and DHE fix ([CVE-2015-1787])
* Handshake with unseeded PRNG fix ([CVE-2015-0285])
* Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209])
* X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288])
* Removed the export ciphers from the DEFAULT ciphers
### Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.2 [22 Jan 2015]
* Suite B support for TLS 1.2 and DTLS 1.2
* Support for DTLS 1.2
* TLS automatic EC curve selection.
* API to set TLS supported signature algorithms and curves
* SSL_CONF configuration API.
* TLS Brainpool support.
* ALPN support.
* CMS support for RSA-PSS, RSA-OAEP, ECDH and X9.42 DH.
OpenSSL 1.0.1
-------------
### Major changes between OpenSSL 1.0.1t and OpenSSL 1.0.1u [22 Sep 2016]
* OCSP Status Request extension unbounded memory growth ([CVE-2016-6304])
* SWEET32 Mitigation ([CVE-2016-2183])
* OOB write in MDC2_Update() ([CVE-2016-6303])
* Malformed SHA512 ticket DoS ([CVE-2016-6302])
* OOB write in BN_bn2dec() ([CVE-2016-2182])
* OOB read in TS_OBJ_print_bio() ([CVE-2016-2180])
* Pointer arithmetic undefined behaviour ([CVE-2016-2177])
* Constant time flag not preserved in DSA signing ([CVE-2016-2178])
* DTLS buffered message DoS ([CVE-2016-2179])
* DTLS replay protection DoS ([CVE-2016-2181])
* Certificate message OOB reads ([CVE-2016-6306])
### Major changes between OpenSSL 1.0.1s and OpenSSL 1.0.1t [3 May 2016]
* Prevent padding oracle in AES-NI CBC MAC check ([CVE-2016-2107])
* Fix EVP_EncodeUpdate overflow ([CVE-2016-2105])
* Fix EVP_EncryptUpdate overflow ([CVE-2016-2106])
* Prevent ASN.1 BIO excessive memory allocation ([CVE-2016-2109])
* EBCDIC overread ([CVE-2016-2176])
* Modify behavior of ALPN to invoke callback after SNI/servername
callback, such that updates to the SSL_CTX affect ALPN.
* Remove LOW from the DEFAULT cipher list. This removes singles DES from
the default.
* Only remove the SSLv2 methods with the no-ssl2-method option.
### Major changes between OpenSSL 1.0.1r and OpenSSL 1.0.1s [1 Mar 2016]
* Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
* Disable SSLv2 default build, default negotiation and weak ciphers
([CVE-2016-0800])
* Fix a double-free in DSA code ([CVE-2016-0705])
* Disable SRP fake user seed to address a server memory leak
([CVE-2016-0798])
* Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
([CVE-2016-0797])
* Fix memory issues in BIO_*printf functions ([CVE-2016-0799])
* Fix side channel attack on modular exponentiation ([CVE-2016-0702])
### Major changes between OpenSSL 1.0.1q and OpenSSL 1.0.1r [28 Jan 2016]
* Protection for DH small subgroup attacks
* SSLv2 doesn't block disabled ciphers ([CVE-2015-3197])
### Major changes between OpenSSL 1.0.1p and OpenSSL 1.0.1q [3 Dec 2015]
* Certificate verify crash with missing PSS parameter ([CVE-2015-3194])
* X509_ATTRIBUTE memory leak ([CVE-2015-3195])
* Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
* In DSA_generate_parameters_ex, if the provided seed is too short,
return an error
### Major changes between OpenSSL 1.0.1o and OpenSSL 1.0.1p [9 Jul 2015]
* Alternate chains certificate forgery ([CVE-2015-1793])
* Race condition handling PSK identify hint ([CVE-2015-3196])
### Major changes between OpenSSL 1.0.1n and OpenSSL 1.0.1o [12 Jun 2015]
* Fix HMAC ABI incompatibility
### Major changes between OpenSSL 1.0.1m and OpenSSL 1.0.1n [11 Jun 2015]
* Malformed ECParameters causes infinite loop ([CVE-2015-1788])
* Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789])
* PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790])
* CMS verify infinite loop with unknown hash function ([CVE-2015-1792])
* Race condition handling NewSessionTicket ([CVE-2015-1791])
### Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.1m [19 Mar 2015]
* Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286])
* ASN.1 structure reuse memory corruption fix ([CVE-2015-0287])
* PKCS7 NULL pointer dereferences fix ([CVE-2015-0289])
* DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293])
* Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209])
* X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288])
* Removed the export ciphers from the DEFAULT ciphers
### Major changes between OpenSSL 1.0.1k and OpenSSL 1.0.1l [15 Jan 2015]
* Build fixes for the Windows and OpenVMS platforms
### Major changes between OpenSSL 1.0.1j and OpenSSL 1.0.1k [8 Jan 2015]
* Fix for [CVE-2014-3571]
* Fix for [CVE-2015-0206]
* Fix for [CVE-2014-3569]
* Fix for [CVE-2014-3572]
* Fix for [CVE-2015-0204]
* Fix for [CVE-2015-0205]
* Fix for [CVE-2014-8275]
* Fix for [CVE-2014-3570]
### Major changes between OpenSSL 1.0.1i and OpenSSL 1.0.1j [15 Oct 2014]
* Fix for [CVE-2014-3513]
* Fix for [CVE-2014-3567]
* Mitigation for [CVE-2014-3566] (SSL protocol vulnerability)
* Fix for [CVE-2014-3568]
### Major changes between OpenSSL 1.0.1h and OpenSSL 1.0.1i [6 Aug 2014]
* Fix for [CVE-2014-3512]
* Fix for [CVE-2014-3511]
* Fix for [CVE-2014-3510]
* Fix for [CVE-2014-3507]
* Fix for [CVE-2014-3506]
* Fix for [CVE-2014-3505]
* Fix for [CVE-2014-3509]
* Fix for [CVE-2014-5139]
* Fix for [CVE-2014-3508]
### Major changes between OpenSSL 1.0.1g and OpenSSL 1.0.1h [5 Jun 2014]
* Fix for [CVE-2014-0224]
* Fix for [CVE-2014-0221]
* Fix for [CVE-2014-0198]
* Fix for [CVE-2014-0195]
* Fix for [CVE-2014-3470]
* Fix for [CVE-2010-5298]
### Major changes between OpenSSL 1.0.1f and OpenSSL 1.0.1g [7 Apr 2014]
* Fix for [CVE-2014-0160]
* Add TLS padding extension workaround for broken servers.
* Fix for [CVE-2014-0076]
### Major changes between OpenSSL 1.0.1e and OpenSSL 1.0.1f [6 Jan 2014]
* Don't include gmt_unix_time in TLS server and client random values
* Fix for TLS record tampering bug ([CVE-2013-4353])
* Fix for TLS version checking bug ([CVE-2013-6449])
* Fix for DTLS retransmission bug ([CVE-2013-6450])
### Major changes between OpenSSL 1.0.1d and OpenSSL 1.0.1e [11 Feb 2013]
* Corrected fix for ([CVE-2013-0169])
### Major changes between OpenSSL 1.0.1c and OpenSSL 1.0.1d [4 Feb 2013]
* Fix renegotiation in TLS 1.1, 1.2 by using the correct TLS version.
* Include the fips configuration module.
* Fix OCSP bad key DoS attack ([CVE-2013-0166])
* Fix for SSL/TLS/DTLS CBC plaintext recovery attack ([CVE-2013-0169])
* 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]
* Fix TLS/DTLS record length checking bug ([CVE-2012-2333])
* 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]
* Fix compilation error on non-x86 platforms.
* Make FIPS capable OpenSSL ciphers work in non-FIPS mode.
* 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]
* Fix for ASN1 overflow bug ([CVE-2012-2110])
* Workarounds for some servers that hang on long client hellos.
* Fix SEGV in AES code.
### Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.1 [14 Mar 2012]
* TLS/DTLS heartbeat support.
* SCTP support.
* RFC 5705 TLS key material exporter.
* RFC 5764 DTLS-SRTP negotiation.
* Next Protocol Negotiation.
* PSS signatures in certificates, requests and CRLs.
* Support for password based recipient info for CMS.
* Support TLS v1.2 and TLS v1.1.
* Preliminary FIPS capability for unvalidated 2.0 FIPS module.
* SRP support.
OpenSSL 1.0.0
-------------
### Major changes between OpenSSL 1.0.0s and OpenSSL 1.0.0t [3 Dec 2015]
* X509_ATTRIBUTE memory leak (([CVE-2015-3195]))
* Race condition handling PSK identify hint ([CVE-2015-3196])
### Major changes between OpenSSL 1.0.0r and OpenSSL 1.0.0s [11 Jun 2015]
* Malformed ECParameters causes infinite loop ([CVE-2015-1788])
* Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789])
* PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790])
* CMS verify infinite loop with unknown hash function ([CVE-2015-1792])
* Race condition handling NewSessionTicket ([CVE-2015-1791])
### Major changes between OpenSSL 1.0.0q and OpenSSL 1.0.0r [19 Mar 2015]
* Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286])
* ASN.1 structure reuse memory corruption fix ([CVE-2015-0287])
* PKCS7 NULL pointer dereferences fix ([CVE-2015-0289])
* DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293])
* Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209])
* X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288])
* Removed the export ciphers from the DEFAULT ciphers
### Major changes between OpenSSL 1.0.0p and OpenSSL 1.0.0q [15 Jan 2015]
* Build fixes for the Windows and OpenVMS platforms
### Major changes between OpenSSL 1.0.0o and OpenSSL 1.0.0p [8 Jan 2015]
* Fix for [CVE-2014-3571]
* Fix for [CVE-2015-0206]
* Fix for [CVE-2014-3569]
* Fix for [CVE-2014-3572]
* Fix for [CVE-2015-0204]
* Fix for [CVE-2015-0205]
* Fix for [CVE-2014-8275]
* Fix for [CVE-2014-3570]
### Major changes between OpenSSL 1.0.0n and OpenSSL 1.0.0o [15 Oct 2014]
* Fix for [CVE-2014-3513]
* Fix for [CVE-2014-3567]
* Mitigation for [CVE-2014-3566] (SSL protocol vulnerability)
* Fix for [CVE-2014-3568]
### Major changes between OpenSSL 1.0.0m and OpenSSL 1.0.0n [6 Aug 2014]
* Fix for [CVE-2014-3510]
* Fix for [CVE-2014-3507]
* Fix for [CVE-2014-3506]
* Fix for [CVE-2014-3505]
* Fix for [CVE-2014-3509]
* Fix for [CVE-2014-3508]
Known issues in OpenSSL 1.0.0m:
* EAP-FAST and other applications using tls_session_secret_cb
won't resume sessions. Fixed in 1.0.0n-dev
* Compilation failure of s3_pkt.c on some platforms due to missing
`<limits.h>` include. Fixed in 1.0.0n-dev
### Major changes between OpenSSL 1.0.0l and OpenSSL 1.0.0m [5 Jun 2014]
* Fix for [CVE-2014-0224]
* Fix for [CVE-2014-0221]
* Fix for [CVE-2014-0198]
* Fix for [CVE-2014-0195]
* Fix for [CVE-2014-3470]
* Fix for [CVE-2014-0076]
* Fix for [CVE-2010-5298]
### Major changes between OpenSSL 1.0.0k and OpenSSL 1.0.0l [6 Jan 2014]
* Fix for DTLS retransmission bug ([CVE-2013-6450])
### Major changes between OpenSSL 1.0.0j and OpenSSL 1.0.0k [5 Feb 2013]
* Fix for SSL/TLS/DTLS CBC plaintext recovery attack ([CVE-2013-0169])
* Fix OCSP bad key DoS attack ([CVE-2013-0166])
### Major changes between OpenSSL 1.0.0i and OpenSSL 1.0.0j [10 May 2012]
* Fix DTLS record length checking bug ([CVE-2012-2333])
### Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.0i [19 Apr 2012]
* Fix for ASN1 overflow bug ([CVE-2012-2110])
### Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h [12 Mar 2012]
* Fix for CMS/PKCS#7 MMA ([CVE-2012-0884])
* Corrected fix for ([CVE-2011-4619])
* Various DTLS fixes.
### Major changes between OpenSSL 1.0.0f and OpenSSL 1.0.0g [18 Jan 2012]
* Fix for DTLS DoS issue ([CVE-2012-0050])
### Major changes between OpenSSL 1.0.0e and OpenSSL 1.0.0f [4 Jan 2012]
* Fix for DTLS plaintext recovery attack ([CVE-2011-4108])
* Clear block padding bytes of SSL 3.0 records ([CVE-2011-4576])
* Only allow one SGC handshake restart for SSL/TLS ([CVE-2011-4619])
* Check parameters are not NULL in GOST ENGINE ([CVE-2012-0027])
* Check for malformed RFC3779 data ([CVE-2011-4577])
### Major changes between OpenSSL 1.0.0d and OpenSSL 1.0.0e [6 Sep 2011]
* Fix for CRL vulnerability issue ([CVE-2011-3207])
* Fix for ECDH crashes ([CVE-2011-3210])
* Protection against EC timing attacks.
* Support ECDH ciphersuites for certificates using SHA2 algorithms.
* Various DTLS fixes.
### Major changes between OpenSSL 1.0.0c and OpenSSL 1.0.0d [8 Feb 2011]
* Fix for security issue ([CVE-2011-0014])
### Major changes between OpenSSL 1.0.0b and OpenSSL 1.0.0c [2 Dec 2010]
* Fix for security issue ([CVE-2010-4180])
* Fix for ([CVE-2010-4252])
* Fix mishandling of absent EC point format extension.
* Fix various platform compilation issues.
* Corrected fix for security issue ([CVE-2010-3864]).
### Major changes between OpenSSL 1.0.0a and OpenSSL 1.0.0b [16 Nov 2010]
* Fix for security issue ([CVE-2010-3864]).
* Fix for ([CVE-2010-2939])
* Fix WIN32 build system for GOST ENGINE.
### Major changes between OpenSSL 1.0.0 and OpenSSL 1.0.0a [1 Jun 2010]
* Fix for security issue ([CVE-2010-1633]).
* GOST MAC and CFB fixes.
### Major changes between OpenSSL 0.9.8n and OpenSSL 1.0.0 [29 Mar 2010]
* RFC3280 path validation: sufficient to process PKITS tests.
* Integrated support for PVK files and keyblobs.
* Change default private key format to PKCS#8.
* CMS support: able to process all examples in RFC4134
* Streaming ASN1 encode support for PKCS#7 and CMS.
* Multiple signer and signer add support for PKCS#7 and CMS.
* ASN1 printing support.
* Whirlpool hash algorithm added.
* RFC3161 time stamp support.
* New generalised public key API supporting ENGINE based algorithms.
* New generalised public key API utilities.
* New ENGINE supporting GOST algorithms.
* SSL/TLS GOST ciphersuite support.
* PKCS#7 and CMS GOST support.
* RFC4279 PSK ciphersuite support.
* Supported points format extension for ECC ciphersuites.
* ecdsa-with-SHA224/256/384/512 signature types.
* dsa-with-SHA224 and dsa-with-SHA256 signature types.
* Opaque PRF Input TLS extension support.
* Updated time routines to avoid OS limitations.
OpenSSL 0.9.x
-------------
### Major changes between OpenSSL 0.9.8m and OpenSSL 0.9.8n [24 Mar 2010]
* CFB cipher definition fixes.
* 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]
* Cipher definition fixes.
* Workaround for slow RAND_poll() on some WIN32 versions.
* Remove MD2 from algorithm tables.
* SPKAC handling fixes.
* Support for RFC5746 TLS renegotiation extension.
* Compression memory leak fixed.
* Compression session resumption fixed.
* Ticket and SNI coexistence fixes.
* Many fixes to DTLS handling.
### Major changes between OpenSSL 0.9.8k and OpenSSL 0.9.8l [5 Nov 2009]
* Temporary work around for [CVE-2009-3555]: disable renegotiation.
### Major changes between OpenSSL 0.9.8j and OpenSSL 0.9.8k [25 Mar 2009]
* Fix various build issues.
* 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]
* Fix security issue ([CVE-2008-5077])
* Merge FIPS 140-2 branch code.
### Major changes between OpenSSL 0.9.8g and OpenSSL 0.9.8h [28 May 2008]
* CryptoAPI ENGINE support.
* Various precautionary measures.
* Fix for bugs affecting certificate request creation.
* 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]
* Backport of CMS functionality to 0.9.8.
* Fixes for bugs introduced with 0.9.8f.
### Major changes between OpenSSL 0.9.8e and OpenSSL 0.9.8f [11 Oct 2007]
* Add gcc 4.2 support.
* Add support for AES and SSE2 assembly language optimization
for VC++ build.
* Support for RFC4507bis and server name extensions if explicitly
selected at compile time.
* DTLS improvements.
* RFC4507bis support.
* TLS Extensions support.
### Major changes between OpenSSL 0.9.8d and OpenSSL 0.9.8e [23 Feb 2007]
* Various ciphersuite selection fixes.
* RFC3779 support.
### Major changes between OpenSSL 0.9.8c and OpenSSL 0.9.8d [28 Sep 2006]
* Introduce limits to prevent malicious key DoS ([CVE-2006-2940])
* Fix security issues [CVE-2006-2937], [CVE-2006-3737], [CVE-2006-4343]
* Changes to ciphersuite selection algorithm
### Major changes between OpenSSL 0.9.8b and OpenSSL 0.9.8c [5 Sep 2006]
* Fix Daniel Bleichenbacher forged signature attack, [CVE-2006-4339]
* New cipher Camellia
### Major changes between OpenSSL 0.9.8a and OpenSSL 0.9.8b [4 May 2006]
* Cipher string fixes.
* Fixes for VC++ 2005.
* Updated ECC cipher suite support.
* New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free().
* Zlib compression usage fixes.
* Built in dynamic engine compilation support on Win32.
* Fixes auto dynamic engine loading in Win32.
### Major changes between OpenSSL 0.9.8 and OpenSSL 0.9.8a [11 Oct 2005]
* Fix potential SSL 2.0 rollback ([CVE-2005-2969])
* Extended Windows CE support
### Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.8 [5 Jul 2005]
* 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.
* Addition of BIGNUM functions for fields GF(2^m) and NIST
curves, to support the Elliptic Crypto functions.
* Major work on Elliptic Crypto; ECDH and ECDSA added, including
the use through EVP, X509 and ENGINE.
* New ASN.1 mini-compiler that's usable through the OpenSSL
configuration file.
* Added support for ASN.1 indefinite length constructed encoding.
* New PKCS#12 'medium level' API to manipulate PKCS#12 files.
* Complete rework of shared library construction and linking
programs with shared or static libraries, through a separate
Makefile.shared.
* Rework of the passing of parameters from one Makefile to another.
* Changed ENGINE framework to load dynamic engine modules
automatically from specifically given directories.
* New structure and ASN.1 functions for CertificatePair.
* Changed the ZLIB compression method to be stateful.
* Changed the key-generation and primality testing "progress"
mechanism to take a structure that contains the ticker
function and an argument.
* New engine module: GMP (performs private key exponentiation).
* New engine module: VIA PadLOck ACE extension in VIA C3
Nehemiah processors.
* Added support for IPv6 addresses in certificate extensions.
See RFC 1884, section 2.2.
* Added support for certificate policy mappings, policy
constraints and name constraints.
* Added support for multi-valued AVAs in the OpenSSL
configuration file.
* Added support for multiple certificates with the same subject
in the 'openssl ca' index file.
* Make it possible to create self-signed certificates using
'openssl ca -selfsign'.
* Make it possible to generate a serial number file with
'openssl ca -create_serial'.
* New binary search functions with extended functionality.
* New BUF functions.
* 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.
* New control functions for the error stack.
* Changed the PKCS#7 library to support one-pass S/MIME
processing.
* 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.
* Constification of all ASN.1 conversion functions, and other
affected functions.
* Improved platform support for PowerPC.
* New FIPS 180-2 algorithms (SHA-224, -256, -384 and -512).
* New X509_VERIFY_PARAM structure to support parameterisation
of X.509 path validation.
* Major overhaul of RC4 performance on Intel P4, IA-64 and
AMD64.
* Changed the Configure script to have some algorithms disabled
by default. Those can be explicitly enabled with the new
argument form 'enable-xxx'.
* Change the default digest in 'openssl' commands from MD5 to
SHA-1.
* Added support for DTLS.
* New BIGNUM blinding.
* Added support for the RSA-PSS encryption scheme
* Added support for the RSA X.931 padding.
* Added support for BSD sockets on NetWare.
* Added support for files larger than 2GB.
* Added initial support for Win64.
* Added alternate pkg-config files.
### Major changes between OpenSSL 0.9.7l and OpenSSL 0.9.7m [23 Feb 2007]
* FIPS 1.1.1 module linking.
* Various ciphersuite selection fixes.
### Major changes between OpenSSL 0.9.7k and OpenSSL 0.9.7l [28 Sep 2006]
* Introduce limits to prevent malicious key DoS ([CVE-2006-2940])
* 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]
* Fix Daniel Bleichenbacher forged signature attack, [CVE-2006-4339]
### Major changes between OpenSSL 0.9.7i and OpenSSL 0.9.7j [4 May 2006]
* Visual C++ 2005 fixes.
* Update Windows build system for FIPS.
### Major changes between OpenSSL 0.9.7h and OpenSSL 0.9.7i [14 Oct 2005]
* Give EVP_MAX_MD_SIZE its old value, except for a FIPS build.
### Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.7h [11 Oct 2005]
* Fix SSL 2.0 Rollback ([CVE-2005-2969])
* Allow use of fixed-length exponent on DSA signing
* Default fixed-window RSA, DSA, DH private-key operations
### Major changes between OpenSSL 0.9.7f and OpenSSL 0.9.7g [11 Apr 2005]
* More compilation issues fixed.
* Adaptation to more modern Kerberos API.
* Enhanced or corrected configuration for Solaris64, Mingw and Cygwin.
* Enhanced x86_64 assembler BIGNUM module.
* More constification.
* Added processing of proxy certificates (RFC 3820).
### Major changes between OpenSSL 0.9.7e and OpenSSL 0.9.7f [22 Mar 2005]
* Several compilation issues fixed.
* Many memory allocation failure checks added.
* Improved comparison of X509 Name type.
* Mandatory basic checks on certificates.
* Performance improvements.
### Major changes between OpenSSL 0.9.7d and OpenSSL 0.9.7e [25 Oct 2004]
* Fix race condition in CRL checking code.
* Fixes to PKCS#7 (S/MIME) code.
### Major changes between OpenSSL 0.9.7c and OpenSSL 0.9.7d [17 Mar 2004]
* Security: Fix Kerberos ciphersuite SSL/TLS handshaking bug
* Security: Fix null-pointer assignment in do_change_cipher_spec()
* Allow multiple active certificates with same subject in CA index
* Multiple X509 verification fixes
* Speed up HMAC and other operations
### Major changes between OpenSSL 0.9.7b and OpenSSL 0.9.7c [30 Sep 2003]
* Security: fix various ASN1 parsing bugs.
* New -ignore_err option to OCSP utility.
* Various interop and bug fixes in S/MIME code.
* SSL/TLS protocol fix for unrequested client certificates.
### Major changes between OpenSSL 0.9.7a and OpenSSL 0.9.7b [10 Apr 2003]
* Security: counter the Klima-Pokorny-Rosa extension of
Bleichbacher's attack
* Security: make RSA blinding default.
* Configuration: Irix fixes, AIX fixes, better mingw support.
* Support for new platforms: linux-ia64-ecc.
* Build: shared library support fixes.
* ASN.1: treat domainComponent correctly.
* Documentation: fixes and additions.
### Major changes between OpenSSL 0.9.7 and OpenSSL 0.9.7a [19 Feb 2003]
* Security: Important security related bugfixes.
* Enhanced compatibility with MIT Kerberos.
* Can be built without the ENGINE framework.
* IA32 assembler enhancements.
* Support for new platforms: FreeBSD/IA64 and FreeBSD/Sparc64.
* Configuration: the no-err option now works properly.
* SSL/TLS: now handles manual certificate chain building.
* SSL/TLS: certain session ID malfunctions corrected.
### Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.7 [30 Dec 2002]
* New library section OCSP.
* Complete rewrite of ASN1 code.
* CRL checking in verify code and openssl utility.
* Extension copying in 'ca' utility.
* Flexible display options in 'ca' utility.
* Provisional support for international characters with UTF8.
* Support for external crypto devices ('engine') is no longer
a separate distribution.
* New elliptic curve library section.
* New AES (Rijndael) library section.
* Support for new platforms: Windows CE, Tandem OSS, A/UX, AIX 64-bit,
Linux x86_64, Linux 64-bit on Sparc v9
* Extended support for some platforms: VxWorks
* Enhanced support for shared libraries.
* Now only builds PIC code when shared library support is requested.
* Support for pkg-config.
* Lots of new manuals.
* Makes symbolic links to or copies of manuals to cover all described
functions.
* 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).
* Unify handling of cryptographic algorithms (software and engine)
to be available via EVP routines for asymmetric and symmetric ciphers.
* NCONF: new configuration handling routines.
* Change API to use more 'const' modifiers to improve error checking
and help optimizers.
* Finally remove references to RSAref.
* Reworked parts of the BIGNUM code.
* Support for new engines: Broadcom ubsec, Accelerated Encryption
Processing, IBM 4758.
* A few new engines added in the demos area.
* Extended and corrected OID (object identifier) table.
* PRNG: query at more locations for a random device, automatic query for
EGD style random sources at several locations.
* SSL/TLS: allow optional cipher choice according to server's preference.
* SSL/TLS: allow server to explicitly set new session ids.
* SSL/TLS: support Kerberos cipher suites (RFC2712).
Only supports MIT Kerberos for now.
* SSL/TLS: allow more precise control of renegotiations and sessions.
* SSL/TLS: add callback to retrieve SSL/TLS messages.
* SSL/TLS: support AES cipher suites (RFC3268).
### Major changes between OpenSSL 0.9.6j and OpenSSL 0.9.6k [30 Sep 2003]
* Security: fix various ASN1 parsing bugs.
* SSL/TLS protocol fix for unrequested client certificates.
### Major changes between OpenSSL 0.9.6i and OpenSSL 0.9.6j [10 Apr 2003]
* Security: counter the Klima-Pokorny-Rosa extension of
Bleichbacher's attack
* Security: make RSA blinding default.
* Build: shared library support fixes.
### Major changes between OpenSSL 0.9.6h and OpenSSL 0.9.6i [19 Feb 2003]
* Important security related bugfixes.
### Major changes between OpenSSL 0.9.6g and OpenSSL 0.9.6h [5 Dec 2002]
* New configuration targets for Tandem OSS and A/UX.
* New OIDs for Microsoft attributes.
* Better handling of SSL session caching.
* Better comparison of distinguished names.
* Better handling of shared libraries in a mixed GNU/non-GNU environment.
* Support assembler code with Borland C.
* Fixes for length problems.
* Fixes for uninitialised variables.
* Fixes for memory leaks, some unusual crashes and some race conditions.
* Fixes for smaller building problems.
* Updates of manuals, FAQ and other instructive documents.
### Major changes between OpenSSL 0.9.6f and OpenSSL 0.9.6g [9 Aug 2002]
* Important building fixes on Unix.
### Major changes between OpenSSL 0.9.6e and OpenSSL 0.9.6f [8 Aug 2002]
* Various important bugfixes.
### Major changes between OpenSSL 0.9.6d and OpenSSL 0.9.6e [30 Jul 2002]
* Important security related bugfixes.
* Various SSL/TLS library bugfixes.
### Major changes between OpenSSL 0.9.6c and OpenSSL 0.9.6d [9 May 2002]
* Various SSL/TLS library bugfixes.
* Fix DH parameter generation for 'non-standard' generators.
### Major changes between OpenSSL 0.9.6b and OpenSSL 0.9.6c [21 Dec 2001]
* Various SSL/TLS library bugfixes.
* BIGNUM library fixes.
* RSA OAEP and random number generation fixes.
* Object identifiers corrected and added.
* Add assembler BN routines for IA64.
* Add support for OS/390 Unix, UnixWare with gcc, OpenUNIX 8,
MIPS Linux; shared library support for Irix, HP-UX.
* 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]
* Security fix: PRNG improvements.
* Security fix: RSA OAEP check.
* Security fix: Reinsert and fix countermeasure to Bleichbacher's
attack.
* MIPS bug fix in BIGNUM.
* Bug fix in "openssl enc".
* Bug fix in X.509 printing routine.
* Bug fix in DSA verification routine and DSA S/MIME verification.
* Bug fix to make PRNG thread-safe.
* Bug fix in RAND_file_name().
* Bug fix in compatibility mode trust settings.
* Bug fix in blowfish EVP.
* Increase default size for BIO buffering filter.
* Compatibility fixes in some scripts.
### Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.6a [5 Apr 2001]
* Security fix: change behavior of OpenSSL to avoid using
environment variables when running as root.
* Security fix: check the result of RSA-CRT to reduce the
possibility of deducing the private key from an incorrectly
calculated signature.
* Security fix: prevent Bleichenbacher's DSA attack.
* Security fix: Zero the premaster secret after deriving the
master secret in DH ciphersuites.
* Reimplement SSL_peek(), which had various problems.
* Compatibility fix: the function des_encrypt() renamed to
des_encrypt1() to avoid clashes with some Unixen libc.
* Bug fixes for Win32, HP/UX and Irix.
* Bug fixes in BIGNUM, SSL, PKCS#7, PKCS#12, X.509, CONF and
memory checking routines.
* Bug fixes for RSA operations in threaded environments.
* Bug fixes in misc. openssl applications.
* Remove a few potential memory leaks.
* Add tighter checks of BIGNUM routines.
* Shared library support has been reworked for generality.
* More documentation.
* New function BN_rand_range().
* 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]
* Some documentation for BIO and SSL libraries.
* Enhanced chain verification using key identifiers.
* New sign and verify options to 'dgst' application.
* Support for DER and PEM encoded messages in 'smime' application.
* New 'rsautl' application, low-level RSA utility.
* MD4 now included.
* Bugfix for SSL rollback padding check.
* Support for external crypto devices [1].
* Enhanced EVP interface.
[1] The support for external crypto devices is currently a separate
distribution. See the file README-Engine.md.
### Major changes between OpenSSL 0.9.5 and OpenSSL 0.9.5a [1 Apr 2000]
* Bug fixes for Win32, SuSE Linux, NeXTSTEP and FreeBSD 2.2.8
* Shared library support for HPUX and Solaris-gcc
* Support of Linux/IA64
* Assembler support for Mingw32
* New 'rand' application
* 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]
* S/MIME support in new 'smime' command
* Documentation for the OpenSSL command line application
* Automation of 'req' application
* Fixes to make s_client, s_server work under Windows
* Support for multiple fieldnames in SPKACs
* New SPKAC command line utility and associated library functions
* Options to allow passwords to be obtained from various sources
* New public key PEM format and options to handle it
* Many other fixes and enhancements to command line utilities
* Usable certificate chain verification
* Certificate purpose checking
* Certificate trust settings
* Support of authority information access extension
* Extensions in certificate requests
* Simplified X509 name and attribute routines
* Initial (incomplete) support for international character sets
* New DH_METHOD, DSA_METHOD and enhanced RSA_METHOD
* Read only memory BIOs and simplified creation function
* TLS/SSL protocol bugfixes: Accept TLS 'client hello' in SSL 3.0
record; allow fragmentation and interleaving of handshake and other
data
* TLS/SSL code now "tolerates" MS SGC
* Work around for Netscape client certificate hang bug
* RSA_NULL option that removes RSA patent code but keeps other
RSA functionality
* Memory leak detection now allows applications to add extra information
via a per-thread stack
* PRNG robustness improved
* EGD support
* BIGNUM library bug fixes
* Faster DSA parameter generation
* Enhanced support for Alpha Linux
* Experimental macOS support
### Major changes between OpenSSL 0.9.3 and OpenSSL 0.9.4 [9 Aug 1999]
* Transparent support for PKCS#8 format private keys: these are used
by several software packages and are more secure than the standard
form
* PKCS#5 v2.0 implementation
* Password callbacks have a new void * argument for application data
* Avoid various memory leaks
* 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]
* Lots of enhancements and cleanups to the Configuration mechanism
* RSA OEAP related fixes
* Added "openssl ca -revoke" option for revoking a certificate
* Source cleanups: const correctness, type-safe stacks and ASN.1 SETs
* Source tree cleanups: removed lots of obsolete files
* Thawte SXNet, certificate policies and CRL distribution points
extension support
* Preliminary (experimental) S/MIME support
* Support for ASN.1 UTF8String and VisibleString
* Full integration of PKCS#12 code
* Sparc assembler bignum implementation, optimized hash functions
* Option to disable selected ciphers
### Major changes between OpenSSL 0.9.1c and OpenSSL 0.9.2b [22 Mar 1999]
* Fixed a security hole related to session resumption
* Fixed RSA encryption routines for the p < q case
* "ALL" in cipher lists now means "everything except NULL ciphers"
* Support for Triple-DES CBCM cipher
* Support of Optimal Asymmetric Encryption Padding (OAEP) for RSA
* First support for new TLSv1 ciphers
* Added a few new BIOs (syslog BIO, reliable BIO)
* Extended support for DSA certificate/keys.
* Extended support for Certificate Signing Requests (CSR)
* Initial support for X.509v3 extensions
* Extended support for compression inside the SSL record layer
* Overhauled Win32 builds
* Cleanups and fixes to the Big Number (BN) library
* Support for ASN.1 GeneralizedTime
* Splitted ASN.1 SETs from SEQUENCEs
* ASN1 and PEM support for Netscape Certificate Sequences
* Overhauled Perl interface
* Lots of source tree cleanups.
* Lots of memory leak fixes.
* Lots of bug fixes.
### Major changes between SSLeay 0.9.0b and OpenSSL 0.9.1c [23 Dec 1998]
* Integration of the popular NO_RSA/NO_DSA patches
* Initial support for compression inside the SSL record layer
* Added BIO proxy and filtering functionality
* Extended Big Number (BN) library
* Added RIPE MD160 message digest
* Added support for RC2/64bit cipher
* Extended ASN.1 parser routines
* Adjustments of the source tree for CVS
* Support for various new platforms
<!-- Links -->
+[CVE-2024-13176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-13176
+[CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
[CVE-2024-6119]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-6119
[CVE-2024-5535]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-5535
[CVE-2024-4741]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-4741
[CVE-2024-4603]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-4603
[CVE-2024-2511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-2511
[CVE-2024-0727]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-0727
[CVE-2023-6237]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6237
[CVE-2023-6129]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6129
[CVE-2023-5678]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-5678
[CVE-2023-5363]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-5363
[CVE-2023-4807]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-4807
[CVE-2023-3817]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-3817
[CVE-2023-3446]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-3446
[CVE-2023-2975]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-2975
[CVE-2023-2650]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-2650
[CVE-2023-1255]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-1255
[CVE-2023-0466]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0466
[CVE-2023-0465]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0465
[CVE-2023-0464]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0464
[CVE-2023-0401]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0401
[CVE-2023-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0286
[CVE-2023-0217]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0217
[CVE-2023-0216]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0216
[CVE-2023-0215]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0215
[CVE-2022-4450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4450
[CVE-2022-4304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4304
[CVE-2022-4203]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4203
[CVE-2022-3996]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-3996
[CVE-2022-2274]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274
[CVE-2022-2097]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2097
[CVE-2020-1971]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1971
[CVE-2020-1967]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1967
[CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563
[CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559
[CVE-2019-1552]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1552
[CVE-2019-1551]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1551
[CVE-2019-1549]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1549
[CVE-2019-1547]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1547
[CVE-2019-1543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1543
[CVE-2018-5407]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-5407
[CVE-2018-0739]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0739
[CVE-2018-0737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0737
[CVE-2018-0735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0735
[CVE-2018-0734]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0734
[CVE-2018-0733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0733
[CVE-2018-0732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0732
[CVE-2017-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3738
[CVE-2017-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3737
[CVE-2017-3736]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3736
[CVE-2017-3735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3735
[CVE-2017-3733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3733
[CVE-2017-3732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3732
[CVE-2017-3731]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3731
[CVE-2017-3730]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3730
[CVE-2016-7055]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7055
[CVE-2016-7054]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7054
[CVE-2016-7053]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7053
[CVE-2016-7052]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7052
[CVE-2016-6309]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6309
[CVE-2016-6308]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6308
[CVE-2016-6307]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6307
[CVE-2016-6306]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6306
[CVE-2016-6305]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6305
[CVE-2016-6304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6304
[CVE-2016-6303]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6303
[CVE-2016-6302]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6302
[CVE-2016-2183]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2183
[CVE-2016-2182]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2182
[CVE-2016-2181]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2181
[CVE-2016-2180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2180
[CVE-2016-2179]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2179
[CVE-2016-2178]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2178
[CVE-2016-2177]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2177
[CVE-2016-2176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2176
[CVE-2016-2109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2109
[CVE-2016-2107]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2107
[CVE-2016-2106]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2106
[CVE-2016-2105]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2105
[CVE-2016-0800]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0800
[CVE-2016-0799]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0799
[CVE-2016-0798]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0798
[CVE-2016-0797]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0797
[CVE-2016-0705]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0705
[CVE-2016-0702]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0702
[CVE-2016-0701]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0701
[CVE-2015-3197]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3197
[CVE-2015-3196]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3196
[CVE-2015-3195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3195
[CVE-2015-3194]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3194
[CVE-2015-3193]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3193
[CVE-2015-1793]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1793
[CVE-2015-1792]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1792
[CVE-2015-1791]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1791
[CVE-2015-1790]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1790
[CVE-2015-1789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1789
[CVE-2015-1788]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1788
[CVE-2015-1787]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1787
[CVE-2015-0293]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0293
[CVE-2015-0291]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0291
[CVE-2015-0290]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0290
[CVE-2015-0289]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0289
[CVE-2015-0288]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0288
[CVE-2015-0287]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0287
[CVE-2015-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0286
[CVE-2015-0285]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0285
[CVE-2015-0209]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0209
[CVE-2015-0208]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0208
[CVE-2015-0207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0207
[CVE-2015-0206]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0206
[CVE-2015-0205]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0205
[CVE-2015-0204]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0204
[CVE-2014-8275]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-8275
[CVE-2014-5139]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-5139
[CVE-2014-3572]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3572
[CVE-2014-3571]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3571
[CVE-2014-3570]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3570
[CVE-2014-3569]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3569
[CVE-2014-3568]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3568
[CVE-2014-3567]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3567
[CVE-2014-3566]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3566
[CVE-2014-3513]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3513
[CVE-2014-3512]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3512
[CVE-2014-3511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3511
[CVE-2014-3510]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3510
[CVE-2014-3509]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3509
[CVE-2014-3508]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3508
[CVE-2014-3507]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3507
[CVE-2014-3506]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3506
[CVE-2014-3505]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3505
[CVE-2014-3470]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3470
[CVE-2014-0224]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0224
[CVE-2014-0221]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0221
[CVE-2014-0198]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0198
[CVE-2014-0195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0195
[CVE-2014-0160]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0160
[CVE-2014-0076]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0076
[CVE-2013-6450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6450
[CVE-2013-6449]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6449
[CVE-2013-4353]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-4353
[CVE-2013-0169]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0169
[CVE-2013-0166]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0166
[CVE-2012-2686]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2686
[CVE-2012-2333]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2333
[CVE-2012-2110]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2110
[CVE-2012-0884]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0884
[CVE-2012-0050]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0050
[CVE-2012-0027]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0027
[CVE-2011-4619]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4619
[CVE-2011-4577]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4577
[CVE-2011-4576]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4576
[CVE-2011-4108]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4108
[CVE-2011-3210]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3210
[CVE-2011-3207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3207
[CVE-2011-0014]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-0014
[CVE-2010-5298]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-5298
[CVE-2010-4252]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4252
[CVE-2010-4180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4180
[CVE-2010-3864]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-3864
[CVE-2010-2939]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-2939
[CVE-2010-1633]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-1633
[CVE-2010-0740]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0740
[CVE-2010-0433]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0433
[CVE-2009-3555]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3555
[CVE-2009-0789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0789
[CVE-2009-0591]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0591
[CVE-2009-0590]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0590
[CVE-2008-5077]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-5077
[CVE-2006-4343]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4343
[CVE-2006-4339]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4339
[CVE-2006-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-3737
[CVE-2006-2940]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2940
[CVE-2006-2937]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2937
[CVE-2005-2969]: https://www.openssl.org/news/vulnerabilities.html#CVE-2005-2969
diff --git a/crypto/openssl/NOTES-NONSTOP.md b/crypto/openssl/NOTES-NONSTOP.md
index ab13de7d3a76..9441647604c7 100644
--- a/crypto/openssl/NOTES-NONSTOP.md
+++ b/crypto/openssl/NOTES-NONSTOP.md
@@ -1,262 +1,259 @@
NOTES FOR THE HPE NONSTOP PLATFORM
==============================
Requirement details
-------------------
In addition to the requirements and instructions listed
in [INSTALL.md](INSTALL.md), the following are required as well:
* The TNS/X platform supports hardware randomization.
Specify the `--with-rand-seed=rdcpu` option to the `./Configure` script.
This is recommended but not required. `egd` is supported at 3.0 but cannot
be used if FIPS is selected.
* The TNS/E platform does not support hardware randomization, so
specify the `--with-rand-seed=egd` option to the `./Configure` script.
About c99 compiler
------------------
The c99 compiler is required for building OpenSSL from source. While c11
may work, it has not been broadly tested. c99 is the only compiler
prerequisite needed to build OpenSSL 3.0 on this platform. You should also
have the FLOSS package installed on your system. The ITUGLIB FLOSS package
is the only FLOSS variant that has been broadly tested.
Threading Models
----------------
OpenSSL can be built using unthreaded, POSIX User Threads (PUT), or Standard
POSIX Threads (SPT). Select the following build configuration for each on
the TNS/X (L-Series) platform:
* `nonstop-nsx` or default will select an unthreaded build.
* `nonstop-nsx_put` selects the PUT build.
* `nonstop-nsx_64_put` selects the 64 bit file length PUT build.
* `nonstop-nsx_spt_floss` selects the SPT build with FLOSS. FLOSS is
required for SPT builds because of a known hang when using SPT on its own.
### TNS/E Considerations
The TNS/E platform is build using the same set of builds specifying `nse`
instead of `nsx` in the set above.
You cannot build for TNS/E for FIPS, so you must specify the `no-fips`
option to `./Configure`.
Linking and Loading Considerations
----------------------------------
Because of how the NonStop Common Runtime Environment (CRE) works, there are
restrictions on how programs can link and load with OpenSSL libraries.
On current NonStop platforms, programs cannot both statically link OpenSSL
libraries and dynamically load OpenSSL shared libraries concurrently. If this
is done, there is a high probability of encountering a SIGSEGV condition
relating to `atexit()` processing when a shared library is unloaded and when
the program terminates. This limitation applies to all OpenSSL shared library
components.
It is possible to configure the build with `no-atexit` to avoid the SIGSEGV.
Preferably, you can explicitly call `OPENSSL_cleanup()` from your application.
It is not mandatory as it just deallocates various global data structures
OpenSSL allocated.
About Prefix and OpenSSLDir
---------------------------
Because there are many potential builds that must co-exist on any given
NonStop node, managing the location of your build distribution is crucial.
Keep each destination separate and distinct. Mixing any mode described in
this document can cause application instability. The recommended approach
is to specify the OpenSSL version and threading model in your configuration
options, and keeping your memory and float options consistent, for example:
* For 1.1 `--prefix=/usr/local-ssl1.1 --openssldir=/usr/local-ssl1.1/ssl`
* For 1.1 PUT `--prefix=/usr/local-ssl1.1_put --openssldir=/usr/local-ssl1.1_put/ssl`
As of 3.0, the NonStop configurations use the multilib attribute to distinguish
between different models:
* For 3.0 `--prefix=/usr/local-ssl3.0 --openssldir=/usr/local-ssl3.0/ssl`
The PUT model is placed in `${prefix}/lib-put` for 32-bit models and
`${prefix}/lib64-put` for 64-bit models.
Use the `_RLD_LIB_PATH` environment variable in OSS to select the appropriate
directory containing `libcrypto.so` and `libssl.so`. In GUARDIAN, use the
`=_RLD_LIB_PATH` search define to locate the GUARDIAN subvolume where OpenSSL
is installed.
Float Considerations
--------------------
OpenSSL is built using IEEE Float mode by default. If you need a different
IEEE mode, create a new configuration specifying `tfloat-x86-64` (for Tandem
Float) or `nfloat-x86-64` (for Neutral Float).
Memory Models
-------------
The current OpenSSL default memory model uses the default platform address
model. If you need a different address model, you must specify the appropriate
c99 options for compile (`CFLAGS`) and linkers (`LDFLAGS`).
Cross Compiling on Windows
--------------------------
To configure and compile OpenSSL, you will need to set up a Cygwin environment.
The Cygwin tools should include bash, make, and any other normal tools required
for building programs.
Your `PATH` must include the bin directory for the c99 cross-compiler, as in:
export PATH=/cygdrive/c/Program\ Files\ \(x86\)/HPE\ NonStop/L16.05/usr/bin:$PATH
This should be set before Configure is run. For the c99 cross-compiler to work
correctly, you also need the `COMP_ROOT` set, as in:
export COMP_ROOT="C:\Program Files (x86)\HPE NonStop\L16.05"
`COMP_ROOT` needs to be in Windows form.
-`Configure` must specify the `no-makedepend` option otherwise errors will
-result when running the build because the c99 cross-compiler does not support
-the `gcc -MT` option. An example of a `Configure` command to be run from the
-OpenSSL directory is:
+An example of a `Configure` command to be run from the OpenSSL directory is:
- ./Configure nonstop-nsx_64 no-makedepend --with-rand-seed=rdcpu
+ ./Configure nonstop-nsx_64 --with-rand-seed=rdcpu
Do not forget to include any OpenSSL cross-compiling prefix and certificate
options when creating your libraries.
The OpenSSL test suite will not run on your workstation. In order to verify the
build, you will need to perform the build and test steps in OSS in your NonStop
server. You can also build under gcc and run the test suite for Windows but that
is not equivalent.
**Note:** In the event that you are attempting a FIPS-compliant cross-compile,
be aware that signatures may not match between builds done under OSS and under
cross-compiles as the compilers do not necessarily generate identical objects.
Anything and everything to do with FIPS is outside the scope of this document.
Refer to the FIPS security policy for more information.
The following build configurations have been successfully attempted at one
point or another. If you are successful in your cross-compile efforts, please
update this list:
- nonstop-nsx_64
- nonstop-nsx_64_put
**Note:** Cross-compile builds for TNS/E have not been attempted, but should
follow the same considerations as for TNS/X above. SPT builds generally require
FLOSS, which is not available for workstation builds. As a result, SPT builds
of OpenSSL cannot be cross-compiled.
Also see the NSDEE discussion below for more historical information.
Cross Compiling with NSDEE
--------------------------
**Note:** None of these builds have been tested by the platform maintainer and
are supplied for historical value. Please submit a Pull Request to OpenSSL
should these need to be adjusted.
If you are attempting to build OpenSSL with NSDEE, you will need to specify
the following variables. The following set of compiler defines are required:
# COMP_ROOT must be a full path for the build system (e.g. windows)
COMP_ROOT=$(cygpath -w /path/to/comp_root)
# CC must be executable by your shell
CC=/path/to/c99
### Optional Build Variables
DBGFLAG="--debug"
CIPHENABLES="enable-ssl3 enable-ssl3-method enable-weak-ssl-ciphers enable-rc4"
### Internal Known TNS/X to TNS/E Cross Compile Variables
The following definition is required if you are building on TNS/X for TNS/E
and have access to a TNS/E machine on your EXPAND network - with an example
node named `\CS3`:
SYSTEMLIBS="-L/E/cs3/usr/local/lib"
Version Procedure (VPROC) Considerations
----------------------------------------
If you require a VPROC entry for platform version identification, use the
following variables:
### For Itanium
OPENSSL_VPROC_PREFIX=T0085H06
### For x86
OPENSSL_VPROC_PREFIX=T0085L01
### Common Definition
export OPENSSL_VPROC=${OPENSSL_VPROC_PREFIX}_$(
. VERSION.dat
if [ -n "$PRE_RELEASE_TAG" ]; then
PRE_RELEASE_TAG="-$PRE_RELEASE_TAG"
fi
if [ -n "$BUILD_METADATA" ]; then
BUILD_METADATA="+$BUILD_METADATA"
fi
echo "$MAJOR.$MINOR.$PATCH$PRE_RELEASE_TAG$BUILD_METADATA" |\
sed -e 's/[-.+]/_/g'
)
Example Configure Targets
-------------------------
For OSS targets, the main DLL names will be `libssl.so` and `libcrypto.so`.
For GUARDIAN targets, DLL names will be `ssl` and `crypto`. The following
assumes that your PWD is set according to your installation standards.
./Configure nonstop-nsx --prefix=${PWD} \
--openssldir=${PWD}/ssl no-threads \
--with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nsx_g --prefix=${PWD} \
--openssldir=${PWD}/ssl no-threads \
--with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nsx_put --prefix=${PWD} \
--openssldir=${PWD}/ssl threads "-D_REENTRANT" \
--with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nsx_spt_floss --prefix=${PWD} \
--openssldir=${PWD}/ssl threads "-D_REENTRANT" \
--with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nsx_64 --prefix=${PWD} \
--openssldir=${PWD}/ssl no-threads \
--with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nsx_64_put --prefix=${PWD} \
--openssldir=${PWD}/ssl threads "-D_REENTRANT" \
--with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nsx_g_tandem --prefix=${PWD} \
--openssldir=${PWD}/ssl no-threads \
--with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nse --prefix=${PWD} \
--openssldir=${PWD}/ssl no-threads \
--with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nse_g --prefix=${PWD} \
--openssldir=${PWD}/ssl no-threads \
--with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nse_put --prefix=${PWD} \
--openssldir=${PWD}/ssl threads "-D_REENTRANT" \
--with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nse_spt_floss --prefix=${PWD} \
--openssldir=${PWD}/ssl threads "-D_REENTRANT" \
--with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nse_64 --prefix=${PWD} \
--openssldir=${PWD}/ssl no-threads \
--with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nse_64_put --prefix=${PWD} \
--openssldir=${PWD}/ssl threads "-D_REENTRANT"
--with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
./Configure nonstop-nse_g_tandem --prefix=${PWD} \
--openssldir=${PWD}/ssl no-threads \
--with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
diff --git a/crypto/openssl/README.md b/crypto/openssl/README.md
index 5184a461bb17..477f5cbb7d12 100644
--- a/crypto/openssl/README.md
+++ b/crypto/openssl/README.md
@@ -1,224 +1,212 @@
Welcome to the OpenSSL Project
==============================
[![openssl logo]][www.openssl.org]
[![github actions ci badge]][github actions ci]
[![appveyor badge]][appveyor jobs]
OpenSSL is a robust, commercial-grade, full-featured Open Source Toolkit
for the Transport Layer Security (TLS) protocol formerly known as the
Secure Sockets Layer (SSL) protocol. The protocol implementation is based
on a full-strength general purpose cryptographic library, which can also
be used stand-alone.
OpenSSL is descended from the SSLeay library developed by Eric A. Young
and Tim J. Hudson.
The official Home Page of the OpenSSL Project is [www.openssl.org].
Table of Contents
=================
- [Overview](#overview)
- [Download](#download)
- [Build and Install](#build-and-install)
- [Documentation](#documentation)
- [License](#license)
- [Support](#support)
- [Contributing](#contributing)
- [Legalities](#legalities)
Overview
========
The OpenSSL toolkit includes:
- **libssl**
an implementation of all TLS protocol versions up to TLSv1.3 ([RFC 8446]).
- **libcrypto**
a full-strength general purpose cryptographic library. It constitutes the
basis of the TLS implementation, but can also be used independently.
- **openssl**
the OpenSSL command line tool, a swiss army knife for cryptographic tasks,
testing and analyzing. It 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...
Download
========
For Production Use
------------------
Source code tarballs of the official releases can be downloaded from
-[www.openssl.org/source](https://www.openssl.org/source).
+[openssl-library.org/source/](https://openssl-library.org/source/).
The OpenSSL project does not distribute the toolkit in binary form.
However, for a large variety of operating systems precompiled versions
of the OpenSSL toolkit are available. In particular on Linux and other
Unix operating systems it is normally recommended to link against the
precompiled shared libraries provided by the distributor or vendor.
For Testing and Development
---------------------------
Although testing and development could in theory also be done using
the source tarballs, having a local copy of the git repository with
the entire project history gives you much more insight into the
code base.
-The official OpenSSL Git Repository is located at [git.openssl.org].
-There is a GitHub mirror of the repository at [github.com/openssl/openssl],
+The main OpenSSL Git repository is private.
+There is a public GitHub mirror of it at [github.com/openssl/openssl],
which is updated automatically from the former on every commit.
-A local copy of the Git Repository can be obtained by cloning it from
-the original OpenSSL repository using
-
- git clone git://git.openssl.org/openssl.git
-
-or from the GitHub mirror using
+A local copy of the Git repository can be obtained by cloning it from
+the GitHub mirror using
git clone https://github.com/openssl/openssl.git
If you intend to contribute to OpenSSL, either to fix bugs or contribute
-new features, you need to fork the OpenSSL repository openssl/openssl on
-GitHub and clone your public fork instead.
+new features, you need to fork the GitHub mirror and clone your public fork
+instead.
git clone https://github.com/yourname/openssl.git
This is necessary, because all development of OpenSSL nowadays is done via
GitHub pull requests. For more details, see [Contributing](#contributing).
Build and Install
=================
After obtaining the Source, have a look at the [INSTALL](INSTALL.md) file for
detailed instructions about building and installing OpenSSL. For some
platforms, the installation instructions are amended by a platform specific
document.
* [Notes for UNIX-like platforms](NOTES-UNIX.md)
* [Notes for Android platforms](NOTES-ANDROID.md)
* [Notes for Windows platforms](NOTES-WINDOWS.md)
* [Notes for the DOS platform with DJGPP](NOTES-DJGPP.md)
* [Notes for the OpenVMS platform](NOTES-VMS.md)
* [Notes on Perl](NOTES-PERL.md)
* [Notes on Valgrind](NOTES-VALGRIND.md)
Specific notes on upgrading to OpenSSL 3.0 from previous versions can be found
in the [migration_guide(7ossl)] manual page.
Documentation
=============
Manual Pages
------------
The manual pages for the master branch and all current stable releases are
available online.
- [OpenSSL master](https://www.openssl.org/docs/manmaster)
- [OpenSSL 3.0](https://www.openssl.org/docs/man3.0)
- [OpenSSL 1.1.1](https://www.openssl.org/docs/man1.1.1)
Wiki
----
There is a Wiki at [wiki.openssl.org] which is currently not very active.
It contains a lot of useful information, not all of which is up to date.
License
=======
OpenSSL is licensed under the Apache License 2.0, which means that
you are free to get and use it for commercial and non-commercial
purposes as long as you fulfill its conditions.
See the [LICENSE.txt](LICENSE.txt) file for more details.
Support
=======
There are various ways to get in touch. The correct channel depends on
your requirement. see the [SUPPORT](SUPPORT.md) file for more details.
Contributing
============
If you are interested and willing to contribute to the OpenSSL project,
please take a look at the [CONTRIBUTING](CONTRIBUTING.md) file.
Legalities
==========
A number of nations restrict the use or export of cryptography. If you are
potentially subject to such restrictions you should seek legal advice before
attempting to develop or distribute cryptographic code.
Copyright
=========
-Copyright (c) 1998-2024 The OpenSSL Project
+Copyright (c) 1998-2025 The OpenSSL Project
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
All rights reserved.
<!-- Links -->
[www.openssl.org]:
<https://www.openssl.org>
"OpenSSL Homepage"
-[git.openssl.org]:
- <https://git.openssl.org>
- "OpenSSL Git Repository"
-
-[git.openssl.org]:
- <https://git.openssl.org>
- "OpenSSL Git Repository"
-
[github.com/openssl/openssl]:
<https://github.com/openssl/openssl>
"OpenSSL GitHub Mirror"
[wiki.openssl.org]:
<https://wiki.openssl.org>
"OpenSSL Wiki"
[migration_guide(7ossl)]:
<https://www.openssl.org/docs/man3.0/man7/migration_guide.html>
"OpenSSL Migration Guide"
[RFC 8446]:
<https://tools.ietf.org/html/rfc8446>
<!-- Logos and Badges -->
[openssl logo]:
doc/images/openssl.svg
"OpenSSL Logo"
[github actions ci badge]:
<https://github.com/openssl/openssl/workflows/GitHub%20CI/badge.svg>
"GitHub Actions CI Status"
[github actions ci]:
<https://github.com/openssl/openssl/actions?query=workflow%3A%22GitHub+CI%22>
"GitHub Actions CI"
[appveyor badge]:
<https://ci.appveyor.com/api/projects/status/8e10o7xfrg73v98f/branch/master?svg=true>
"AppVeyor Build Status"
[appveyor jobs]:
<https://ci.appveyor.com/project/openssl/openssl/branch/master>
"AppVeyor Jobs"
diff --git a/crypto/openssl/VERSION.dat b/crypto/openssl/VERSION.dat
index 0942ddc200ca..4b7eb91a451a 100644
--- a/crypto/openssl/VERSION.dat
+++ b/crypto/openssl/VERSION.dat
@@ -1,7 +1,7 @@
MAJOR=3
MINOR=0
-PATCH=15
+PATCH=16
PRE_RELEASE_TAG=
BUILD_METADATA=
-RELEASE_DATE="3 Sep 2024"
+RELEASE_DATE="11 Feb 2025"
SHLIB_VERSION=3
diff --git a/crypto/openssl/apps/asn1parse.c b/crypto/openssl/apps/asn1parse.c
index f0bfd1d45fc4..129b867c8cc7 100644
--- a/crypto/openssl/apps/asn1parse.c
+++ b/crypto/openssl/apps/asn1parse.c
@@ -1,362 +1,363 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "apps.h"
#include "progs.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/asn1t.h>
typedef enum OPTION_choice {
OPT_COMMON,
OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT,
OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT,
OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM,
OPT_ITEM
} OPTION_CHOICE;
const OPTIONS asn1parse_options[] = {
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"oid", OPT_OID, '<', "file of extra oid definitions"},
OPT_SECTION("I/O"),
{"inform", OPT_INFORM, 'F', "input format - one of DER PEM"},
{"in", OPT_IN, '<', "input file"},
{"out", OPT_OUT, '>', "output file (output format is always DER)"},
{"noout", OPT_NOOUT, 0, "do not produce any output"},
{"offset", OPT_OFFSET, 'p', "offset into file"},
{"length", OPT_LENGTH, 'p', "length of section in file"},
{"strparse", OPT_STRPARSE, 'p',
"offset; a series of these can be used to 'dig'"},
{"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"},
{OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"},
{"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"},
{"strictpem", OPT_STRICTPEM, 0,
"do not attempt base64 decode outside PEM markers"},
{"item", OPT_ITEM, 's', "item to parse and print"},
{OPT_MORE_STR, 0, 0, "(-inform will be ignored)"},
OPT_SECTION("Formatting"),
{"i", OPT_INDENT, 0, "indents the output"},
{"dump", OPT_DUMP, 0, "unknown data in hex form"},
{"dlimit", OPT_DLIMIT, 'p',
"dump the first arg bytes of unknown data in hex form"},
{NULL}
};
static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf);
int asn1parse_main(int argc, char **argv)
{
ASN1_TYPE *at = NULL;
BIO *in = NULL, *b64 = NULL, *derout = NULL;
BUF_MEM *buf = NULL;
STACK_OF(OPENSSL_STRING) *osk = NULL;
char *genstr = NULL, *genconf = NULL;
char *infile = NULL, *oidfile = NULL, *derfile = NULL;
unsigned char *str = NULL;
char *name = NULL, *header = NULL, *prog;
const unsigned char *ctmpbuf;
int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM;
int offset = 0, ret = 1, i, j;
long num, tmplen;
unsigned char *tmpbuf;
unsigned int length = 0;
OPTION_CHOICE o;
const ASN1_ITEM *it = NULL;
prog = opt_init(argc, argv, asn1parse_options);
if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) {
BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
goto end;
}
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(asn1parse_options);
ret = 0;
goto end;
case OPT_INFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
goto opthelp;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUT:
derfile = opt_arg();
break;
case OPT_INDENT:
indent = 1;
break;
case OPT_NOOUT:
noout = 1;
break;
case OPT_OID:
oidfile = opt_arg();
break;
case OPT_OFFSET:
offset = strtol(opt_arg(), NULL, 0);
break;
case OPT_LENGTH:
length = strtol(opt_arg(), NULL, 0);
break;
case OPT_DUMP:
dump = -1;
break;
case OPT_DLIMIT:
dump = strtol(opt_arg(), NULL, 0);
break;
case OPT_STRPARSE:
- sk_OPENSSL_STRING_push(osk, opt_arg());
+ if (sk_OPENSSL_STRING_push(osk, opt_arg()) <= 0)
+ goto end;
break;
case OPT_GENSTR:
genstr = opt_arg();
break;
case OPT_GENCONF:
genconf = opt_arg();
break;
case OPT_STRICTPEM:
strictpem = 1;
informat = FORMAT_PEM;
break;
case OPT_ITEM:
it = ASN1_ITEM_lookup(opt_arg());
if (it == NULL) {
size_t tmp;
BIO_printf(bio_err, "Unknown item name %s\n", opt_arg());
BIO_puts(bio_err, "Supported types:\n");
for (tmp = 0;; tmp++) {
it = ASN1_ITEM_get(tmp);
if (it == NULL)
break;
BIO_printf(bio_err, " %s\n", it->sname);
}
goto end;
}
break;
}
}
/* No extra args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
if (oidfile != NULL) {
in = bio_open_default(oidfile, 'r', FORMAT_TEXT);
if (in == NULL)
goto end;
OBJ_create_objects(in);
BIO_free(in);
}
if ((in = bio_open_default(infile, 'r', informat)) == NULL)
goto end;
if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL)
goto end;
if ((buf = BUF_MEM_new()) == NULL)
goto end;
if (strictpem) {
if (PEM_read_bio(in, &name, &header, &str, &num) != 1) {
BIO_printf(bio_err, "Error reading PEM file\n");
ERR_print_errors(bio_err);
goto end;
}
buf->data = (char *)str;
buf->length = buf->max = num;
} else {
if (!BUF_MEM_grow(buf, BUFSIZ * 8))
goto end; /* Pre-allocate :-) */
if (genstr || genconf) {
num = do_generate(genstr, genconf, buf);
if (num < 0) {
ERR_print_errors(bio_err);
goto end;
}
} else {
if (informat == FORMAT_PEM) {
BIO *tmp;
if ((b64 = BIO_new(BIO_f_base64())) == NULL)
goto end;
BIO_push(b64, in);
tmp = in;
in = b64;
b64 = tmp;
}
num = 0;
for (;;) {
if (!BUF_MEM_grow(buf, num + BUFSIZ))
goto end;
i = BIO_read(in, &(buf->data[num]), BUFSIZ);
if (i <= 0)
break;
num += i;
}
}
str = (unsigned char *)buf->data;
}
/* If any structs to parse go through in sequence */
if (sk_OPENSSL_STRING_num(osk)) {
tmpbuf = str;
tmplen = num;
for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) {
ASN1_TYPE *atmp;
int typ;
j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0);
if (j <= 0 || j >= tmplen) {
BIO_printf(bio_err, "'%s' is out of range\n",
sk_OPENSSL_STRING_value(osk, i));
continue;
}
tmpbuf += j;
tmplen -= j;
atmp = at;
ctmpbuf = tmpbuf;
at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen);
ASN1_TYPE_free(atmp);
if (!at) {
BIO_printf(bio_err, "Error parsing structure\n");
ERR_print_errors(bio_err);
goto end;
}
typ = ASN1_TYPE_get(at);
if ((typ == V_ASN1_OBJECT)
|| (typ == V_ASN1_BOOLEAN)
|| (typ == V_ASN1_NULL)) {
BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ));
ERR_print_errors(bio_err);
goto end;
}
/* hmm... this is a little evil but it works */
tmpbuf = at->value.asn1_string->data;
tmplen = at->value.asn1_string->length;
}
str = tmpbuf;
num = tmplen;
}
if (offset < 0 || offset >= num) {
BIO_printf(bio_err, "Error: offset out of range\n");
goto end;
}
num -= offset;
if (length == 0 || length > (unsigned int)num)
length = (unsigned int)num;
if (derout != NULL) {
if (BIO_write(derout, str + offset, length) != (int)length) {
BIO_printf(bio_err, "Error writing output\n");
ERR_print_errors(bio_err);
goto end;
}
}
if (!noout) {
const unsigned char *p = str + offset;
if (it != NULL) {
ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it);
if (value == NULL) {
BIO_printf(bio_err, "Error parsing item %s\n", it->sname);
ERR_print_errors(bio_err);
goto end;
}
ASN1_item_print(bio_out, value, 0, it, NULL);
ASN1_item_free(value, it);
} else {
if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) {
ERR_print_errors(bio_err);
goto end;
}
}
}
ret = 0;
end:
BIO_free(derout);
BIO_free(in);
BIO_free(b64);
if (ret != 0)
ERR_print_errors(bio_err);
BUF_MEM_free(buf);
OPENSSL_free(name);
OPENSSL_free(header);
ASN1_TYPE_free(at);
sk_OPENSSL_STRING_free(osk);
return ret;
}
static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf)
{
CONF *cnf = NULL;
int len;
unsigned char *p;
ASN1_TYPE *atyp = NULL;
if (genconf != NULL) {
if ((cnf = app_load_config(genconf)) == NULL)
goto err;
if (genstr == NULL)
genstr = NCONF_get_string(cnf, "default", "asn1");
if (genstr == NULL) {
BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf);
goto err;
}
}
atyp = ASN1_generate_nconf(genstr, cnf);
NCONF_free(cnf);
cnf = NULL;
if (atyp == NULL)
return -1;
len = i2d_ASN1_TYPE(atyp, NULL);
if (len <= 0)
goto err;
if (!BUF_MEM_grow(buf, len))
goto err;
p = (unsigned char *)buf->data;
i2d_ASN1_TYPE(atyp, &p);
ASN1_TYPE_free(atyp);
return len;
err:
NCONF_free(cnf);
ASN1_TYPE_free(atyp);
return -1;
}
diff --git a/crypto/openssl/apps/cms.c b/crypto/openssl/apps/cms.c
index abb9f196a760..dce227ef2db5 100644
--- a/crypto/openssl/apps/cms.c
+++ b/crypto/openssl/apps/cms.c
@@ -1,1457 +1,1474 @@
/*
- * Copyright 2008-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* CMS utility function */
#include <stdio.h>
#include <string.h>
#include "apps.h"
#include "progs.h"
#include <openssl/crypto.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/x509_vfy.h>
#include <openssl/x509v3.h>
#include <openssl/cms.h>
static int save_certs(char *signerfile, STACK_OF(X509) *signers);
static int cms_cb(int ok, X509_STORE_CTX *ctx);
static void receipt_request_print(CMS_ContentInfo *cms);
static CMS_ReceiptRequest
*make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
STACK_OF(OPENSSL_STRING) *rr_from);
static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
STACK_OF(OPENSSL_STRING) *param);
#define SMIME_OP 0x100
#define SMIME_IP 0x200
#define SMIME_SIGNERS 0x400
#define SMIME_ENCRYPT (1 | SMIME_OP)
#define SMIME_DECRYPT (2 | SMIME_IP)
#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
#define SMIME_VERIFY (4 | SMIME_IP)
#define SMIME_RESIGN (5 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
#define SMIME_SIGN_RECEIPT (6 | SMIME_IP | SMIME_OP)
#define SMIME_VERIFY_RECEIPT (7 | SMIME_IP)
#define SMIME_DIGEST_CREATE (8 | SMIME_OP)
#define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
#define SMIME_COMPRESS (10 | SMIME_OP)
#define SMIME_UNCOMPRESS (11 | SMIME_IP)
#define SMIME_ENCRYPTED_ENCRYPT (12 | SMIME_OP)
#define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
#define SMIME_DATA_CREATE (14 | SMIME_OP)
#define SMIME_DATA_OUT (15 | SMIME_IP)
#define SMIME_CMSOUT (16 | SMIME_IP | SMIME_OP)
static int verify_err = 0;
typedef struct cms_key_param_st cms_key_param;
struct cms_key_param_st {
int idx;
STACK_OF(OPENSSL_STRING) *param;
cms_key_param *next;
};
typedef enum OPTION_choice {
OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN,
OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT,
OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS,
OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID,
OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF,
OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT,
OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE,
OPT_CAPATH, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
OPT_CONTENT, OPT_PRINT, OPT_NAMEOPT,
OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE,
OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM,
OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
OPT_3DES_WRAP, OPT_WRAP, OPT_ENGINE,
OPT_R_ENUM,
OPT_PROV_ENUM, OPT_CONFIG,
OPT_V_ENUM,
OPT_CIPHER,
OPT_ORIGINATOR
} OPTION_CHOICE;
const OPTIONS cms_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"},
{"help", OPT_HELP, '-', "Display this summary"},
OPT_SECTION("General"),
{"in", OPT_IN, '<', "Input file"},
{"out", OPT_OUT, '>', "Output file"},
OPT_CONFIG_OPTION,
OPT_SECTION("Operation"),
{"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
{"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
{"sign", OPT_SIGN, '-', "Sign message"},
{"verify", OPT_VERIFY, '-', "Verify signed message"},
{"resign", OPT_RESIGN, '-', "Resign a signed message"},
{"sign_receipt", OPT_SIGN_RECEIPT, '-',
"Generate a signed receipt for a message"},
{"verify_receipt", OPT_VERIFY_RECEIPT, '<',
"Verify receipts; exit if receipt signatures do not verify"},
{"digest_create", OPT_DIGEST_CREATE, '-',
"Create a CMS \"DigestedData\" object"},
{"digest_verify", OPT_DIGEST_VERIFY, '-',
"Verify a CMS \"DigestedData\" object and output it"},
{"compress", OPT_COMPRESS, '-', "Create a CMS \"CompressedData\" object"},
{"uncompress", OPT_UNCOMPRESS, '-',
"Uncompress a CMS \"CompressedData\" object"},
{"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-',
"Create CMS \"EncryptedData\" object using symmetric key"},
{"EncryptedData_decrypt", OPT_ED_DECRYPT, '-',
"Decrypt CMS \"EncryptedData\" object using symmetric key"},
{"data_create", OPT_DATA_CREATE, '-', "Create a CMS \"Data\" object"},
{"data_out", OPT_DATA_OUT, '-', "Copy CMS \"Data\" object to output"},
{"cmsout", OPT_CMSOUT, '-', "Output CMS structure"},
OPT_SECTION("File format"),
{"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
{"outform", OPT_OUTFORM, 'c',
"Output format SMIME (default), PEM or DER"},
{"rctform", OPT_RCTFORM, 'F', "Receipt file format"},
{"stream", OPT_INDEF, '-', "Enable CMS streaming"},
{"indef", OPT_INDEF, '-', "Same as -stream"},
{"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
{"binary", OPT_BINARY, '-',
"Treat input as binary: do not translate to canonical form"},
{"crlfeol", OPT_CRLFEOL, '-',
"Use CRLF as EOL termination instead of LF only" },
{"asciicrlf", OPT_ASCIICRLF, '-',
"Perform CRLF canonicalisation when signing"},
OPT_SECTION("Keys and passwords"),
{"pwri_password", OPT_PWRI_PASSWORD, 's',
"Specific password for recipient"},
{"secretkey", OPT_SECRETKEY, 's',
"Use specified hex-encoded key to decrypt/encrypt recipients or content"},
{"secretkeyid", OPT_SECRETKEYID, 's',
"Identity of the -secretkey for CMS \"KEKRecipientInfo\" object"},
{"inkey", OPT_INKEY, 's',
"Input private key (if not signer or recipient)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"},
{"keyform", OPT_KEYFORM, 'f',
"Input private key format (ENGINE, other values ignored)"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
#endif
OPT_PROV_OPTIONS,
OPT_R_OPTIONS,
OPT_SECTION("Encryption and decryption"),
{"originator", OPT_ORIGINATOR, 's', "Originator certificate file"},
{"recip", OPT_RECIP, '<', "Recipient cert file"},
{"cert...", OPT_PARAM, '.',
"Recipient certs (optional; used only when encrypting)"},
{"", OPT_CIPHER, '-',
"The encryption algorithm to use (any supported cipher)"},
{"wrap", OPT_WRAP, 's',
"Key wrap algorithm to use when encrypting with key agreement"},
{"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
{"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
{"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"},
{"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
{"debug_decrypt", OPT_DEBUG_DECRYPT, '-',
"Disable MMA protection, return error if no recipient found (see doc)"},
OPT_SECTION("Signing"),
{"md", OPT_MD, 's', "Digest algorithm to use"},
{"signer", OPT_SIGNER, 's', "Signer certificate input file"},
{"certfile", OPT_CERTFILE, '<', "Other certificates file"},
{"cades", OPT_CADES, '-',
"Include signingCertificate attribute (CAdES-BES)"},
{"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
{"nocerts", OPT_NOCERTS, '-',
"Don't include signer's certificate when signing"},
{"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
{"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
{"receipt_request_all", OPT_RR_ALL, '-',
"When signing, create a receipt request for all recipients"},
{"receipt_request_first", OPT_RR_FIRST, '-',
"When signing, create a receipt request for first recipient"},
{"receipt_request_from", OPT_RR_FROM, 's',
"Create signed receipt request with specified email address"},
{"receipt_request_to", OPT_RR_TO, 's',
"Create signed receipt targeted to specified address"},
OPT_SECTION("Verification"),
{"signer", OPT_DUP, 's', "Signer certificate(s) output file"},
{"content", OPT_CONTENT, '<',
"Supply or override content for detached signature"},
{"no_content_verify", OPT_NO_CONTENT_VERIFY, '-',
"Do not verify signed content signatures"},
{"no_attr_verify", OPT_NO_ATTR_VERIFY, '-',
"Do not verify signed attribute signatures"},
{"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
{"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
{"nointern", OPT_NOINTERN, '-',
"Don't search certificates in message for signer"},
{"cades", OPT_DUP, '-', "Check signingCertificate (CAdES-BES)"},
{"verify_retcode", OPT_VERIFY_RETCODE, '-',
"Exit non-zero on verification failure"},
{"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
{"CApath", OPT_CAPATH, '/', "Trusted certificates directory"},
{"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
{"no-CAstore", OPT_NOCASTORE, '-',
"Do not load certificates from the default certificates store"},
OPT_SECTION("Output"),
{"keyid", OPT_KEYID, '-', "Use subject key identifier"},
{"econtent_type", OPT_ECONTENT_TYPE, 's', "OID for external content"},
{"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
{"certsout", OPT_CERTSOUT, '>', "Certificate output file"},
{"to", OPT_TO, 's', "To address"},
{"from", OPT_FROM, 's', "From address"},
{"subject", OPT_SUBJECT, 's', "Subject"},
OPT_SECTION("Printing"),
{"noout", OPT_NOOUT, '-',
"For the -cmsout operation do not output the parsed CMS structure"},
{"print", OPT_PRINT, '-',
"For the -cmsout operation print out all fields of the CMS structure"},
{"nameopt", OPT_NAMEOPT, 's',
"For the -print option specifies various strings printing options"},
{"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" },
OPT_V_OPTIONS,
{NULL}
};
static CMS_ContentInfo *load_content_info(int informat, BIO *in, int flags,
BIO **indata, const char *name)
{
CMS_ContentInfo *ret, *ci;
ret = CMS_ContentInfo_new_ex(app_get0_libctx(), app_get0_propq());
if (ret == NULL) {
BIO_printf(bio_err, "Error allocating CMS_contentinfo\n");
return NULL;
}
switch (informat) {
case FORMAT_SMIME:
ci = SMIME_read_CMS_ex(in, flags, indata, &ret);
break;
case FORMAT_PEM:
ci = PEM_read_bio_CMS(in, &ret, NULL, NULL);
break;
case FORMAT_ASN1:
ci = d2i_CMS_bio(in, &ret);
break;
default:
BIO_printf(bio_err, "Bad input format for %s\n", name);
goto err;
}
if (ci == NULL) {
BIO_printf(bio_err, "Error reading %s Content Info\n", name);
goto err;
}
return ret;
err:
CMS_ContentInfo_free(ret);
return NULL;
}
int cms_main(int argc, char **argv)
{
CONF *conf = NULL;
ASN1_OBJECT *econtent_type = NULL;
BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
CMS_ContentInfo *cms = NULL, *rcms = NULL;
CMS_ReceiptRequest *rr = NULL;
ENGINE *e = NULL;
EVP_PKEY *key = NULL;
EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
EVP_MD *sign_md = NULL;
STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
STACK_OF(X509) *encerts = sk_X509_new_null(), *other = NULL;
X509 *cert = NULL, *recip = NULL, *signer = NULL, *originator = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = X509_VERIFY_PARAM_new();
char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL;
char *certsoutfile = NULL, *digestname = NULL, *wrapname = NULL;
int noCAfile = 0, noCApath = 0, noCAstore = 0;
char *infile = NULL, *outfile = NULL, *rctfile = NULL;
char *passinarg = NULL, *passin = NULL, *signerfile = NULL;
char *originatorfile = NULL, *recipfile = NULL, *ciphername = NULL;
char *to = NULL, *from = NULL, *subject = NULL, *prog;
cms_key_param *key_first = NULL, *key_param = NULL;
int flags = CMS_DETACHED, binary_files = 0;
int noout = 0, print = 0, keyidx = -1, vpmtouched = 0;
int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1;
int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_UNDEF;
size_t secret_keylen = 0, secret_keyidlen = 0;
unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
unsigned char *secret_key = NULL, *secret_keyid = NULL;
long ltmp;
const char *mime_eol = "\n";
OPTION_CHOICE o;
OSSL_LIB_CTX *libctx = app_get0_libctx();
if (encerts == NULL || vpm == NULL)
goto end;
prog = opt_init(argc, argv, cms_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(cms_options);
ret = 0;
goto end;
case OPT_INFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
goto opthelp;
break;
case OPT_OUTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
goto opthelp;
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_ENCRYPT:
operation = SMIME_ENCRYPT;
break;
case OPT_DECRYPT:
operation = SMIME_DECRYPT;
break;
case OPT_SIGN:
operation = SMIME_SIGN;
break;
case OPT_VERIFY:
operation = SMIME_VERIFY;
break;
case OPT_RESIGN:
operation = SMIME_RESIGN;
break;
case OPT_SIGN_RECEIPT:
operation = SMIME_SIGN_RECEIPT;
break;
case OPT_VERIFY_RECEIPT:
operation = SMIME_VERIFY_RECEIPT;
rctfile = opt_arg();
break;
case OPT_VERIFY_RETCODE:
verify_retcode = 1;
break;
case OPT_DIGEST_CREATE:
operation = SMIME_DIGEST_CREATE;
break;
case OPT_DIGEST_VERIFY:
operation = SMIME_DIGEST_VERIFY;
break;
case OPT_COMPRESS:
operation = SMIME_COMPRESS;
break;
case OPT_UNCOMPRESS:
operation = SMIME_UNCOMPRESS;
break;
case OPT_ED_ENCRYPT:
operation = SMIME_ENCRYPTED_ENCRYPT;
break;
case OPT_ED_DECRYPT:
operation = SMIME_ENCRYPTED_DECRYPT;
break;
case OPT_DATA_CREATE:
operation = SMIME_DATA_CREATE;
break;
case OPT_DATA_OUT:
operation = SMIME_DATA_OUT;
break;
case OPT_CMSOUT:
operation = SMIME_CMSOUT;
break;
case OPT_DEBUG_DECRYPT:
flags |= CMS_DEBUG_DECRYPT;
break;
case OPT_TEXT:
flags |= CMS_TEXT;
break;
case OPT_ASCIICRLF:
flags |= CMS_ASCIICRLF;
break;
case OPT_NOINTERN:
flags |= CMS_NOINTERN;
break;
case OPT_NOVERIFY:
flags |= CMS_NO_SIGNER_CERT_VERIFY;
break;
case OPT_NOCERTS:
flags |= CMS_NOCERTS;
break;
case OPT_NOATTR:
flags |= CMS_NOATTR;
break;
case OPT_NODETACH:
flags &= ~CMS_DETACHED;
break;
case OPT_NOSMIMECAP:
flags |= CMS_NOSMIMECAP;
break;
case OPT_BINARY:
flags |= CMS_BINARY;
break;
case OPT_CADES:
flags |= CMS_CADES;
break;
case OPT_KEYID:
flags |= CMS_USE_KEYID;
break;
case OPT_NOSIGS:
flags |= CMS_NOSIGS;
break;
case OPT_NO_CONTENT_VERIFY:
flags |= CMS_NO_CONTENT_VERIFY;
break;
case OPT_NO_ATTR_VERIFY:
flags |= CMS_NO_ATTR_VERIFY;
break;
case OPT_INDEF:
flags |= CMS_STREAM;
break;
case OPT_NOINDEF:
flags &= ~CMS_STREAM;
break;
case OPT_CRLFEOL:
mime_eol = "\r\n";
flags |= CMS_CRLFEOL;
break;
case OPT_NOOUT:
noout = 1;
break;
case OPT_RR_PRINT:
rr_print = 1;
break;
case OPT_RR_ALL:
rr_allorfirst = 0;
break;
case OPT_RR_FIRST:
rr_allorfirst = 1;
break;
case OPT_RCTFORM:
if (!opt_format(opt_arg(),
OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
goto opthelp;
break;
case OPT_CERTFILE:
certfile = opt_arg();
break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_CAPATH:
CApath = opt_arg();
break;
case OPT_CASTORE:
CAstore = opt_arg();
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_NOCASTORE:
noCAstore = 1;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_CONTENT:
contfile = opt_arg();
break;
case OPT_RR_FROM:
if (rr_from == NULL
&& (rr_from = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(rr_from, opt_arg());
+ if (sk_OPENSSL_STRING_push(rr_from, opt_arg()) <= 0)
+ goto end;
break;
case OPT_RR_TO:
if (rr_to == NULL
&& (rr_to = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(rr_to, opt_arg());
+ if (sk_OPENSSL_STRING_push(rr_to, opt_arg()) <= 0)
+ goto end;
break;
case OPT_PRINT:
noout = print = 1;
break;
case OPT_NAMEOPT:
if (!set_nameopt(opt_arg()))
goto opthelp;
break;
case OPT_SECRETKEY:
if (secret_key != NULL) {
BIO_printf(bio_err, "Invalid key (supplied twice) %s\n",
opt_arg());
goto opthelp;
}
secret_key = OPENSSL_hexstr2buf(opt_arg(), &ltmp);
if (secret_key == NULL) {
BIO_printf(bio_err, "Invalid key %s\n", opt_arg());
goto end;
}
secret_keylen = (size_t)ltmp;
break;
case OPT_SECRETKEYID:
if (secret_keyid != NULL) {
BIO_printf(bio_err, "Invalid id (supplied twice) %s\n",
opt_arg());
goto opthelp;
}
secret_keyid = OPENSSL_hexstr2buf(opt_arg(), &ltmp);
if (secret_keyid == NULL) {
BIO_printf(bio_err, "Invalid id %s\n", opt_arg());
goto opthelp;
}
secret_keyidlen = (size_t)ltmp;
break;
case OPT_PWRI_PASSWORD:
pwri_pass = (unsigned char *)opt_arg();
break;
case OPT_ECONTENT_TYPE:
if (econtent_type != NULL) {
BIO_printf(bio_err, "Invalid OID (supplied twice) %s\n",
opt_arg());
goto opthelp;
}
econtent_type = OBJ_txt2obj(opt_arg(), 0);
if (econtent_type == NULL) {
BIO_printf(bio_err, "Invalid OID %s\n", opt_arg());
goto opthelp;
}
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_TO:
to = opt_arg();
break;
case OPT_FROM:
from = opt_arg();
break;
case OPT_SUBJECT:
subject = opt_arg();
break;
case OPT_CERTSOUT:
certsoutfile = opt_arg();
break;
case OPT_MD:
digestname = opt_arg();
break;
case OPT_SIGNER:
/* If previous -signer argument add signer to list */
if (signerfile != NULL) {
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0)
+ goto end;
if (keyfile == NULL)
keyfile = signerfile;
if (skkeys == NULL
&& (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(skkeys, keyfile);
+ if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0)
+ goto end;
keyfile = NULL;
}
signerfile = opt_arg();
break;
case OPT_ORIGINATOR:
originatorfile = opt_arg();
break;
case OPT_INKEY:
/* If previous -inkey argument add signer to list */
if (keyfile != NULL) {
if (signerfile == NULL) {
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
goto end;
}
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0)
+ goto end;
signerfile = NULL;
if (skkeys == NULL
&& (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(skkeys, keyfile);
+ if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0)
+ goto end;
}
keyfile = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
break;
case OPT_RECIP:
if (operation == SMIME_ENCRYPT) {
cert = load_cert(opt_arg(), FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
if (!sk_X509_push(encerts, cert))
goto end;
cert = NULL;
} else {
recipfile = opt_arg();
}
break;
case OPT_CIPHER:
ciphername = opt_unknown();
break;
case OPT_KEYOPT:
keyidx = -1;
if (operation == SMIME_ENCRYPT) {
if (sk_X509_num(encerts) > 0)
keyidx += sk_X509_num(encerts);
} else {
if (keyfile != NULL || signerfile != NULL)
keyidx++;
if (skkeys != NULL)
keyidx += sk_OPENSSL_STRING_num(skkeys);
}
if (keyidx < 0) {
BIO_printf(bio_err, "No key specified\n");
goto opthelp;
}
if (key_param == NULL || key_param->idx != keyidx) {
cms_key_param *nparam;
nparam = app_malloc(sizeof(*nparam), "key param buffer");
if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL) {
OPENSSL_free(nparam);
goto end;
}
nparam->idx = keyidx;
nparam->next = NULL;
if (key_first == NULL)
key_first = nparam;
else
key_param->next = nparam;
key_param = nparam;
}
- sk_OPENSSL_STRING_push(key_param->param, opt_arg());
+ if (sk_OPENSSL_STRING_push(key_param->param, opt_arg()) <= 0)
+ goto end;
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto end;
vpmtouched++;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_PROV_CASES:
if (!opt_provider(o))
goto end;
break;
case OPT_CONFIG:
conf = app_load_config_modules(opt_arg());
if (conf == NULL)
goto end;
break;
case OPT_WRAP:
wrapname = opt_arg();
break;
case OPT_AES128_WRAP:
case OPT_AES192_WRAP:
case OPT_AES256_WRAP:
case OPT_3DES_WRAP:
wrapname = opt_flag() + 1;
break;
}
}
if (!app_RAND_load())
goto end;
if (digestname != NULL) {
if (!opt_md(digestname, &sign_md))
goto end;
}
if (ciphername != NULL) {
if (!opt_cipher_any(ciphername, &cipher))
goto end;
}
if (wrapname != NULL) {
if (!opt_cipher_any(wrapname, &wrap_cipher))
goto end;
}
/* Remaining args are files to process. */
argc = opt_num_rest();
argv = opt_rest();
if ((rr_allorfirst != -1 || rr_from != NULL) && rr_to == NULL) {
BIO_puts(bio_err, "No Signed Receipts Recipients\n");
goto opthelp;
}
if (!(operation & SMIME_SIGNERS) && (rr_to != NULL || rr_from != NULL)) {
BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
goto opthelp;
}
if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) {
BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
goto opthelp;
}
if ((flags & CMS_CADES) != 0) {
if ((flags & CMS_NOATTR) != 0) {
BIO_puts(bio_err, "Incompatible options: "
"CAdES requires signed attributes\n");
goto opthelp;
}
if (operation == SMIME_VERIFY
&& (flags & (CMS_NO_SIGNER_CERT_VERIFY | CMS_NO_ATTR_VERIFY)) != 0) {
BIO_puts(bio_err, "Incompatible options: CAdES validation requires"
" certs and signed attributes validations\n");
goto opthelp;
}
}
if (operation & SMIME_SIGNERS) {
if (keyfile != NULL && signerfile == NULL) {
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
goto opthelp;
}
/* Check to see if any final signer needs to be appended */
if (signerfile != NULL) {
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0)
+ goto end;
if (skkeys == NULL && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
if (keyfile == NULL)
keyfile = signerfile;
- sk_OPENSSL_STRING_push(skkeys, keyfile);
+ if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0)
+ goto end;
}
if (sksigners == NULL) {
BIO_printf(bio_err, "No signer certificate specified\n");
goto opthelp;
}
signerfile = NULL;
keyfile = NULL;
} else if (operation == SMIME_DECRYPT) {
if (recipfile == NULL && keyfile == NULL
&& secret_key == NULL && pwri_pass == NULL) {
BIO_printf(bio_err,
"No recipient certificate or key specified\n");
goto opthelp;
}
} else if (operation == SMIME_ENCRYPT) {
if (*argv == NULL && secret_key == NULL
&& pwri_pass == NULL && sk_X509_num(encerts) <= 0) {
BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
goto opthelp;
}
} else if (!operation) {
BIO_printf(bio_err, "No operation option (-encrypt|-decrypt|-sign|-verify|...) specified.\n");
goto opthelp;
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
ret = 2;
if ((operation & SMIME_SIGNERS) == 0) {
if ((flags & CMS_DETACHED) == 0)
BIO_printf(bio_err,
"Warning: -nodetach option is ignored for non-signing operation\n");
flags &= ~CMS_DETACHED;
}
if ((operation & SMIME_IP) == 0 && contfile != NULL)
BIO_printf(bio_err,
"Warning: -contfile option is ignored for the given operation\n");
if (operation != SMIME_ENCRYPT && *argv != NULL)
BIO_printf(bio_err,
"Warning: recipient certificate file parameters ignored for operation other than -encrypt\n");
if ((flags & CMS_BINARY) != 0) {
if (!(operation & SMIME_OP))
outformat = FORMAT_BINARY;
if (!(operation & SMIME_IP))
informat = FORMAT_BINARY;
if ((operation & SMIME_SIGNERS) != 0 && (flags & CMS_DETACHED) != 0)
binary_files = 1;
if ((operation & SMIME_IP) != 0 && contfile == NULL)
binary_files = 1;
}
if (operation == SMIME_ENCRYPT) {
if (!cipher) {
#ifndef OPENSSL_NO_DES
cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
#else
BIO_printf(bio_err, "No cipher selected\n");
goto end;
#endif
}
if (secret_key && !secret_keyid) {
BIO_printf(bio_err, "No secret key id\n");
goto end;
}
for (; *argv != NULL; argv++) {
cert = load_cert(*argv, FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
if (!sk_X509_push(encerts, cert))
goto end;
cert = NULL;
}
}
if (certfile != NULL) {
if (!load_certs(certfile, 0, &other, NULL, "certificate file")) {
ERR_print_errors(bio_err);
goto end;
}
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
if ((recip = load_cert(recipfile, FORMAT_UNDEF,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (originatorfile != NULL) {
if ((originator = load_cert(originatorfile, FORMAT_UNDEF,
"originator certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (operation == SMIME_SIGN_RECEIPT) {
if ((signer = load_cert(signerfile, FORMAT_UNDEF,
"receipt signer certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if ((operation == SMIME_DECRYPT) || (operation == SMIME_ENCRYPT)) {
if (keyfile == NULL)
keyfile = recipfile;
} else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) {
if (keyfile == NULL)
keyfile = signerfile;
} else {
keyfile = NULL;
}
if (keyfile != NULL) {
key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
}
in = bio_open_default(infile, 'r',
binary_files ? FORMAT_BINARY : informat);
if (in == NULL)
goto end;
if (operation & SMIME_IP) {
cms = load_content_info(informat, in, flags, &indata, "SMIME");
if (cms == NULL)
goto end;
if (contfile != NULL) {
BIO_free(indata);
if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
BIO_printf(bio_err, "Can't read content file %s\n", contfile);
goto end;
}
}
if (certsoutfile != NULL) {
STACK_OF(X509) *allcerts;
allcerts = CMS_get1_certs(cms);
if (!save_certs(certsoutfile, allcerts)) {
BIO_printf(bio_err,
"Error writing certs to %s\n", certsoutfile);
ret = 5;
goto end;
}
sk_X509_pop_free(allcerts, X509_free);
}
}
if (rctfile != NULL) {
char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) {
BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile);
goto end;
}
rcms = load_content_info(rctformat, rctin, 0, NULL, "receipt");
if (rcms == NULL)
goto end;
}
out = bio_open_default(outfile, 'w',
binary_files ? FORMAT_BINARY : outformat);
if (out == NULL)
goto end;
if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
CAstore, noCAstore)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, cms_cb);
if (vpmtouched)
X509_STORE_set1_param(store, vpm);
}
ret = 3;
if (operation == SMIME_DATA_CREATE) {
cms = CMS_data_create_ex(in, flags, libctx, app_get0_propq());
} else if (operation == SMIME_DIGEST_CREATE) {
cms = CMS_digest_create_ex(in, sign_md, flags, libctx, app_get0_propq());
} else if (operation == SMIME_COMPRESS) {
cms = CMS_compress(in, -1, flags);
} else if (operation == SMIME_ENCRYPT) {
int i;
flags |= CMS_PARTIAL;
cms = CMS_encrypt_ex(NULL, in, cipher, flags, libctx, app_get0_propq());
if (cms == NULL)
goto end;
for (i = 0; i < sk_X509_num(encerts); i++) {
CMS_RecipientInfo *ri;
cms_key_param *kparam;
int tflags = flags | CMS_KEY_PARAM;
/* This flag enforces allocating the EVP_PKEY_CTX for the recipient here */
EVP_PKEY_CTX *pctx;
X509 *x = sk_X509_value(encerts, i);
int res;
for (kparam = key_first; kparam; kparam = kparam->next) {
if (kparam->idx == i) {
break;
}
}
ri = CMS_add1_recipient(cms, x, key, originator, tflags);
if (ri == NULL)
goto end;
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (kparam != NULL) {
if (!cms_set_pkey_param(pctx, kparam->param))
goto end;
}
res = EVP_PKEY_CTX_ctrl(pctx, -1, -1,
EVP_PKEY_CTRL_CIPHER,
EVP_CIPHER_get_nid(cipher), NULL);
if (res <= 0 && res != -2)
goto end;
if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
&& wrap_cipher != NULL) {
EVP_CIPHER_CTX *wctx;
wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
}
}
if (secret_key != NULL) {
if (!CMS_add0_recipient_key(cms, NID_undef,
secret_key, secret_keylen,
secret_keyid, secret_keyidlen,
NULL, NULL, NULL))
goto end;
/* NULL these because call absorbs them */
secret_key = NULL;
secret_keyid = NULL;
}
if (pwri_pass != NULL) {
pwri_tmp = (unsigned char *)OPENSSL_strdup((char *)pwri_pass);
if (pwri_tmp == NULL)
goto end;
if (CMS_add0_recipient_password(cms,
-1, NID_undef, NID_undef,
pwri_tmp, -1, NULL) == NULL)
goto end;
pwri_tmp = NULL;
}
if (!(flags & CMS_STREAM)) {
- if (!CMS_final(cms, in, NULL, flags))
+ if (!CMS_final(cms, in, NULL, flags)) {
+ if (originator != NULL
+ && ERR_GET_REASON(ERR_peek_error())
+ == CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT) {
+ BIO_printf(bio_err, "Cannot use originator for encryption\n");
+ goto end;
+ }
goto end;
+ }
}
} else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
cms = CMS_EncryptedData_encrypt_ex(in, cipher, secret_key,
secret_keylen, flags, libctx, app_get0_propq());
} else if (operation == SMIME_SIGN_RECEIPT) {
CMS_ContentInfo *srcms = NULL;
STACK_OF(CMS_SignerInfo) *sis;
CMS_SignerInfo *si;
sis = CMS_get0_SignerInfos(cms);
if (sis == NULL)
goto end;
si = sk_CMS_SignerInfo_value(sis, 0);
srcms = CMS_sign_receipt(si, signer, key, other, flags);
if (srcms == NULL)
goto end;
CMS_ContentInfo_free(cms);
cms = srcms;
} else if (operation & SMIME_SIGNERS) {
int i;
/*
* If detached data content we enable streaming if S/MIME output
* format.
*/
if (operation == SMIME_SIGN) {
if (flags & CMS_DETACHED) {
if (outformat == FORMAT_SMIME)
flags |= CMS_STREAM;
}
flags |= CMS_PARTIAL;
cms = CMS_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq());
if (cms == NULL)
goto end;
if (econtent_type != NULL)
CMS_set1_eContentType(cms, econtent_type);
if (rr_to != NULL
&& ((rr = make_receipt_request(rr_to, rr_allorfirst, rr_from))
== NULL)) {
BIO_puts(bio_err, "Signed Receipt Request Creation Error\n");
goto end;
}
} else {
flags |= CMS_REUSE_DIGEST;
}
for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
CMS_SignerInfo *si;
cms_key_param *kparam;
int tflags = flags;
signerfile = sk_OPENSSL_STRING_value(sksigners, i);
keyfile = sk_OPENSSL_STRING_value(skkeys, i);
signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL) {
ret = 2;
goto end;
}
key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL) {
ret = 2;
goto end;
}
for (kparam = key_first; kparam; kparam = kparam->next) {
if (kparam->idx == i) {
tflags |= CMS_KEY_PARAM;
break;
}
}
si = CMS_add1_signer(cms, signer, key, sign_md, tflags);
if (si == NULL)
goto end;
if (kparam != NULL) {
EVP_PKEY_CTX *pctx;
pctx = CMS_SignerInfo_get0_pkey_ctx(si);
if (!cms_set_pkey_param(pctx, kparam->param))
goto end;
}
if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr))
goto end;
X509_free(signer);
signer = NULL;
EVP_PKEY_free(key);
key = NULL;
}
/* If not streaming or resigning finalize structure */
if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) {
if (!CMS_final(cms, in, NULL, flags))
goto end;
}
}
if (cms == NULL) {
BIO_printf(bio_err, "Error creating CMS structure\n");
goto end;
}
ret = 4;
if (operation == SMIME_DECRYPT) {
if (flags & CMS_DEBUG_DECRYPT)
CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);
if (secret_key != NULL) {
if (!CMS_decrypt_set1_key(cms,
secret_key, secret_keylen,
secret_keyid, secret_keyidlen)) {
BIO_puts(bio_err, "Error decrypting CMS using secret key\n");
goto end;
}
}
if (key != NULL) {
if (!CMS_decrypt_set1_pkey_and_peer(cms, key, recip, originator)) {
BIO_puts(bio_err, "Error decrypting CMS using private key\n");
goto end;
}
}
if (pwri_pass != NULL) {
if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) {
BIO_puts(bio_err, "Error decrypting CMS using password\n");
goto end;
}
}
if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) {
BIO_printf(bio_err, "Error decrypting CMS structure\n");
goto end;
}
} else if (operation == SMIME_DATA_OUT) {
if (!CMS_data(cms, out, flags))
goto end;
} else if (operation == SMIME_UNCOMPRESS) {
if (!CMS_uncompress(cms, indata, out, flags))
goto end;
} else if (operation == SMIME_DIGEST_VERIFY) {
if (CMS_digest_verify(cms, indata, out, flags) > 0) {
BIO_printf(bio_err, "Verification successful\n");
} else {
BIO_printf(bio_err, "Verification failure\n");
goto end;
}
} else if (operation == SMIME_ENCRYPTED_DECRYPT) {
if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
indata, out, flags))
goto end;
} else if (operation == SMIME_VERIFY) {
if (CMS_verify(cms, other, store, indata, out, flags) > 0) {
BIO_printf(bio_err, "%s Verification successful\n",
(flags & CMS_CADES) != 0 ? "CAdES" : "CMS");
} else {
BIO_printf(bio_err, "%s Verification failure\n",
(flags & CMS_CADES) != 0 ? "CAdES" : "CMS");
if (verify_retcode)
ret = verify_err + 32;
goto end;
}
if (signerfile != NULL) {
STACK_OF(X509) *signers = CMS_get0_signers(cms);
if (!save_certs(signerfile, signers)) {
BIO_printf(bio_err,
"Error writing signers to %s\n", signerfile);
ret = 5;
goto end;
}
sk_X509_free(signers);
}
if (rr_print)
receipt_request_print(cms);
} else if (operation == SMIME_VERIFY_RECEIPT) {
if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0) {
BIO_printf(bio_err, "Verification successful\n");
} else {
BIO_printf(bio_err, "Verification failure\n");
goto end;
}
} else {
if (noout) {
if (print) {
ASN1_PCTX *pctx = NULL;
if (get_nameopt() != XN_FLAG_ONELINE) {
pctx = ASN1_PCTX_new();
if (pctx != NULL) { /* Print anyway if malloc failed */
ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT);
ASN1_PCTX_set_str_flags(pctx, get_nameopt());
ASN1_PCTX_set_nm_flags(pctx, get_nameopt());
}
}
CMS_ContentInfo_print_ctx(out, cms, 0, pctx);
ASN1_PCTX_free(pctx);
}
} else if (outformat == FORMAT_SMIME) {
if (to)
BIO_printf(out, "To: %s%s", to, mime_eol);
if (from)
BIO_printf(out, "From: %s%s", from, mime_eol);
if (subject)
BIO_printf(out, "Subject: %s%s", subject, mime_eol);
if (operation == SMIME_RESIGN)
ret = SMIME_write_CMS(out, cms, indata, flags);
else
ret = SMIME_write_CMS(out, cms, in, flags);
} else if (outformat == FORMAT_PEM) {
ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
} else if (outformat == FORMAT_ASN1) {
ret = i2d_CMS_bio_stream(out, cms, in, flags);
} else {
BIO_printf(bio_err, "Bad output format for CMS file\n");
goto end;
}
if (ret <= 0) {
ret = 6;
goto end;
}
}
ret = 0;
end:
if (ret)
ERR_print_errors(bio_err);
sk_X509_pop_free(encerts, X509_free);
sk_X509_pop_free(other, X509_free);
X509_VERIFY_PARAM_free(vpm);
sk_OPENSSL_STRING_free(sksigners);
sk_OPENSSL_STRING_free(skkeys);
OPENSSL_free(secret_key);
OPENSSL_free(secret_keyid);
OPENSSL_free(pwri_tmp);
ASN1_OBJECT_free(econtent_type);
CMS_ReceiptRequest_free(rr);
sk_OPENSSL_STRING_free(rr_to);
sk_OPENSSL_STRING_free(rr_from);
for (key_param = key_first; key_param;) {
cms_key_param *tparam;
sk_OPENSSL_STRING_free(key_param->param);
tparam = key_param->next;
OPENSSL_free(key_param);
key_param = tparam;
}
X509_STORE_free(store);
X509_free(cert);
X509_free(recip);
X509_free(signer);
+ X509_free(originator);
EVP_PKEY_free(key);
EVP_CIPHER_free(cipher);
EVP_CIPHER_free(wrap_cipher);
EVP_MD_free(sign_md);
CMS_ContentInfo_free(cms);
CMS_ContentInfo_free(rcms);
release_engine(e);
BIO_free(rctin);
BIO_free(in);
BIO_free(indata);
BIO_free_all(out);
OPENSSL_free(passin);
NCONF_free(conf);
return ret;
}
static int save_certs(char *signerfile, STACK_OF(X509) *signers)
{
int i;
BIO *tmp;
if (signerfile == NULL)
return 1;
tmp = BIO_new_file(signerfile, "w");
if (tmp == NULL)
return 0;
for (i = 0; i < sk_X509_num(signers); i++)
PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
BIO_free(tmp);
return 1;
}
/* Minimal callback just to output policy info (if any) */
static int cms_cb(int ok, X509_STORE_CTX *ctx)
{
int error;
error = X509_STORE_CTX_get_error(ctx);
verify_err = error;
if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
&& ((error != X509_V_OK) || (ok != 2)))
return ok;
policies_print(ctx);
return ok;
}
static void gnames_stack_print(STACK_OF(GENERAL_NAMES) *gns)
{
STACK_OF(GENERAL_NAME) *gens;
GENERAL_NAME *gen;
int i, j;
for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) {
gens = sk_GENERAL_NAMES_value(gns, i);
for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) {
gen = sk_GENERAL_NAME_value(gens, j);
BIO_puts(bio_err, " ");
GENERAL_NAME_print(bio_err, gen);
BIO_puts(bio_err, "\n");
}
}
return;
}
static void receipt_request_print(CMS_ContentInfo *cms)
{
STACK_OF(CMS_SignerInfo) *sis;
CMS_SignerInfo *si;
CMS_ReceiptRequest *rr;
int allorfirst;
STACK_OF(GENERAL_NAMES) *rto, *rlist;
ASN1_STRING *scid;
int i, rv;
sis = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) {
si = sk_CMS_SignerInfo_value(sis, i);
rv = CMS_get1_ReceiptRequest(si, &rr);
BIO_printf(bio_err, "Signer %d:\n", i + 1);
if (rv == 0) {
BIO_puts(bio_err, " No Receipt Request\n");
} else if (rv < 0) {
BIO_puts(bio_err, " Receipt Request Parse Error\n");
ERR_print_errors(bio_err);
} else {
const char *id;
int idlen;
CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
&rlist, &rto);
BIO_puts(bio_err, " Signed Content ID:\n");
idlen = ASN1_STRING_length(scid);
id = (const char *)ASN1_STRING_get0_data(scid);
BIO_dump_indent(bio_err, id, idlen, 4);
BIO_puts(bio_err, " Receipts From");
if (rlist != NULL) {
BIO_puts(bio_err, " List:\n");
gnames_stack_print(rlist);
} else if (allorfirst == 1) {
BIO_puts(bio_err, ": First Tier\n");
} else if (allorfirst == 0) {
BIO_puts(bio_err, ": All\n");
} else {
BIO_printf(bio_err, " Unknown (%d)\n", allorfirst);
}
BIO_puts(bio_err, " Receipts To:\n");
gnames_stack_print(rto);
}
CMS_ReceiptRequest_free(rr);
}
}
static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
{
int i;
STACK_OF(GENERAL_NAMES) *ret;
GENERAL_NAMES *gens = NULL;
GENERAL_NAME *gen = NULL;
ret = sk_GENERAL_NAMES_new_null();
if (ret == NULL)
goto err;
for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) {
char *str = sk_OPENSSL_STRING_value(ns, i);
gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0);
if (gen == NULL)
goto err;
gens = GENERAL_NAMES_new();
if (gens == NULL)
goto err;
if (!sk_GENERAL_NAME_push(gens, gen))
goto err;
gen = NULL;
if (!sk_GENERAL_NAMES_push(ret, gens))
goto err;
gens = NULL;
}
return ret;
err:
sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
GENERAL_NAMES_free(gens);
GENERAL_NAME_free(gen);
return NULL;
}
static CMS_ReceiptRequest
*make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
STACK_OF(OPENSSL_STRING) *rr_from)
{
STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
CMS_ReceiptRequest *rr;
rct_to = make_names_stack(rr_to);
if (rct_to == NULL)
goto err;
if (rr_from != NULL) {
rct_from = make_names_stack(rr_from);
if (rct_from == NULL)
goto err;
} else {
rct_from = NULL;
}
rr = CMS_ReceiptRequest_create0_ex(NULL, -1, rr_allorfirst, rct_from,
rct_to, app_get0_libctx());
if (rr == NULL)
goto err;
return rr;
err:
sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
sk_GENERAL_NAMES_pop_free(rct_from, GENERAL_NAMES_free);
return NULL;
}
static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
STACK_OF(OPENSSL_STRING) *param)
{
char *keyopt;
int i;
if (sk_OPENSSL_STRING_num(param) <= 0)
return 1;
for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) {
keyopt = sk_OPENSSL_STRING_value(param, i);
if (pkey_ctrl_string(pctx, keyopt) <= 0) {
BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt);
ERR_print_errors(bio_err);
return 0;
}
}
return 1;
}
diff --git a/crypto/openssl/apps/engine.c b/crypto/openssl/apps/engine.c
index 1b0f64309c6f..c83bdfc150c3 100644
--- a/crypto/openssl/apps/engine.c
+++ b/crypto/openssl/apps/engine.c
@@ -1,493 +1,495 @@
/*
- * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* We need to use some engine deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
#include <openssl/opensslconf.h>
#include "apps.h"
#include "progs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/engine.h>
#include <openssl/ssl.h>
#include <openssl/store.h>
typedef enum OPTION_choice {
OPT_COMMON,
OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST,
OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV
} OPTION_CHOICE;
const OPTIONS engine_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"},
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"t", OPT_T, '-', "Check that specified engine is available"},
{"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"},
{"post", OPT_POST, 's', "Run command against the ENGINE after loading it"},
OPT_SECTION("Output"),
{"v", OPT_V, '-', "List 'control commands' For each specified engine"},
{"vv", OPT_VV, '-', "Also display each command's description"},
{"vvv", OPT_VVV, '-', "Also add the input flags for each command"},
{"vvvv", OPT_VVVV, '-', "Also show internal input flags"},
{"c", OPT_C, '-', "List the capabilities of specified engine"},
{"tt", OPT_TT, '-', "Display error trace for unavailable engines"},
{OPT_MORE_STR, OPT_EOF, 1,
"Commands are like \"SO_PATH:/lib/libdriver.so\""},
OPT_PARAMETERS(),
{"engine", 0, 0, "ID of engine(s) to load"},
{NULL}
};
static int append_buf(char **buf, int *size, const char *s)
{
const int expand = 256;
int len = strlen(s) + 1;
char *p = *buf;
if (p == NULL) {
*size = ((len + expand - 1) / expand) * expand;
p = *buf = app_malloc(*size, "engine buffer");
} else {
const int blen = strlen(p);
if (blen > 0)
len += 2 + blen;
if (len > *size) {
*size = ((len + expand - 1) / expand) * expand;
p = OPENSSL_realloc(p, *size);
if (p == NULL) {
OPENSSL_free(*buf);
*buf = NULL;
return 0;
}
*buf = p;
}
if (blen > 0) {
p += blen;
*p++ = ',';
*p++ = ' ';
}
}
strcpy(p, s);
return 1;
}
static int util_flags(BIO *out, unsigned int flags, const char *indent)
{
int started = 0, err = 0;
/* Indent before displaying input flags */
BIO_printf(out, "%s%s(input flags): ", indent, indent);
if (flags == 0) {
BIO_printf(out, "<no flags>\n");
return 1;
}
/*
* If the object is internal, mark it in a way that shows instead of
* having it part of all the other flags, even if it really is.
*/
if (flags & ENGINE_CMD_FLAG_INTERNAL) {
BIO_printf(out, "[Internal] ");
}
if (flags & ENGINE_CMD_FLAG_NUMERIC) {
BIO_printf(out, "NUMERIC");
started = 1;
}
/*
* Now we check that no combinations of the mutually exclusive NUMERIC,
* STRING, and NO_INPUT flags have been used. Future flags that can be
* OR'd together with these would need to added after these to preserve
* the testing logic.
*/
if (flags & ENGINE_CMD_FLAG_STRING) {
if (started) {
BIO_printf(out, "|");
err = 1;
}
BIO_printf(out, "STRING");
started = 1;
}
if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
if (started) {
BIO_printf(out, "|");
err = 1;
}
BIO_printf(out, "NO_INPUT");
started = 1;
}
/* Check for unknown flags */
flags = flags & ~ENGINE_CMD_FLAG_NUMERIC &
~ENGINE_CMD_FLAG_STRING &
~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL;
if (flags) {
if (started)
BIO_printf(out, "|");
BIO_printf(out, "<0x%04X>", flags);
}
if (err)
BIO_printf(out, " <illegal flags!>");
BIO_printf(out, "\n");
return 1;
}
static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent)
{
static const int line_wrap = 78;
int num;
int ret = 0;
char *name = NULL;
char *desc = NULL;
int flags;
int xpos = 0;
STACK_OF(OPENSSL_STRING) *cmds = NULL;
if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
0, NULL, NULL)) <= 0)) {
return 1;
}
cmds = sk_OPENSSL_STRING_new_null();
if (cmds == NULL)
goto err;
do {
int len;
/* Get the command input flags */
if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
NULL, NULL)) < 0)
goto err;
if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) {
/* Get the command name */
if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
NULL, NULL)) <= 0)
goto err;
name = app_malloc(len + 1, "name buffer");
if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
NULL) <= 0)
goto err;
/* Get the command description */
if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
NULL, NULL)) < 0)
goto err;
if (len > 0) {
desc = app_malloc(len + 1, "description buffer");
if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
NULL) <= 0)
goto err;
}
/* Now decide on the output */
if (xpos == 0)
/* Do an indent */
xpos = BIO_puts(out, indent);
else
/* Otherwise prepend a ", " */
xpos += BIO_printf(out, ", ");
if (verbose == 1) {
/*
* We're just listing names, comma-delimited
*/
if ((xpos > (int)strlen(indent)) &&
(xpos + (int)strlen(name) > line_wrap)) {
BIO_printf(out, "\n");
xpos = BIO_puts(out, indent);
}
xpos += BIO_printf(out, "%s", name);
} else {
/* We're listing names plus descriptions */
BIO_printf(out, "%s: %s\n", name,
(desc == NULL) ? "<no description>" : desc);
/* ... and sometimes input flags */
if ((verbose >= 3) && !util_flags(out, flags, indent))
goto err;
xpos = 0;
}
}
OPENSSL_free(name);
name = NULL;
OPENSSL_free(desc);
desc = NULL;
/* Move to the next command */
num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL);
} while (num > 0);
if (xpos > 0)
BIO_printf(out, "\n");
ret = 1;
err:
sk_OPENSSL_STRING_free(cmds);
OPENSSL_free(name);
OPENSSL_free(desc);
return ret;
}
static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds,
BIO *out, const char *indent)
{
int loop, res, num = sk_OPENSSL_STRING_num(cmds);
if (num < 0) {
BIO_printf(out, "[Error]: internal stack error\n");
return;
}
for (loop = 0; loop < num; loop++) {
char buf[256];
const char *cmd, *arg;
cmd = sk_OPENSSL_STRING_value(cmds, loop);
res = 1; /* assume success */
/* Check if this command has no ":arg" */
if ((arg = strstr(cmd, ":")) == NULL) {
if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
res = 0;
} else {
if ((int)(arg - cmd) > 254) {
BIO_printf(out, "[Error]: command name too long\n");
return;
}
memcpy(buf, cmd, (int)(arg - cmd));
buf[arg - cmd] = '\0';
arg++; /* Move past the ":" */
/* Call the command with the argument */
if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0))
res = 0;
}
if (res) {
BIO_printf(out, "[Success]: %s\n", cmd);
} else {
BIO_printf(out, "[Failure]: %s\n", cmd);
ERR_print_errors(out);
}
}
}
struct util_store_cap_data {
ENGINE *engine;
char **cap_buf;
int *cap_size;
int ok;
};
static void util_store_cap(const OSSL_STORE_LOADER *loader, void *arg)
{
struct util_store_cap_data *ctx = arg;
if (OSSL_STORE_LOADER_get0_engine(loader) == ctx->engine) {
char buf[256];
BIO_snprintf(buf, sizeof(buf), "STORE(%s)",
OSSL_STORE_LOADER_get0_scheme(loader));
if (!append_buf(ctx->cap_buf, ctx->cap_size, buf))
ctx->ok = 0;
}
}
int engine_main(int argc, char **argv)
{
int ret = 1, i;
int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0;
ENGINE *e;
STACK_OF(OPENSSL_CSTRING) *engines = sk_OPENSSL_CSTRING_new_null();
STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null();
STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null();
BIO *out;
const char *indent = " ";
OPTION_CHOICE o;
char *prog;
char *argv1;
out = dup_bio_out(FORMAT_TEXT);
if (engines == NULL || pre_cmds == NULL || post_cmds == NULL)
goto end;
/* Remember the original command name, parse/skip any leading engine
* names, and then setup to parse the rest of the line as flags. */
prog = argv[0];
while ((argv1 = argv[1]) != NULL && *argv1 != '-') {
sk_OPENSSL_CSTRING_push(engines, argv1);
argc--;
argv++;
}
argv[0] = prog;
opt_init(argc, argv, engine_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(engine_options);
ret = 0;
goto end;
case OPT_VVVV:
case OPT_VVV:
case OPT_VV:
case OPT_V:
/* Convert to an integer from one to four. */
i = (int)(o - OPT_V) + 1;
if (verbose < i)
verbose = i;
break;
case OPT_C:
list_cap = 1;
break;
case OPT_TT:
test_avail_noise++;
/* fall thru */
case OPT_T:
test_avail++;
break;
case OPT_PRE:
- sk_OPENSSL_STRING_push(pre_cmds, opt_arg());
+ if (sk_OPENSSL_STRING_push(pre_cmds, opt_arg()) <= 0)
+ goto end;
break;
case OPT_POST:
- sk_OPENSSL_STRING_push(post_cmds, opt_arg());
+ if (sk_OPENSSL_STRING_push(post_cmds, opt_arg()) <= 0)
+ goto end;
break;
}
}
/* Any remaining arguments are engine names. */
argc = opt_num_rest();
argv = opt_rest();
for ( ; *argv; argv++) {
if (**argv == '-') {
BIO_printf(bio_err, "%s: Cannot mix flags and engine names.\n",
prog);
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
}
sk_OPENSSL_CSTRING_push(engines, *argv);
}
if (sk_OPENSSL_CSTRING_num(engines) == 0) {
for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {
sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e));
}
}
ret = 0;
for (i = 0; i < sk_OPENSSL_CSTRING_num(engines); i++) {
const char *id = sk_OPENSSL_CSTRING_value(engines, i);
if ((e = ENGINE_by_id(id)) != NULL) {
const char *name = ENGINE_get_name(e);
/*
* Do "id" first, then "name". Easier to auto-parse.
*/
BIO_printf(out, "(%s) %s\n", id, name);
util_do_cmds(e, pre_cmds, out, indent);
if (strcmp(ENGINE_get_id(e), id) != 0) {
BIO_printf(out, "Loaded: (%s) %s\n",
ENGINE_get_id(e), ENGINE_get_name(e));
}
if (list_cap) {
int cap_size = 256;
char *cap_buf = NULL;
int k, n;
const int *nids;
ENGINE_CIPHERS_PTR fn_c;
ENGINE_DIGESTS_PTR fn_d;
ENGINE_PKEY_METHS_PTR fn_pk;
if (ENGINE_get_RSA(e) != NULL
&& !append_buf(&cap_buf, &cap_size, "RSA"))
goto end;
if (ENGINE_get_DSA(e) != NULL
&& !append_buf(&cap_buf, &cap_size, "DSA"))
goto end;
if (ENGINE_get_DH(e) != NULL
&& !append_buf(&cap_buf, &cap_size, "DH"))
goto end;
if (ENGINE_get_RAND(e) != NULL
&& !append_buf(&cap_buf, &cap_size, "RAND"))
goto end;
fn_c = ENGINE_get_ciphers(e);
if (fn_c == NULL)
goto skip_ciphers;
n = fn_c(e, NULL, &nids, 0);
for (k = 0; k < n; ++k)
if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
goto end;
skip_ciphers:
fn_d = ENGINE_get_digests(e);
if (fn_d == NULL)
goto skip_digests;
n = fn_d(e, NULL, &nids, 0);
for (k = 0; k < n; ++k)
if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
goto end;
skip_digests:
fn_pk = ENGINE_get_pkey_meths(e);
if (fn_pk == NULL)
goto skip_pmeths;
n = fn_pk(e, NULL, &nids, 0);
for (k = 0; k < n; ++k)
if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
goto end;
skip_pmeths:
{
struct util_store_cap_data store_ctx;
store_ctx.engine = e;
store_ctx.cap_buf = &cap_buf;
store_ctx.cap_size = &cap_size;
store_ctx.ok = 1;
OSSL_STORE_do_all_loaders(util_store_cap, &store_ctx);
if (!store_ctx.ok)
goto end;
}
if (cap_buf != NULL && (*cap_buf != '\0'))
BIO_printf(out, " [%s]\n", cap_buf);
OPENSSL_free(cap_buf);
}
if (test_avail) {
BIO_printf(out, "%s", indent);
if (ENGINE_init(e)) {
BIO_printf(out, "[ available ]\n");
util_do_cmds(e, post_cmds, out, indent);
ENGINE_finish(e);
} else {
BIO_printf(out, "[ unavailable ]\n");
if (test_avail_noise)
ERR_print_errors_fp(stdout);
ERR_clear_error();
}
}
if ((verbose > 0) && !util_verbose(e, verbose, out, indent))
goto end;
ENGINE_free(e);
} else {
ERR_print_errors(bio_err);
/* because exit codes above 127 have special meaning on Unix */
if (++ret > 127)
ret = 127;
}
}
end:
ERR_print_errors(bio_err);
sk_OPENSSL_CSTRING_free(engines);
sk_OPENSSL_STRING_free(pre_cmds);
sk_OPENSSL_STRING_free(post_cmds);
BIO_free_all(out);
return ret;
}
diff --git a/crypto/openssl/apps/lib/http_server.c b/crypto/openssl/apps/lib/http_server.c
index a7fe5e1a58b0..33ae886d4a1c 100644
--- a/crypto/openssl/apps/lib/http_server.c
+++ b/crypto/openssl/apps/lib/http_server.c
@@ -1,533 +1,536 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* Very basic HTTP server */
#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 <string.h>
#include <ctype.h>
#include "http_server.h"
#include "internal/sockets.h"
#include <openssl/err.h>
#include <openssl/rand.h>
#include "s_apps.h"
#if defined(__TANDEM)
# if defined(OPENSSL_TANDEM_FLOSS)
# include <floss.h(floss_fork)>
# endif
#endif
static int verbosity = LOG_INFO;
#define HTTP_PREFIX "HTTP/"
#define HTTP_VERSION_PATT "1." /* allow 1.x */
#define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT
#define HTTP_1_0 HTTP_PREFIX_VERSION"0" /* "HTTP/1.0" */
#ifdef HTTP_DAEMON
int multi = 0; /* run multiple responder processes */
int acfd = (int) INVALID_SOCKET;
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;
}
#endif
void log_message(const char *prog, int level, const char *fmt, ...)
{
va_list ap;
if (verbosity < level)
return;
va_start(ap, fmt);
#ifdef HTTP_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);
} else
#endif
{
BIO_printf(bio_err, "%s: ", prog);
BIO_vprintf(bio_err, fmt, ap);
BIO_printf(bio_err, "\n");
(void)BIO_flush(bio_err);
}
va_end(ap);
}
#ifdef HTTP_DAEMON
void socket_timeout(int signum)
{
if (acfd != (int)INVALID_SOCKET)
(void)shutdown(acfd, SHUT_RD);
}
static void killall(int ret, pid_t *kidpids)
{
int i;
for (i = 0; i < multi; ++i)
if (kidpids[i] != 0)
(void)kill(kidpids[i], SIGTERM);
OPENSSL_free(kidpids);
ossl_sleep(1000);
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.
*/
void spawn_loop(const char *prog)
{
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
"");
ossl_sleep(1000);
}
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 */
ossl_sleep(30000);
break;
case 0: /* child */
OPENSSL_free(kidpids);
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
if (termsig)
_exit(0);
if (RAND_poll() <= 0) {
syslog(LOG_ERR, "fatal: RAND_poll() failed");
_exit(1);
}
return;
default: /* parent */
for (i = 0; i < multi; ++i) {
if (kidpids[i] == 0) {
kidpids[i] = fpid;
procs++;
break;
}
}
if (i >= multi) {
syslog(LOG_ERR, "fatal: internal error: no free child slots");
killall(1, kidpids);
}
break;
}
}
/* The loop above can only break on termsig */
syslog(LOG_INFO, "terminating on signal: %d", termsig);
killall(0, kidpids);
}
#endif
#ifndef OPENSSL_NO_SOCK
BIO *http_server_init_bio(const char *prog, const char *port)
{
BIO *acbio = NULL, *bufbio;
int asock;
+ char name[40];
+ snprintf(name, sizeof(name), "[::]:%s", port); /* port may be "0" */
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) {
+ || BIO_set_accept_ip_family(acbio, BIO_FAMILY_IPANY) <= 0 /* IPv4/6 */
+ || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) <= 0
+ || BIO_set_accept_name(acbio, name) <= 0) {
log_message(prog, 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(prog, LOG_ERR, "Error starting accept");
goto err;
}
/* Report back what address and port are used */
BIO_get_fd(acbio, &asock);
if (!report_server_accept(bio_out, asock, 1, 1)) {
log_message(prog, LOG_ERR, "Error printing ACCEPT string");
goto err;
}
return acbio;
err:
BIO_free_all(acbio);
BIO_free(bufbio);
return NULL;
}
/*
* Decode %xx URL-decoding in-place. Ignores malformed 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);
}
/* if *pcbio != NULL, continue given connected session, else accept new */
/* if found_keep_alive != NULL, return this way connection persistence state */
int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
char **ppath, BIO **pcbio, BIO *acbio,
int *found_keep_alive,
const char *prog, const char *port,
int accept_get, int timeout)
{
BIO *cbio = *pcbio, *getbio = NULL, *b64 = NULL;
int len;
char reqbuf[2048], inbuf[2048];
char *meth, *url, *end;
ASN1_VALUE *req;
int ret = 0;
*preq = NULL;
if (ppath != NULL)
*ppath = NULL;
if (cbio == NULL) {
log_message(prog, LOG_DEBUG,
"Awaiting new connection on port %s...", port);
if (BIO_do_accept(acbio) <= 0)
/* Connection loss before accept() is routine, ignore silently */
return ret;
*pcbio = cbio = BIO_pop(acbio);
} else {
log_message(prog, LOG_DEBUG, "Awaiting next request...");
}
if (cbio == NULL) {
/* Cannot call http_server_send_status(cbio, ...) */
ret = -1;
goto out;
}
# ifdef HTTP_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)
return ret;
ret = 1;
if (len < 0) {
log_message(prog, LOG_WARNING, "Request line read error");
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
if ((end = strchr(reqbuf, '\r')) != NULL
|| (end = strchr(reqbuf, '\n')) != NULL)
*end = '\0';
log_message(prog, LOG_INFO, "Received request, 1st line: %s", reqbuf);
meth = reqbuf;
url = meth + 3;
if ((accept_get && strncmp(meth, "GET ", 4) == 0)
|| (url++, strncmp(meth, "POST ", 5) == 0)) {
static const char http_version_str[] = " "HTTP_PREFIX_VERSION;
static const size_t http_version_str_len = sizeof(http_version_str) - 1;
/* Expecting (GET|POST) {sp} /URL {sp} HTTP/1.x */
*(url++) = '\0';
while (*url == ' ')
url++;
if (*url != '/') {
log_message(prog, LOG_WARNING,
"Invalid %s -- URL does not begin with '/': %s",
meth, url);
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
url++;
/* Splice off the HTTP version identifier. */
for (end = url; *end != '\0'; end++)
if (*end == ' ')
break;
if (strncmp(end, http_version_str, http_version_str_len) != 0) {
log_message(prog, LOG_WARNING,
"Invalid %s -- bad HTTP/version string: %s",
meth, end + 1);
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
*end = '\0';
/* above HTTP 1.0, connection persistence is the default */
if (found_keep_alive != NULL)
*found_keep_alive = end[http_version_str_len] > '0';
/*-
* Skip "GET / HTTP..." requests often used by load-balancers.
* 'url' was incremented above to point to the first byte *after*
* the leading slash, so in case 'GET / ' it is now an empty string.
*/
if (strlen(meth) == 3 && url[0] == '\0') {
(void)http_server_send_status(cbio, 200, "OK");
goto out;
}
len = urldecode(url);
if (len < 0) {
log_message(prog, LOG_WARNING,
"Invalid %s request -- bad URL encoding: %s",
meth, url);
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
if (strlen(meth) == 3) { /* GET */
if ((getbio = BIO_new_mem_buf(url, len)) == NULL
|| (b64 = BIO_new(BIO_f_base64())) == NULL) {
log_message(prog, LOG_ERR,
"Could not allocate base64 bio with size = %d",
len);
goto fatal;
}
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
getbio = BIO_push(b64, getbio);
}
} else {
log_message(prog, LOG_WARNING,
"HTTP request does not begin with %sPOST: %s",
accept_get ? "GET or " : "", reqbuf);
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
/* chop any further/duplicate leading or trailing '/' */
while (*url == '/')
url++;
while (end >= url + 2 && end[-2] == '/' && end[-1] == '/')
end--;
*end = '\0';
/* Read and skip past the headers. */
for (;;) {
char *key, *value, *line_end = NULL;
len = BIO_gets(cbio, inbuf, sizeof(inbuf));
if (len <= 0) {
log_message(prog, LOG_WARNING, "Error reading HTTP header");
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
if (inbuf[0] == '\r' || inbuf[0] == '\n')
break;
key = inbuf;
value = strchr(key, ':');
if (value == NULL) {
log_message(prog, LOG_WARNING,
"Error parsing HTTP header: missing ':'");
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
*(value++) = '\0';
while (*value == ' ')
value++;
line_end = strchr(value, '\r');
if (line_end == NULL) {
line_end = strchr(value, '\n');
if (line_end == NULL) {
log_message(prog, LOG_WARNING,
"Error parsing HTTP header: missing end of line");
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
}
*line_end = '\0';
/* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */
if (found_keep_alive != NULL
&& OPENSSL_strcasecmp(key, "Connection") == 0) {
if (OPENSSL_strcasecmp(value, "keep-alive") == 0)
*found_keep_alive = 1;
else if (OPENSSL_strcasecmp(value, "close") == 0)
*found_keep_alive = 0;
}
}
# ifdef HTTP_DAEMON
/* Clear alarm before we close the client socket */
alarm(0);
timeout = 0;
# endif
/* Try to read and parse request */
req = ASN1_item_d2i_bio(it, getbio != NULL ? getbio : cbio, NULL);
if (req == NULL) {
log_message(prog, LOG_WARNING,
"Error parsing DER-encoded request content");
(void)http_server_send_status(cbio, 400, "Bad Request");
} else if (ppath != NULL && (*ppath = OPENSSL_strdup(url)) == NULL) {
log_message(prog, LOG_ERR,
"Out of memory allocating %zu bytes", strlen(url) + 1);
ASN1_item_free(req, it);
goto fatal;
}
*preq = req;
out:
BIO_free_all(getbio);
# ifdef HTTP_DAEMON
if (timeout > 0)
alarm(0);
acfd = (int)INVALID_SOCKET;
# endif
return ret;
fatal:
(void)http_server_send_status(cbio, 500, "Internal Server Error");
if (ppath != NULL) {
OPENSSL_free(*ppath);
*ppath = NULL;
}
BIO_free_all(cbio);
*pcbio = NULL;
ret = -1;
goto out;
}
/* assumes that cbio does not do an encoding that changes the output length */
int http_server_send_asn1_resp(BIO *cbio, int keep_alive,
const char *content_type,
const ASN1_ITEM *it, const ASN1_VALUE *resp)
{
int ret = BIO_printf(cbio, HTTP_1_0" 200 OK\r\n%s"
"Content-type: %s\r\n"
"Content-Length: %d\r\n\r\n",
keep_alive ? "Connection: keep-alive\r\n" : "",
content_type,
ASN1_item_i2d(resp, NULL, it)) > 0
&& ASN1_item_i2d_bio(it, cbio, resp) > 0;
(void)BIO_flush(cbio);
return ret;
}
int http_server_send_status(BIO *cbio, int status, const char *reason)
{
int ret = BIO_printf(cbio, HTTP_1_0" %d %s\r\n\r\n",
/* This implicitly cancels keep-alive */
status, reason) > 0;
(void)BIO_flush(cbio);
return ret;
}
#endif
diff --git a/crypto/openssl/apps/lib/s_cb.c b/crypto/openssl/apps/lib/s_cb.c
index 6440b496099e..9f33c24c4e35 100644
--- a/crypto/openssl/apps/lib/s_cb.c
+++ b/crypto/openssl/apps/lib/s_cb.c
@@ -1,1572 +1,1592 @@
/*
* Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/core_names.h>
#include <openssl/params.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/bn.h>
#ifndef OPENSSL_NO_DH
# include <openssl/dh.h>
#endif
#include "s_apps.h"
#define COOKIE_SECRET_LENGTH 16
VERIFY_CB_ARGS verify_args = { -1, 0, X509_V_OK, 0 };
#ifndef OPENSSL_NO_SOCK
static unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
static int cookie_initialized = 0;
#endif
static BIO *bio_keylog = NULL;
static const char *lookup(int val, const STRINT_PAIR* list, const char* def)
{
for ( ; list->name; ++list)
if (list->retval == val)
return list->name;
return def;
}
int verify_callback(int ok, X509_STORE_CTX *ctx)
{
X509 *err_cert;
int err, depth;
err_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx);
depth = X509_STORE_CTX_get_error_depth(ctx);
if (!verify_args.quiet || !ok) {
BIO_printf(bio_err, "depth=%d ", depth);
if (err_cert != NULL) {
X509_NAME_print_ex(bio_err,
X509_get_subject_name(err_cert),
0, get_nameopt());
BIO_puts(bio_err, "\n");
} else {
BIO_puts(bio_err, "<no cert>\n");
}
}
if (!ok) {
BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
X509_verify_cert_error_string(err));
if (verify_args.depth < 0 || verify_args.depth >= depth) {
if (!verify_args.return_error)
ok = 1;
verify_args.error = err;
} else {
ok = 0;
verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
}
}
switch (err) {
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
if (err_cert != NULL) {
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:
if (err_cert != NULL) {
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:
if (err_cert != NULL) {
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},
{"GOST12 Sign", TLS_CT_GOST12_IANA_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";
+ return "ed25519";
case NID_ED448:
- return "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, ":");
+ switch (rsign | rhash << 8) {
+ case 0x0809:
+ BIO_puts(out, "rsa_pss_pss_sha256");
+ continue;
+ case 0x080a:
+ BIO_puts(out, "rsa_pss_pss_sha384");
+ continue;
+ case 0x080b:
+ BIO_puts(out, "rsa_pss_pss_sha512");
+ continue;
+ case 0x081a:
+ BIO_puts(out, "ecdsa_brainpoolP256r1_sha256");
+ continue;
+ case 0x081b:
+ BIO_puts(out, "ecdsa_brainpoolP384r1_sha384");
+ continue;
+ case 0x081c:
+ BIO_puts(out, "ecdsa_brainpoolP512r1_sha512");
+ continue;
+ }
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;
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 groups: ");
for (i = 0; i < ngroups; i++) {
if (i)
BIO_puts(out, ":");
nid = groups[i];
BIO_printf(out, "%s", SSL_group_to_name(s, nid));
}
OPENSSL_free(groups);
if (noshared) {
BIO_puts(out, "\n");
return 1;
}
BIO_puts(out, "\nShared 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);
BIO_printf(out, "%s", SSL_group_to_name(s, nid));
}
if (ngroups == 0)
BIO_puts(out, "NONE");
BIO_puts(out, "\n");
return 1;
}
#endif
int ssl_print_tmp_key(BIO *out, SSL *s)
{
EVP_PKEY *key;
if (!SSL_get_peer_tmp_key(s, &key))
return 1;
BIO_puts(out, "Server Temp Key: ");
switch (EVP_PKEY_get_id(key)) {
case EVP_PKEY_RSA:
BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_get_bits(key));
break;
case EVP_PKEY_DH:
BIO_printf(out, "DH, %d bits\n", EVP_PKEY_get_bits(key));
break;
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
{
char name[80];
size_t name_len;
if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME,
name, sizeof(name), &name_len))
strcpy(name, "?");
BIO_printf(out, "ECDH, %s, %d bits\n", name, EVP_PKEY_get_bits(key));
}
break;
#endif
default:
BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_get_id(key)),
EVP_PKEY_get_bits(key));
}
EVP_PKEY_free(key);
return 1;
}
long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len,
int argi, long argl, int ret, size_t *processed)
{
BIO *out;
out = (BIO *)BIO_get_callback_arg(bio);
if (out == NULL)
return ret;
if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
if (ret > 0 && processed != NULL) {
BIO_printf(out, "read from %p [%p] (%zu bytes => %zu (0x%zX))\n",
(void *)bio, (void *)argp, len, *processed, *processed);
BIO_dump(out, argp, (int)*processed);
} else {
BIO_printf(out, "read from %p [%p] (%zu bytes => %d)\n",
(void *)bio, (void *)argp, len, ret);
}
} else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
if (ret > 0 && processed != NULL) {
BIO_printf(out, "write to %p [%p] (%zu bytes => %zu (0x%zX))\n",
(void *)bio, (void *)argp, len, *processed, *processed);
BIO_dump(out, argp, (int)*processed);
} else {
BIO_printf(out, "write to %p [%p] (%zu bytes => %d)\n",
(void *)bio, (void *)argp, len, 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 ? ">>>" : "<<<";
char tmpbuf[128];
const char *str_version, *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) {
str_version = lookup(version, ssl_versions, "???");
switch (content_type) {
case SSL3_RT_CHANGE_CIPHER_SPEC:
/* type 20 */
str_content_type = ", ChangeCipherSpec";
break;
case SSL3_RT_ALERT:
/* type 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 SSL3_RT_HANDSHAKE:
/* type 22 */
str_content_type = ", Handshake";
str_details1 = "???";
if (len > 0)
str_details1 = lookup((int)bp[0], handshakes, "???");
break;
case SSL3_RT_APPLICATION_DATA:
/* type 23 */
str_content_type = ", ApplicationData";
break;
case SSL3_RT_HEADER:
/* type 256 */
str_content_type = ", RecordHeader";
break;
case SSL3_RT_INNER_CONTENT_TYPE:
/* type 257 */
str_content_type = ", InnerContent";
break;
default:
BIO_snprintf(tmpbuf, sizeof(tmpbuf)-1, ", Unknown (content_type=%d)", content_type);
str_content_type = tmpbuf;
}
} else {
BIO_snprintf(tmpbuf, sizeof(tmpbuf)-1, "Not TLS data or unknown version (version=%d, content_type=%d)", version, content_type);
str_version = tmpbuf;
}
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 const 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},
{"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},
{"early_data", TLSEXT_TYPE_early_data},
{NULL}
};
/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */
static STRINT_PAIR signature_tls13_scheme_list[] = {
{"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */},
{"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */},
/* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */
/* {"ecdsa_sha224", 0x0303 TLSEXT_SIGALG_ecdsa_sha224} not in rfc8446 */
{"rsa_pkcs1_sha256", 0x0401 /* TLSEXT_SIGALG_rsa_pkcs1_sha256 */},
{"ecdsa_secp256r1_sha256", 0x0403 /* TLSEXT_SIGALG_ecdsa_secp256r1_sha256 */},
{"rsa_pkcs1_sha384", 0x0501 /* TLSEXT_SIGALG_rsa_pkcs1_sha384 */},
{"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */},
{"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */},
{"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */},
{"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */},
{"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */},
{"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */},
{"ed25519", 0x0807 /* TLSEXT_SIGALG_ed25519 */},
{"ed448", 0x0808 /* TLSEXT_SIGALG_ed448 */},
{"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */},
{"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */},
{"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */},
{"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */},
{"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */},
{"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */},
{NULL}
};
/* from rfc5246 7.4.1.4.1. */
static STRINT_PAIR signature_tls12_alg_list[] = {
{"anonymous", TLSEXT_signature_anonymous /* 0 */},
{"RSA", TLSEXT_signature_rsa /* 1 */},
{"DSA", TLSEXT_signature_dsa /* 2 */},
{"ECDSA", TLSEXT_signature_ecdsa /* 3 */},
{NULL}
};
/* from rfc5246 7.4.1.4.1. */
static STRINT_PAIR signature_tls12_hash_list[] = {
{"none", TLSEXT_hash_none /* 0 */},
{"MD5", TLSEXT_hash_md5 /* 1 */},
{"SHA1", TLSEXT_hash_sha1 /* 2 */},
{"SHA224", TLSEXT_hash_sha224 /* 3 */},
{"SHA256", TLSEXT_hash_sha256 /* 4 */},
{"SHA384", TLSEXT_hash_sha384 /* 5 */},
{"SHA512", TLSEXT_hash_sha512 /* 6 */},
{NULL}
};
void tlsext_cb(SSL *s, int client_server, int type,
const unsigned char *data, int len, void *arg)
{
BIO *bio = arg;
const char *extname = lookup(type, tlsext_types, "unknown");
BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
client_server ? "server" : "client", extname, type, len);
BIO_dump(bio, (const char *)data, len);
(void)BIO_flush(bio);
}
#ifndef OPENSSL_NO_SOCK
int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
size_t *cookie_len)
{
unsigned char *buffer = NULL;
size_t length = 0;
unsigned short port;
BIO_ADDR *lpeer = NULL, *peer = NULL;
int res = 0;
/* 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");
BIO_ADDR_free(lpeer);
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);
if (EVP_Q_mac(NULL, "HMAC", NULL, "SHA1", NULL,
cookie_secret, COOKIE_SECRET_LENGTH, buffer, length,
cookie, DTLS1_COOKIE_LENGTH, cookie_len) == NULL) {
BIO_printf(bio_err,
"Error calculating HMAC-SHA1 of buffer with secret\n");
goto end;
}
res = 1;
end:
OPENSSL_free(buffer);
BIO_ADDR_free(lpeer);
return res;
}
int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
size_t cookie_len)
{
unsigned char result[EVP_MAX_MD_SIZE];
size_t resultlength;
/* Note: we check cookie_initialized because if it's not,
* it cannot be valid */
if (cookie_initialized
&& generate_stateless_cookie_callback(ssl, result, &resultlength)
&& cookie_len == resultlength
&& memcmp(result, cookie, resultlength) == 0)
return 1;
return 0;
}
int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
unsigned int *cookie_len)
{
size_t temp = 0;
int res = generate_stateless_cookie_callback(ssl, cookie, &temp);
if (res != 0)
*cookie_len = (unsigned int)temp;
return res;
}
int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
unsigned int cookie_len)
{
return verify_stateless_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) {
if (!SSL_set1_chain(ssl, exc->chain))
return 0;
}
}
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, 0, &exc->chain, 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_ANY, &exc->certform))
return 0;
break;
case OPT_X_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &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_get0_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");
}
#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) {
BIO_printf(bio_err, "Call to SSL_CONF_cmd(%s, %s) failed\n",
flag, arg == NULL ? "<NULL>" : arg);
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, ret = 1;
for (i = 0; i < sk_X509_CRL_num(crls); i++) {
crl = sk_X509_CRL_value(crls, i);
if (!X509_STORE_add_crl(st, crl))
ret = 0;
}
return ret;
}
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 *vfyCAstore,
const char *chCApath, const char *chCAfile,
const char *chCAstore,
STACK_OF(X509_CRL) *crls, int crl_download)
{
X509_STORE *vfy = NULL, *ch = NULL;
int rv = 0;
if (vfyCApath != NULL || vfyCAfile != NULL || vfyCAstore != NULL) {
vfy = X509_STORE_new();
if (vfy == NULL)
goto err;
if (vfyCAfile != NULL && !X509_STORE_load_file(vfy, vfyCAfile))
goto err;
if (vfyCApath != NULL && !X509_STORE_load_path(vfy, vfyCApath))
goto err;
if (vfyCAstore != NULL && !X509_STORE_load_store(vfy, vfyCAstore))
goto err;
add_crls_store(vfy, crls);
if (SSL_CTX_set1_verify_cert_store(ctx, vfy) == 0)
goto err;
if (crl_download)
store_setup_crl_download(vfy);
}
if (chCApath != NULL || chCAfile != NULL || chCAstore != NULL) {
ch = X509_STORE_new();
if (ch == NULL)
goto err;
if (chCAfile != NULL && !X509_STORE_load_file(ch, chCAfile))
goto err;
if (chCApath != NULL && !X509_STORE_load_path(ch, chCApath))
goto err;
if (chCAstore != NULL && !X509_STORE_load_store(ch, chCAstore))
goto err;
if (SSL_CTX_set1_chain_cert_store(ctx, ch) == 0)
goto err;
}
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", SSL_SECOP_SIGALG_SUPPORTED},
{"Shared Signature Algorithm", SSL_SECOP_SIGALG_SHARED},
{"Check Signature Algorithm", SSL_SECOP_SIGALG_CHECK},
{"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK},
{"Certificate chain EE key", SSL_SECOP_EE_KEY},
{"Certificate chain CA key", SSL_SECOP_CA_KEY},
{"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY},
{"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY},
{"Certificate chain CA digest", SSL_SECOP_CA_MD},
{"Peer chain CA digest", SSL_SECOP_PEER_CA_MD},
{"SSL compression", SSL_SECOP_COMPRESSION},
{"Session ticket", SSL_SECOP_TICKET},
{NULL}
};
static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid,
void *other, void *ex)
{
security_debug_ex *sdb = ex;
int rv, show_bits = 1, cert_md = 0;
const char *nm;
int show_nm;
rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
if (rv == 1 && sdb->verbose < 2)
return 1;
BIO_puts(sdb->out, "Security callback: ");
nm = lookup(op, callback_types, NULL);
show_nm = nm != NULL;
switch (op) {
case SSL_SECOP_TICKET:
case SSL_SECOP_COMPRESSION:
show_bits = 0;
show_nm = 0;
break;
case SSL_SECOP_VERSION:
BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???"));
show_bits = 0;
show_nm = 0;
break;
case SSL_SECOP_CA_MD:
case SSL_SECOP_PEER_CA_MD:
cert_md = 1;
break;
case SSL_SECOP_SIGALG_SUPPORTED:
case SSL_SECOP_SIGALG_SHARED:
case SSL_SECOP_SIGALG_CHECK:
case SSL_SECOP_SIGALG_MASK:
show_nm = 0;
break;
}
if (show_nm)
BIO_printf(sdb->out, "%s=", nm);
switch (op & SSL_SECOP_OTHER_TYPE) {
case SSL_SECOP_OTHER_CIPHER:
BIO_puts(sdb->out, SSL_CIPHER_get_name(other));
break;
#ifndef OPENSSL_NO_EC
case SSL_SECOP_OTHER_CURVE:
{
const char *cname;
cname = EC_curve_nid2nist(nid);
if (cname == NULL)
cname = OBJ_nid2sn(nid);
BIO_puts(sdb->out, cname);
}
break;
#endif
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);
if (pkey == NULL) {
BIO_printf(sdb->out, "Public key missing");
} else {
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_get_bits(pkey));
}
}
break;
}
case SSL_SECOP_OTHER_SIGALG:
{
const unsigned char *salg = other;
const char *sname = NULL;
int raw_sig_code = (salg[0] << 8) + salg[1]; /* always big endian (msb, lsb) */
/* raw_sig_code: signature_scheme from tls1.3, or signature_and_hash from tls1.2 */
if (nm != NULL)
BIO_printf(sdb->out, "%s", nm);
else
BIO_printf(sdb->out, "s_cb.c:security_callback_debug op=0x%x", op);
sname = lookup(raw_sig_code, signature_tls13_scheme_list, NULL);
if (sname != NULL) {
BIO_printf(sdb->out, " scheme=%s", sname);
} else {
int alg_code = salg[1];
int hash_code = salg[0];
const char *alg_str = lookup(alg_code, signature_tls12_alg_list, NULL);
const char *hash_str = lookup(hash_code, signature_tls12_hash_list, NULL);
if (alg_str != NULL && hash_str != NULL)
BIO_printf(sdb->out, " digest=%s, algorithm=%s", hash_str, alg_str);
else
BIO_printf(sdb->out, " scheme=unknown(0x%04x)", raw_sig_code);
}
}
}
if (show_bits)
BIO_printf(sdb->out, ", security bits=%d", bits);
BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no");
return rv;
}
void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose)
{
static security_debug_ex sdb;
sdb.out = bio_err;
sdb.verbose = verbose;
sdb.old_cb = SSL_CTX_get_security_callback(ctx);
SSL_CTX_set_security_callback(ctx, security_callback_debug);
SSL_CTX_set0_security_ex_data(ctx, &sdb);
}
static void keylog_callback(const SSL *ssl, const char *line)
{
if (bio_keylog == NULL) {
BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n");
return;
}
/*
* There might be concurrent writers to the keylog file, so we must ensure
* that the given line is written at once.
*/
BIO_printf(bio_keylog, "%s\n", line);
(void)BIO_flush(bio_keylog);
}
int set_keylog_file(SSL_CTX *ctx, const char *keylog_file)
{
/* Close any open files */
BIO_free_all(bio_keylog);
bio_keylog = NULL;
if (ctx == NULL || keylog_file == NULL) {
/* Keylogging is disabled, OK. */
return 0;
}
/*
* Append rather than write in order to allow concurrent modification.
* Furthermore, this preserves existing keylog files which is useful when
* the tool is run multiple times.
*/
bio_keylog = BIO_new_file(keylog_file, "a");
if (bio_keylog == NULL) {
BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file);
return 1;
}
/* Write a header for seekable, empty files (this excludes pipes). */
if (BIO_tell(bio_keylog) == 0) {
BIO_puts(bio_keylog,
"# SSL/TLS secrets log file, generated by OpenSSL\n");
(void)BIO_flush(bio_keylog);
}
SSL_CTX_set_keylog_callback(ctx, keylog_callback);
return 0;
}
void print_ca_names(BIO *bio, SSL *s)
{
const char *cs = SSL_is_server(s) ? "server" : "client";
const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s);
int i;
if (sk == NULL || sk_X509_NAME_num(sk) == 0) {
if (!SSL_is_server(s))
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/crypto/openssl/apps/lib/s_socket.c b/crypto/openssl/apps/lib/s_socket.c
index 059afe47b904..8c6020d01692 100644
--- a/crypto/openssl/apps/lib/s_socket.c
+++ b/crypto/openssl/apps/lib/s_socket.c
@@ -1,455 +1,462 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* socket-related functions used by s_client and s_server */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <openssl/opensslconf.h>
/*
* 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
#ifdef _WIN32
# include <process.h>
/* MSVC renamed some POSIX functions to have an underscore prefix. */
# ifdef _MSC_VER
# define getpid _getpid
# endif
#endif
#ifndef OPENSSL_NO_SOCK
# include "apps.h"
# include "s_apps.h"
# include "internal/sockets.h"
# if defined(__TANDEM)
# if defined(OPENSSL_TANDEM_FLOSS)
# include <floss.h(floss_read)>
# endif
# endif
# include <openssl/bio.h>
# include <openssl/err.h>
/* Keep track of our peer's address for the cookie callback */
BIO_ADDR *ourpeer = NULL;
/*
* init_client - helper routine to set up socket communication
* @sock: pointer to storage of resulting socket.
* @host: the host name or path (for AF_UNIX) to connect to.
* @port: the port to connect to (ignored for AF_UNIX).
* @bindhost: source host or path (for AF_UNIX).
* @bindport: source port (ignored for AF_UNIX).
* @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
* AF_UNSPEC
* @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
* @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any)
*
* This will create a socket and use it to connect to a host:port, or if
* family == AF_UNIX, to the path found in host.
*
* If the host has more than one address, it will try them one by one until
* a successful connection is established. The resulting socket will be
* found in *sock on success, it will be given INVALID_SOCKET otherwise.
*
* Returns 1 on success, 0 on failure.
*/
int init_client(int *sock, const char *host, const char *port,
const char *bindhost, const char *bindport,
int family, int type, int protocol)
{
BIO_ADDRINFO *res = NULL;
BIO_ADDRINFO *bindaddr = NULL;
const BIO_ADDRINFO *ai = NULL;
const BIO_ADDRINFO *bi = NULL;
int found = 0;
int ret;
if (BIO_sock_init() != 1)
return 0;
ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol,
&res);
if (ret == 0) {
ERR_print_errors(bio_err);
return 0;
}
if (bindhost != NULL || bindport != NULL) {
ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT,
family, type, protocol, &bindaddr);
if (ret == 0) {
ERR_print_errors (bio_err);
goto out;
}
}
ret = 0;
for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
/* Admittedly, these checks are quite paranoid, we should not get
* anything in the BIO_ADDRINFO chain that we haven't
* asked for. */
OPENSSL_assert((family == AF_UNSPEC
|| family == BIO_ADDRINFO_family(ai))
&& (type == 0 || type == BIO_ADDRINFO_socktype(ai))
&& (protocol == 0
|| protocol == BIO_ADDRINFO_protocol(ai)));
if (bindaddr != NULL) {
for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) {
if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai))
break;
}
if (bi == NULL)
continue;
++found;
}
*sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai),
BIO_ADDRINFO_protocol(ai), 0);
if (*sock == INVALID_SOCKET) {
/* Maybe the kernel doesn't support the socket family, even if
* BIO_lookup() added it in the returned result...
*/
continue;
}
if (bi != NULL) {
if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi),
BIO_SOCK_REUSEADDR)) {
BIO_closesocket(*sock);
*sock = INVALID_SOCKET;
break;
}
}
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP) {
/*
* For SCTP we have to set various options on the socket prior to
* connecting. This is done automatically by BIO_new_dgram_sctp().
* We don't actually need the created BIO though so we free it again
* immediately.
*/
BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE);
if (tmpbio == NULL) {
ERR_print_errors(bio_err);
return 0;
}
BIO_free(tmpbio);
}
#endif
if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai),
BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) {
BIO_closesocket(*sock);
*sock = INVALID_SOCKET;
continue;
}
/* Success, don't try any more addresses */
break;
}
if (*sock == INVALID_SOCKET) {
if (bindaddr != NULL && !found) {
BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n",
#ifdef AF_INET6
BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " :
#endif
BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " :
BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "",
bindhost != NULL ? bindhost : "",
bindport != NULL ? ":" : "",
bindport != NULL ? bindport : "");
ERR_clear_error();
ret = 0;
}
ERR_print_errors(bio_err);
} else {
/* Remove any stale errors from previous connection attempts */
ERR_clear_error();
ret = 1;
}
out:
if (bindaddr != NULL) {
BIO_ADDRINFO_free (bindaddr);
}
BIO_ADDRINFO_free(res);
return ret;
}
int report_server_accept(BIO *out, int asock, int with_address, int with_pid)
{
int success = 1;
if (BIO_printf(out, "ACCEPT") <= 0)
return 0;
if (with_address) {
union BIO_sock_info_u info;
char *hostname = NULL;
char *service = NULL;
if ((info.addr = BIO_ADDR_new()) != NULL
&& BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info)
&& (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL
&& (service = BIO_ADDR_service_string(info.addr, 1)) != NULL) {
success = BIO_printf(out,
strchr(hostname, ':') == NULL
? /* IPv4 */ " %s:%s"
: /* IPv6 */ " [%s]:%s",
hostname, service) > 0;
} else {
(void)BIO_printf(out, "unknown:error\n");
success = 0;
}
OPENSSL_free(hostname);
OPENSSL_free(service);
BIO_ADDR_free(info.addr);
}
if (with_pid)
success = success && BIO_printf(out, " PID=%d", getpid()) > 0;
success = success && BIO_printf(out, "\n") > 0;
(void)BIO_flush(out);
return success;
}
/*
* do_server - helper routine to perform a server operation
* @accept_sock: pointer to storage of resulting socket.
* @host: the host name or path (for AF_UNIX) to connect to.
* @port: the port to connect to (ignored for AF_UNIX).
* @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
* AF_UNSPEC
* @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
* @cb: pointer to a function that receives the accepted socket and
* should perform the communication with the connecting client.
* @context: pointer to memory that's passed verbatim to the cb function.
* @naccept: number of times an incoming connect should be accepted. If -1,
* unlimited number.
*
* This will create a socket and use it to listen to a host:port, or if
* family == AF_UNIX, to the path found in host, then start accepting
* incoming connections and run cb on the resulting socket.
*
* 0 on failure, something other on success.
*/
int do_server(int *accept_sock, const char *host, const char *port,
int family, int type, int protocol, do_server_cb cb,
unsigned char *context, int naccept, BIO *bio_s_out)
{
int asock = 0;
int sock;
int i;
BIO_ADDRINFO *res = NULL;
const BIO_ADDRINFO *next;
int sock_family, sock_type, sock_protocol, sock_port;
const BIO_ADDR *sock_address;
int sock_family_fallback = AF_UNSPEC;
const BIO_ADDR *sock_address_fallback = NULL;
int sock_options = BIO_SOCK_REUSEADDR;
int ret = 0;
if (BIO_sock_init() != 1)
return 0;
if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol,
&res)) {
ERR_print_errors(bio_err);
return 0;
}
/* Admittedly, these checks are quite paranoid, we should not get
* anything in the BIO_ADDRINFO chain that we haven't asked for */
OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res))
&& (type == 0 || type == BIO_ADDRINFO_socktype(res))
&& (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res)));
sock_family = BIO_ADDRINFO_family(res);
sock_type = BIO_ADDRINFO_socktype(res);
sock_protocol = BIO_ADDRINFO_protocol(res);
sock_address = BIO_ADDRINFO_address(res);
next = BIO_ADDRINFO_next(res);
#ifdef AF_INET6
if (sock_family == AF_INET6)
sock_options |= BIO_SOCK_V6_ONLY;
if (next != NULL
&& BIO_ADDRINFO_socktype(next) == sock_type
&& BIO_ADDRINFO_protocol(next) == sock_protocol) {
if (sock_family == AF_INET
&& BIO_ADDRINFO_family(next) == AF_INET6) {
/* In case AF_INET6 is returned but not supported by the
* kernel, retry with the first detected address family */
sock_family_fallback = sock_family;
sock_address_fallback = sock_address;
sock_family = AF_INET6;
sock_address = BIO_ADDRINFO_address(next);
} else if (sock_family == AF_INET6
&& BIO_ADDRINFO_family(next) == AF_INET) {
sock_options &= ~BIO_SOCK_V6_ONLY;
}
}
#endif
asock = BIO_socket(sock_family, sock_type, sock_protocol, 0);
if (asock == INVALID_SOCKET && sock_family_fallback != AF_UNSPEC) {
asock = BIO_socket(sock_family_fallback, sock_type, sock_protocol, 0);
sock_address = sock_address_fallback;
}
if (asock == INVALID_SOCKET
|| !BIO_listen(asock, sock_address, sock_options)) {
BIO_ADDRINFO_free(res);
ERR_print_errors(bio_err);
if (asock != INVALID_SOCKET)
BIO_closesocket(asock);
goto end;
}
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP) {
/*
* For SCTP we have to set various options on the socket prior to
* accepting. This is done automatically by BIO_new_dgram_sctp().
* We don't actually need the created BIO though so we free it again
* immediately.
*/
BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE);
if (tmpbio == NULL) {
BIO_closesocket(asock);
ERR_print_errors(bio_err);
goto end;
}
BIO_free(tmpbio);
}
#endif
sock_port = BIO_ADDR_rawport(sock_address);
BIO_ADDRINFO_free(res);
res = NULL;
if (!report_server_accept(bio_s_out, asock, sock_port == 0, 0)) {
BIO_closesocket(asock);
ERR_print_errors(bio_err);
goto end;
}
if (accept_sock != NULL)
*accept_sock = asock;
for (;;) {
char sink[64];
struct timeval timeout;
fd_set readfds;
if (type == SOCK_STREAM) {
BIO_ADDR_free(ourpeer);
ourpeer = BIO_ADDR_new();
if (ourpeer == NULL) {
BIO_closesocket(asock);
ERR_print_errors(bio_err);
goto end;
}
do {
sock = BIO_accept_ex(asock, ourpeer, 0);
} while (sock < 0 && BIO_sock_should_retry(sock));
if (sock < 0) {
ERR_print_errors(bio_err);
BIO_closesocket(asock);
break;
}
+
+ if (naccept != -1)
+ naccept--;
+ if (naccept == 0)
+ BIO_closesocket(asock);
+
BIO_set_tcp_ndelay(sock, 1);
i = (*cb)(sock, type, protocol, context);
/*
* If we ended with an alert being sent, but still with data in the
* network buffer to be read, then calling BIO_closesocket() will
* result in a TCP-RST being sent. On some platforms (notably
* Windows) then this will result in the peer immediately abandoning
* the connection including any buffered alert data before it has
* had a chance to be read. Shutting down the sending side first,
* and then closing the socket sends TCP-FIN first followed by
* TCP-RST. This seems to allow the peer to read the alert data.
*/
shutdown(sock, 1); /* SHUT_WR */
/*
* We just said we have nothing else to say, but it doesn't mean
* that the other side has nothing. It's even recommended to
* consume incoming data. [In testing context this ensures that
* alerts are passed on...]
*/
timeout.tv_sec = 0;
timeout.tv_usec = 500000; /* some extreme round-trip */
do {
FD_ZERO(&readfds);
openssl_fdset(sock, &readfds);
} while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0
&& readsocket(sock, sink, sizeof(sink)) > 0);
BIO_closesocket(sock);
} else {
+ if (naccept != -1)
+ naccept--;
+
i = (*cb)(asock, type, protocol, context);
}
- if (naccept != -1)
- naccept--;
if (i < 0 || naccept == 0) {
BIO_closesocket(asock);
ret = i;
break;
}
}
end:
# ifdef AF_UNIX
if (family == AF_UNIX)
unlink(host);
# endif
BIO_ADDR_free(ourpeer);
ourpeer = NULL;
return ret;
}
void do_ssl_shutdown(SSL *ssl)
{
int ret;
do {
/* We only do unidirectional shutdown */
ret = SSL_shutdown(ssl);
if (ret < 0) {
switch (SSL_get_error(ssl, ret)) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_ASYNC:
case SSL_ERROR_WANT_ASYNC_JOB:
/* We just do busy waiting. Nothing clever */
continue;
}
ret = 0;
}
} while (ret < 0);
}
#endif /* OPENSSL_NO_SOCK */
diff --git a/crypto/openssl/apps/lib/vms_term_sock.c b/crypto/openssl/apps/lib/vms_term_sock.c
index 97fb3943265c..1a413376b20b 100644
--- a/crypto/openssl/apps/lib/vms_term_sock.c
+++ b/crypto/openssl/apps/lib/vms_term_sock.c
@@ -1,591 +1,591 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2016 VMS Software, Inc. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
#ifdef __VMS
# define OPENSSL_SYS_VMS
# pragma message disable DOLLARID
# include <openssl/opensslconf.h>
# 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>
# undef _POSIX_C_SOURCE
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <inet.h>
# include <unistd.h>
# include <string.h>
# include <errno.h>
# include <starlet.h>
# include <iodef.h>
# ifdef __alpha
# include <iosbdef.h>
# else
typedef struct _iosb { /* Copied from IOSBDEF.H for Alpha */
# pragma __nomember_alignment
__union {
__struct {
unsigned short int iosb$w_status; /* Final I/O status */
__union {
__struct { /* 16-bit byte count variant */
unsigned short int iosb$w_bcnt; /* 16-bit byte count */
__union {
unsigned int iosb$l_dev_depend; /* 32-bit device dependent info */
unsigned int iosb$l_pid; /* 32-bit pid */
} iosb$r_l;
} iosb$r_bcnt_16;
__struct { /* 32-bit byte count variant */
unsigned int iosb$l_bcnt; /* 32-bit byte count (unaligned) */
unsigned short int iosb$w_dev_depend_high; /* 16-bit device dependent info */
} iosb$r_bcnt_32;
} iosb$r_devdepend;
} iosb$r_io_64;
__struct {
__union {
unsigned int iosb$l_getxxi_status; /* Final GETxxI status */
unsigned int iosb$l_reg_status; /* Final $Registry status */
} iosb$r_l_status;
unsigned int iosb$l_reserved; /* Reserved field */
} iosb$r_get_64;
} iosb$r_io_get;
} IOSB;
# if !defined(__VAXC)
# define iosb$w_status iosb$r_io_get.iosb$r_io_64.iosb$w_status
# define iosb$w_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$w_bcnt
# define iosb$r_l iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$r_l
# define iosb$l_dev_depend iosb$r_l.iosb$l_dev_depend
# define iosb$l_pid iosb$r_l.iosb$l_pid
# define iosb$l_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$l_bcnt
# define iosb$w_dev_depend_high iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$w_dev_depend_high
# define iosb$l_getxxi_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_getxxi_status
# define iosb$l_reg_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_reg_status
# endif /* #if !defined(__VAXC) */
# endif /* End of IOSBDEF */
# include <efndef.h>
# include <stdlib.h>
# include <ssdef.h>
# include <time.h>
# include <stdarg.h>
# include <descrip.h>
# include "vms_term_sock.h"
# ifdef __alpha
static struct _iosb TerminalDeviceIosb;
# else
IOSB TerminalDeviceIosb;
# endif
static char TerminalDeviceBuff[255 + 2];
static int TerminalSocketPair[2] = {0, 0};
static unsigned short TerminalDeviceChan = 0;
static int CreateSocketPair (int, int, int, int *);
static void SocketPairTimeoutAst (int);
static int TerminalDeviceAst (int);
static void LogMessage (char *, ...);
/*
** Socket Pair Timeout Value (must be 0-59 seconds)
*/
# define SOCKET_PAIR_TIMEOUT_VALUE 20
/*
** Socket Pair Timeout Block which is passed to timeout AST
*/
typedef struct _SocketPairTimeoutBlock {
unsigned short SockChan1;
unsigned short SockChan2;
} SPTB;
# ifdef TERM_SOCK_TEST
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
int main (int argc, char *argv[], char *envp[])
{
char TermBuff[80];
int TermSock,
status,
len;
LogMessage ("Enter 'q' or 'Q' to quit ...");
while (OPENSSL_strcasecmp (TermBuff, "Q")) {
/*
** Create the terminal socket
*/
status = TerminalSocket (TERM_SOCK_CREATE, &TermSock);
if (status != TERM_SOCK_SUCCESS)
exit (1);
/*
** Process the terminal input
*/
LogMessage ("Waiting on terminal I/O ...\n");
len = recv (TermSock, TermBuff, sizeof(TermBuff), 0) ;
TermBuff[len] = '\0';
LogMessage ("Received terminal I/O [%s]", TermBuff);
/*
** Delete the terminal socket
*/
status = TerminalSocket (TERM_SOCK_DELETE, &TermSock);
if (status != TERM_SOCK_SUCCESS)
exit (1);
}
return 1;
}
# endif
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
int TerminalSocket (int FunctionCode, int *ReturnSocket)
{
int status;
$DESCRIPTOR (TerminalDeviceDesc, "SYS$COMMAND");
/*
** Process the requested function code
*/
switch (FunctionCode) {
case TERM_SOCK_CREATE:
/*
** Create a socket pair
*/
status = CreateSocketPair (AF_INET, SOCK_STREAM, 0, TerminalSocketPair);
if (status == -1) {
LogMessage ("TerminalSocket: CreateSocketPair () - %08X", status);
if (TerminalSocketPair[0])
close (TerminalSocketPair[0]);
if (TerminalSocketPair[1])
close (TerminalSocketPair[1]);
return TERM_SOCK_FAILURE;
}
/*
** Assign a channel to the terminal device
*/
status = sys$assign (&TerminalDeviceDesc,
&TerminalDeviceChan,
0, 0, 0);
if (! (status & 1)) {
LogMessage ("TerminalSocket: SYS$ASSIGN () - %08X", status);
close (TerminalSocketPair[0]);
close (TerminalSocketPair[1]);
return TERM_SOCK_FAILURE;
}
/*
** Queue an async IO to the terminal device
*/
status = sys$qio (EFN$C_ENF,
TerminalDeviceChan,
IO$_READVBLK,
&TerminalDeviceIosb,
TerminalDeviceAst,
0,
TerminalDeviceBuff,
sizeof(TerminalDeviceBuff) - 2,
0, 0, 0, 0);
if (! (status & 1)) {
LogMessage ("TerminalSocket: SYS$QIO () - %08X", status);
close (TerminalSocketPair[0]);
close (TerminalSocketPair[1]);
return TERM_SOCK_FAILURE;
}
/*
** Return the input side of the socket pair
*/
*ReturnSocket = TerminalSocketPair[1];
break;
case TERM_SOCK_DELETE:
/*
** Cancel any pending IO on the terminal channel
*/
status = sys$cancel (TerminalDeviceChan);
if (! (status & 1)) {
LogMessage ("TerminalSocket: SYS$CANCEL () - %08X", status);
close (TerminalSocketPair[0]);
close (TerminalSocketPair[1]);
return TERM_SOCK_FAILURE;
}
/*
** Deassign the terminal channel
*/
status = sys$dassgn (TerminalDeviceChan);
if (! (status & 1)) {
LogMessage ("TerminalSocket: SYS$DASSGN () - %08X", status);
close (TerminalSocketPair[0]);
close (TerminalSocketPair[1]);
return TERM_SOCK_FAILURE;
}
/*
** Close the terminal socket pair
*/
close (TerminalSocketPair[0]);
close (TerminalSocketPair[1]);
/*
** Return the initialized socket
*/
*ReturnSocket = 0;
break;
default:
/*
** Invalid function code
*/
LogMessage ("TerminalSocket: Invalid Function Code - %d", FunctionCode);
return TERM_SOCK_FAILURE;
break;
}
/*
** Return success
*/
return TERM_SOCK_SUCCESS;
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static int CreateSocketPair (int SocketFamily,
int SocketType,
int SocketProtocol,
int *SocketPair)
{
struct dsc$descriptor AscTimeDesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
static const char* LocalHostAddr = {"127.0.0.1"};
unsigned short TcpAcceptChan = 0,
TcpDeviceChan = 0;
unsigned long BinTimeBuff[2];
struct sockaddr_in sin;
char AscTimeBuff[32];
short LocalHostPort;
int status;
unsigned int slen;
# ifdef __alpha
struct _iosb iosb;
# else
IOSB iosb;
# endif
int SockDesc1 = 0,
SockDesc2 = 0;
SPTB sptb;
$DESCRIPTOR (TcpDeviceDesc, "TCPIP$DEVICE");
/*
** Create a socket
*/
SockDesc1 = socket (SocketFamily, SocketType, 0);
if (SockDesc1 < 0) {
LogMessage ("CreateSocketPair: socket () - %d", errno);
return -1;
}
/*
** Initialize the socket information
*/
slen = sizeof(sin);
memset ((char *) &sin, 0, slen);
sin.sin_family = SocketFamily;
sin.sin_addr.s_addr = inet_addr (LocalHostAddr);
sin.sin_port = 0;
/*
** Bind the socket to the local IP
*/
status = bind (SockDesc1, (struct sockaddr *) &sin, slen);
if (status < 0) {
LogMessage ("CreateSocketPair: bind () - %d", errno);
close (SockDesc1);
return -1;
}
/*
** Get the socket name so we can save the port number
*/
status = getsockname (SockDesc1, (struct sockaddr *) &sin, &slen);
if (status < 0) {
LogMessage ("CreateSocketPair: getsockname () - %d", errno);
close (SockDesc1);
return -1;
} else
LocalHostPort = sin.sin_port;
/*
** Setup a listen for the socket
*/
listen (SockDesc1, 5);
/*
** Get the binary (64-bit) time of the specified timeout value
*/
- sprintf (AscTimeBuff, "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE);
+ BIO_snprintf(AscTimeBuff, sizeof(AscTimeBuff), "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE);
AscTimeDesc.dsc$w_length = strlen (AscTimeBuff);
AscTimeDesc.dsc$a_pointer = AscTimeBuff;
status = sys$bintim (&AscTimeDesc, BinTimeBuff);
if (! (status & 1)) {
LogMessage ("CreateSocketPair: SYS$BINTIM () - %08X", status);
close (SockDesc1);
return -1;
}
/*
** Assign another channel to the TCP/IP device for the accept.
** This is the channel that ends up being connected to.
*/
status = sys$assign (&TcpDeviceDesc, &TcpDeviceChan, 0, 0, 0);
if (! (status & 1)) {
LogMessage ("CreateSocketPair: SYS$ASSIGN () - %08X", status);
close (SockDesc1);
return -1;
}
/*
** Get the channel of the first socket for the accept
*/
TcpAcceptChan = decc$get_sdc (SockDesc1);
/*
** Perform the accept using $QIO so we can do this asynchronously
*/
status = sys$qio (EFN$C_ENF,
TcpAcceptChan,
IO$_ACCESS | IO$M_ACCEPT,
&iosb,
0, 0, 0, 0, 0,
&TcpDeviceChan,
0, 0);
if (! (status & 1)) {
LogMessage ("CreateSocketPair: SYS$QIO () - %08X", status);
close (SockDesc1);
sys$dassgn (TcpDeviceChan);
return -1;
}
/*
** Create the second socket to do the connect
*/
SockDesc2 = socket (SocketFamily, SocketType, 0);
if (SockDesc2 < 0) {
LogMessage ("CreateSocketPair: socket () - %d", errno);
sys$cancel (TcpAcceptChan);
close (SockDesc1);
sys$dassgn (TcpDeviceChan);
return (-1) ;
}
/*
** Setup the Socket Pair Timeout Block
*/
sptb.SockChan1 = TcpAcceptChan;
sptb.SockChan2 = decc$get_sdc (SockDesc2);
/*
** Before we block on the connect, set a timer that can cancel I/O on our
** two sockets if it never connects.
*/
status = sys$setimr (EFN$C_ENF,
BinTimeBuff,
SocketPairTimeoutAst,
&sptb,
0);
if (! (status & 1)) {
LogMessage ("CreateSocketPair: SYS$SETIMR () - %08X", status);
sys$cancel (TcpAcceptChan);
close (SockDesc1);
close (SockDesc2);
sys$dassgn (TcpDeviceChan);
return -1;
}
/*
** Now issue the connect
*/
memset ((char *) &sin, 0, sizeof(sin)) ;
sin.sin_family = SocketFamily;
sin.sin_addr.s_addr = inet_addr (LocalHostAddr) ;
sin.sin_port = LocalHostPort ;
status = connect (SockDesc2, (struct sockaddr *) &sin, sizeof(sin));
if (status < 0 ) {
LogMessage ("CreateSocketPair: connect () - %d", errno);
sys$cantim (&sptb, 0);
sys$cancel (TcpAcceptChan);
close (SockDesc1);
close (SockDesc2);
sys$dassgn (TcpDeviceChan);
return -1;
}
/*
** Wait for the asynch $QIO to finish. Note that if the I/O was aborted
** (SS$_ABORT), then we probably canceled it from the AST routine - so log
** a timeout.
*/
status = sys$synch (EFN$C_ENF, &iosb);
if (! (iosb.iosb$w_status & 1)) {
if (iosb.iosb$w_status == SS$_ABORT)
LogMessage ("CreateSocketPair: SYS$QIO(iosb) timeout");
else {
LogMessage ("CreateSocketPair: SYS$QIO(iosb) - %d",
iosb.iosb$w_status);
sys$cantim (&sptb, 0);
}
close (SockDesc1);
close (SockDesc2);
sys$dassgn (TcpDeviceChan);
return -1;
}
/*
** Here we're successfully connected, so cancel the timer, convert the
** I/O channel to a socket fd, close the listener socket and return the
** connected pair.
*/
sys$cantim (&sptb, 0);
close (SockDesc1) ;
SocketPair[0] = SockDesc2 ;
SocketPair[1] = socket_fd (TcpDeviceChan);
return (0) ;
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static void SocketPairTimeoutAst (int astparm)
{
SPTB *sptb = (SPTB *) astparm;
sys$cancel (sptb->SockChan2); /* Cancel the connect() */
sys$cancel (sptb->SockChan1); /* Cancel the accept() */
return;
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static int TerminalDeviceAst (int astparm)
{
int status;
/*
** Terminate the terminal buffer
*/
TerminalDeviceBuff[TerminalDeviceIosb.iosb$w_bcnt] = '\0';
strcat (TerminalDeviceBuff, "\n");
/*
** Send the data read from the terminal device through the socket pair
*/
send (TerminalSocketPair[0], TerminalDeviceBuff,
TerminalDeviceIosb.iosb$w_bcnt + 1, 0);
/*
** Queue another async IO to the terminal device
*/
status = sys$qio (EFN$C_ENF,
TerminalDeviceChan,
IO$_READVBLK,
&TerminalDeviceIosb,
TerminalDeviceAst,
0,
TerminalDeviceBuff,
sizeof(TerminalDeviceBuff) - 1,
0, 0, 0, 0);
/*
** Return status
*/
return status;
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static void LogMessage (char *msg, ...)
{
char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
static unsigned int pid = 0;
va_list args;
time_t CurTime;
struct tm *LocTime;
char MsgBuff[256];
/*
** Get the process pid
*/
if (pid == 0)
pid = getpid ();
/*
** Convert the current time into local time
*/
CurTime = time (NULL);
LocTime = localtime (&CurTime);
/*
** Format the message buffer
*/
- sprintf (MsgBuff, "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n",
- LocTime->tm_mday, Month[LocTime->tm_mon],
- (LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min,
- LocTime->tm_sec, pid, msg);
+ BIO_snprintf(MsgBuff, sizeof(MsgBuff), "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n",
+ LocTime->tm_mday, Month[LocTime->tm_mon],
+ (LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min,
+ LocTime->tm_sec, pid, msg);
/*
** Get any variable arguments and add them to the print of the message
** buffer
*/
va_start (args, msg);
vfprintf (stderr, MsgBuff, args);
va_end (args);
/*
** Flush standard error output
*/
fsync (fileno (stderr));
return;
}
#endif
diff --git a/crypto/openssl/apps/passwd.c b/crypto/openssl/apps/passwd.c
index 64b2e76c147a..31d8bdd87cb6 100644
--- a/crypto/openssl/apps/passwd.c
+++ b/crypto/openssl/apps/passwd.c
@@ -1,847 +1,848 @@
/*
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 "apps.h"
#include "progs.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0)
# include <openssl/des.h>
#endif
#include <openssl/md5.h>
#include <openssl/sha.h>
static const unsigned char cov_2char[64] = {
/* from crypto/des/fcrypt.c */
0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
};
static const char ascii_dollar[] = { 0x24, 0x00 };
typedef enum {
passwd_unset = 0,
passwd_md5,
passwd_apr1,
passwd_sha256,
passwd_sha512,
passwd_aixmd5
} passwd_modes;
static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
char *passwd, BIO *out, int quiet, int table,
int reverse, size_t pw_maxlen, passwd_modes mode);
typedef enum OPTION_choice {
OPT_COMMON,
OPT_IN,
OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1,
OPT_1, OPT_5, OPT_6, OPT_AIXMD5, OPT_SALT, OPT_STDIN,
OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS passwd_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [password]\n"},
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Read passwords from file"},
{"noverify", OPT_NOVERIFY, '-',
"Never verify when reading password from terminal"},
{"stdin", OPT_STDIN, '-', "Read passwords from stdin"},
OPT_SECTION("Output"),
{"quiet", OPT_QUIET, '-', "No warnings"},
{"table", OPT_TABLE, '-', "Format output as table"},
{"reverse", OPT_REVERSE, '-', "Switch table columns"},
OPT_SECTION("Cryptographic"),
{"salt", OPT_SALT, 's', "Use provided salt"},
{"6", OPT_6, '-', "SHA512-based password algorithm"},
{"5", OPT_5, '-', "SHA256-based password algorithm"},
{"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"},
{"1", OPT_1, '-', "MD5-based password algorithm"},
{"aixmd5", OPT_AIXMD5, '-', "AIX MD5-based password algorithm"},
OPT_R_OPTIONS,
OPT_PROV_OPTIONS,
OPT_PARAMETERS(),
{"password", 0, 0, "Password text to digest (optional)"},
{NULL}
};
int passwd_main(int argc, char **argv)
{
BIO *in = NULL;
char *infile = NULL, *salt = NULL, *passwd = NULL, **passwds = NULL;
char *salt_malloc = NULL, *passwd_malloc = NULL, *prog;
OPTION_CHOICE o;
int in_stdin = 0, pw_source_defined = 0;
#ifndef OPENSSL_NO_UI_CONSOLE
int in_noverify = 0;
#endif
int passed_salt = 0, quiet = 0, table = 0, reverse = 0;
int ret = 1;
passwd_modes mode = passwd_unset;
size_t passwd_malloc_size = 0;
size_t pw_maxlen = 256; /* arbitrary limit, should be enough for most
* passwords */
prog = opt_init(argc, argv, passwd_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(passwd_options);
ret = 0;
goto end;
case OPT_IN:
if (pw_source_defined)
goto opthelp;
infile = opt_arg();
pw_source_defined = 1;
break;
case OPT_NOVERIFY:
#ifndef OPENSSL_NO_UI_CONSOLE
in_noverify = 1;
#endif
break;
case OPT_QUIET:
quiet = 1;
break;
case OPT_TABLE:
table = 1;
break;
case OPT_REVERSE:
reverse = 1;
break;
case OPT_1:
if (mode != passwd_unset)
goto opthelp;
mode = passwd_md5;
break;
case OPT_5:
if (mode != passwd_unset)
goto opthelp;
mode = passwd_sha256;
break;
case OPT_6:
if (mode != passwd_unset)
goto opthelp;
mode = passwd_sha512;
break;
case OPT_APR1:
if (mode != passwd_unset)
goto opthelp;
mode = passwd_apr1;
break;
case OPT_AIXMD5:
if (mode != passwd_unset)
goto opthelp;
mode = passwd_aixmd5;
break;
case OPT_SALT:
passed_salt = 1;
salt = opt_arg();
break;
case OPT_STDIN:
if (pw_source_defined)
goto opthelp;
in_stdin = 1;
pw_source_defined = 1;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_PROV_CASES:
if (!opt_provider(o))
goto end;
break;
}
}
/* All remaining arguments are the password text */
argc = opt_num_rest();
argv = opt_rest();
if (*argv != NULL) {
if (pw_source_defined)
goto opthelp;
pw_source_defined = 1;
passwds = argv;
}
if (!app_RAND_load())
goto end;
if (mode == passwd_unset) {
/* use default */
mode = passwd_md5;
}
if (infile != NULL && in_stdin) {
BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog);
goto end;
}
if (infile != NULL || in_stdin) {
/*
* If in_stdin is true, we know that infile is NULL, and that
* bio_open_default() will give us back an alias for stdin.
*/
in = bio_open_default(infile, 'r', FORMAT_TEXT);
if (in == NULL)
goto end;
}
if (passwds == NULL) {
/* no passwords on the command line */
passwd_malloc_size = pw_maxlen + 2;
/* longer than necessary so that we can warn about truncation */
passwd = passwd_malloc =
app_malloc(passwd_malloc_size, "password buffer");
}
if ((in == NULL) && (passwds == NULL)) {
/*
* we use the following method to make sure what
* in the 'else' section is always compiled, to
* avoid rot of not-frequently-used code.
*/
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
/* build a null-terminated list */
static char *passwds_static[2] = { NULL, NULL };
passwds = passwds_static;
if (in == NULL) {
if (EVP_read_pw_string
(passwd_malloc, passwd_malloc_size, "Password: ",
!(passed_salt || in_noverify)) != 0)
goto end;
}
passwds[0] = passwd_malloc;
} else {
#endif
BIO_printf(bio_err, "password required\n");
goto end;
}
}
if (in == NULL) {
assert(passwds != NULL);
assert(*passwds != NULL);
do { /* loop over list of passwords */
passwd = *passwds++;
if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, bio_out,
quiet, table, reverse, pw_maxlen, mode))
goto end;
} while (*passwds != NULL);
} else {
/* in != NULL */
int done;
assert(passwd != NULL);
do {
int r = BIO_gets(in, passwd, pw_maxlen + 1);
if (r > 0) {
char *c = (strchr(passwd, '\n'));
if (c != NULL) {
*c = 0; /* truncate at newline */
} else {
/* ignore rest of line */
char trash[BUFSIZ];
do
r = BIO_gets(in, trash, sizeof(trash));
while ((r > 0) && (!strchr(trash, '\n')));
}
if (!do_passwd
(passed_salt, &salt, &salt_malloc, passwd, bio_out, quiet,
table, reverse, pw_maxlen, mode))
goto end;
}
done = (r <= 0);
} while (!done);
}
ret = 0;
end:
#if 0
ERR_print_errors(bio_err);
#endif
OPENSSL_free(salt_malloc);
OPENSSL_free(passwd_malloc);
BIO_free(in);
return ret;
}
/*
* MD5-based password algorithm (should probably be available as a library
* function; then the static buffer would not be acceptable). For magic
* string "1", this should be compatible to the MD5-based BSD password
* algorithm. For 'magic' string "apr1", this is compatible to the MD5-based
* Apache password algorithm. (Apparently, the Apache password algorithm is
* identical except that the 'magic' string was changed -- the laziest
* application of the NIH principle I've ever encountered.)
*/
static char *md5crypt(const char *passwd, const char *magic, const char *salt)
{
/* "$apr1$..salt..$.......md5hash..........\0" */
static char out_buf[6 + 9 + 24 + 2];
unsigned char buf[MD5_DIGEST_LENGTH];
char ascii_magic[5]; /* "apr1" plus '\0' */
char ascii_salt[9]; /* Max 8 chars plus '\0' */
char *ascii_passwd = NULL;
char *salt_out;
int n;
unsigned int i;
EVP_MD_CTX *md = NULL, *md2 = NULL;
size_t passwd_len, salt_len, magic_len;
passwd_len = strlen(passwd);
out_buf[0] = 0;
magic_len = strlen(magic);
OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic));
#ifdef CHARSET_EBCDIC
if ((magic[0] & 0x80) != 0) /* High bit is 1 in EBCDIC alnums */
ebcdic2ascii(ascii_magic, ascii_magic, magic_len);
#endif
/* The salt gets truncated to 8 chars */
OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt));
salt_len = strlen(ascii_salt);
#ifdef CHARSET_EBCDIC
ebcdic2ascii(ascii_salt, ascii_salt, salt_len);
#endif
#ifdef CHARSET_EBCDIC
ascii_passwd = OPENSSL_strdup(passwd);
if (ascii_passwd == NULL)
return NULL;
ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len);
passwd = ascii_passwd;
#endif
if (magic_len > 0) {
OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
if (magic_len > 4) /* assert it's "1" or "apr1" */
goto err;
OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf));
OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
}
OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf));
if (strlen(out_buf) > 6 + 8) /* assert "$apr1$..salt.." */
goto err;
salt_out = out_buf;
if (magic_len > 0)
salt_out += 2 + magic_len;
if (salt_len > 8)
goto err;
md = EVP_MD_CTX_new();
if (md == NULL
|| !EVP_DigestInit_ex(md, EVP_md5(), NULL)
|| !EVP_DigestUpdate(md, passwd, passwd_len))
goto err;
if (magic_len > 0)
if (!EVP_DigestUpdate(md, ascii_dollar, 1)
|| !EVP_DigestUpdate(md, ascii_magic, magic_len)
|| !EVP_DigestUpdate(md, ascii_dollar, 1))
goto err;
if (!EVP_DigestUpdate(md, ascii_salt, salt_len))
goto err;
md2 = EVP_MD_CTX_new();
if (md2 == NULL
|| !EVP_DigestInit_ex(md2, EVP_md5(), NULL)
|| !EVP_DigestUpdate(md2, passwd, passwd_len)
|| !EVP_DigestUpdate(md2, ascii_salt, salt_len)
|| !EVP_DigestUpdate(md2, passwd, passwd_len)
|| !EVP_DigestFinal_ex(md2, buf, NULL))
goto err;
for (i = passwd_len; i > sizeof(buf); i -= sizeof(buf)) {
if (!EVP_DigestUpdate(md, buf, sizeof(buf)))
goto err;
}
if (!EVP_DigestUpdate(md, buf, i))
goto err;
n = passwd_len;
while (n) {
if (!EVP_DigestUpdate(md, (n & 1) ? "\0" : passwd, 1))
goto err;
n >>= 1;
}
if (!EVP_DigestFinal_ex(md, buf, NULL))
goto err;
for (i = 0; i < 1000; i++) {
if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL))
goto err;
if (!EVP_DigestUpdate(md2,
(i & 1) ? (const unsigned char *)passwd : buf,
(i & 1) ? passwd_len : sizeof(buf)))
goto err;
if (i % 3) {
if (!EVP_DigestUpdate(md2, ascii_salt, salt_len))
goto err;
}
if (i % 7) {
if (!EVP_DigestUpdate(md2, passwd, passwd_len))
goto err;
}
if (!EVP_DigestUpdate(md2,
(i & 1) ? buf : (const unsigned char *)passwd,
(i & 1) ? sizeof(buf) : passwd_len))
goto err;
if (!EVP_DigestFinal_ex(md2, buf, NULL))
goto err;
}
EVP_MD_CTX_free(md2);
EVP_MD_CTX_free(md);
md2 = NULL;
md = NULL;
{
/* transform buf into output string */
unsigned char buf_perm[sizeof(buf)];
int dest, source;
char *output;
/* silly output permutation */
for (dest = 0, source = 0; dest < 14;
dest++, source = (source + 6) % 17)
buf_perm[dest] = buf[source];
buf_perm[14] = buf[5];
buf_perm[15] = buf[11];
# ifndef PEDANTIC /* Unfortunately, this generates a "no
* effect" warning */
assert(16 == sizeof(buf_perm));
# endif
output = salt_out + salt_len;
assert(output == out_buf + strlen(out_buf));
*output++ = ascii_dollar[0];
for (i = 0; i < 15; i += 3) {
*output++ = cov_2char[buf_perm[i + 2] & 0x3f];
*output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) |
(buf_perm[i + 2] >> 6)];
*output++ = cov_2char[((buf_perm[i] & 3) << 4) |
(buf_perm[i + 1] >> 4)];
*output++ = cov_2char[buf_perm[i] >> 2];
}
assert(i == 15);
*output++ = cov_2char[buf_perm[i] & 0x3f];
*output++ = cov_2char[buf_perm[i] >> 6];
*output = 0;
assert(strlen(out_buf) < sizeof(out_buf));
#ifdef CHARSET_EBCDIC
ascii2ebcdic(out_buf, out_buf, strlen(out_buf));
#endif
}
return out_buf;
err:
OPENSSL_free(ascii_passwd);
EVP_MD_CTX_free(md2);
EVP_MD_CTX_free(md);
return NULL;
}
/*
* SHA based password algorithm, describe by Ulrich Drepper here:
* https://www.akkadia.org/drepper/SHA-crypt.txt
* (note that it's in the public domain)
*/
static char *shacrypt(const char *passwd, const char *magic, const char *salt)
{
/* Prefix for optional rounds specification. */
static const char rounds_prefix[] = "rounds=";
/* Maximum salt string length. */
# define SALT_LEN_MAX 16
/* Default number of rounds if not explicitly specified. */
# define ROUNDS_DEFAULT 5000
/* Minimum number of rounds. */
# define ROUNDS_MIN 1000
/* Maximum number of rounds. */
# define ROUNDS_MAX 999999999
/* "$6$rounds=<N>$......salt......$...shahash(up to 86 chars)...\0" */
static char out_buf[3 + 17 + 17 + 86 + 1];
unsigned char buf[SHA512_DIGEST_LENGTH];
unsigned char temp_buf[SHA512_DIGEST_LENGTH];
size_t buf_size = 0;
char ascii_magic[2];
char ascii_salt[17]; /* Max 16 chars plus '\0' */
char *ascii_passwd = NULL;
size_t n;
EVP_MD_CTX *md = NULL, *md2 = NULL;
const EVP_MD *sha = NULL;
size_t passwd_len, salt_len, magic_len;
unsigned int rounds = ROUNDS_DEFAULT; /* Default */
char rounds_custom = 0;
char *p_bytes = NULL;
char *s_bytes = NULL;
char *cp = NULL;
passwd_len = strlen(passwd);
magic_len = strlen(magic);
/* assert it's "5" or "6" */
if (magic_len != 1)
return NULL;
switch (magic[0]) {
case '5':
sha = EVP_sha256();
buf_size = 32;
break;
case '6':
sha = EVP_sha512();
buf_size = 64;
break;
default:
return NULL;
}
if (strncmp(salt, rounds_prefix, sizeof(rounds_prefix) - 1) == 0) {
const char *num = salt + sizeof(rounds_prefix) - 1;
char *endp;
unsigned long int srounds = strtoul (num, &endp, 10);
if (*endp == '$') {
salt = endp + 1;
if (srounds > ROUNDS_MAX)
rounds = ROUNDS_MAX;
else if (srounds < ROUNDS_MIN)
rounds = ROUNDS_MIN;
else
rounds = (unsigned int)srounds;
rounds_custom = 1;
} else {
return NULL;
}
}
OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic));
#ifdef CHARSET_EBCDIC
if ((magic[0] & 0x80) != 0) /* High bit is 1 in EBCDIC alnums */
ebcdic2ascii(ascii_magic, ascii_magic, magic_len);
#endif
/* The salt gets truncated to 16 chars */
OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt));
salt_len = strlen(ascii_salt);
#ifdef CHARSET_EBCDIC
ebcdic2ascii(ascii_salt, ascii_salt, salt_len);
#endif
#ifdef CHARSET_EBCDIC
ascii_passwd = OPENSSL_strdup(passwd);
if (ascii_passwd == NULL)
return NULL;
ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len);
passwd = ascii_passwd;
#endif
out_buf[0] = 0;
OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf));
OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
if (rounds_custom) {
char tmp_buf[80]; /* "rounds=999999999" */
- sprintf(tmp_buf, "rounds=%u", rounds);
+
+ BIO_snprintf(tmp_buf, sizeof(tmp_buf), "rounds=%u", rounds);
#ifdef CHARSET_EBCDIC
/* In case we're really on a ASCII based platform and just pretend */
if (tmp_buf[0] != 0x72) /* ASCII 'r' */
ebcdic2ascii(tmp_buf, tmp_buf, strlen(tmp_buf));
#endif
OPENSSL_strlcat(out_buf, tmp_buf, sizeof(out_buf));
OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
}
OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf));
/* assert "$5$rounds=999999999$......salt......" */
if (strlen(out_buf) > 3 + 17 * rounds_custom + salt_len )
goto err;
md = EVP_MD_CTX_new();
if (md == NULL
|| !EVP_DigestInit_ex(md, sha, NULL)
|| !EVP_DigestUpdate(md, passwd, passwd_len)
|| !EVP_DigestUpdate(md, ascii_salt, salt_len))
goto err;
md2 = EVP_MD_CTX_new();
if (md2 == NULL
|| !EVP_DigestInit_ex(md2, sha, NULL)
|| !EVP_DigestUpdate(md2, passwd, passwd_len)
|| !EVP_DigestUpdate(md2, ascii_salt, salt_len)
|| !EVP_DigestUpdate(md2, passwd, passwd_len)
|| !EVP_DigestFinal_ex(md2, buf, NULL))
goto err;
for (n = passwd_len; n > buf_size; n -= buf_size) {
if (!EVP_DigestUpdate(md, buf, buf_size))
goto err;
}
if (!EVP_DigestUpdate(md, buf, n))
goto err;
n = passwd_len;
while (n) {
if (!EVP_DigestUpdate(md,
(n & 1) ? buf : (const unsigned char *)passwd,
(n & 1) ? buf_size : passwd_len))
goto err;
n >>= 1;
}
if (!EVP_DigestFinal_ex(md, buf, NULL))
goto err;
/* P sequence */
if (!EVP_DigestInit_ex(md2, sha, NULL))
goto err;
for (n = passwd_len; n > 0; n--)
if (!EVP_DigestUpdate(md2, passwd, passwd_len))
goto err;
if (!EVP_DigestFinal_ex(md2, temp_buf, NULL))
goto err;
if ((p_bytes = OPENSSL_zalloc(passwd_len)) == NULL)
goto err;
for (cp = p_bytes, n = passwd_len; n > buf_size; n -= buf_size, cp += buf_size)
memcpy(cp, temp_buf, buf_size);
memcpy(cp, temp_buf, n);
/* S sequence */
if (!EVP_DigestInit_ex(md2, sha, NULL))
goto err;
for (n = 16 + buf[0]; n > 0; n--)
if (!EVP_DigestUpdate(md2, ascii_salt, salt_len))
goto err;
if (!EVP_DigestFinal_ex(md2, temp_buf, NULL))
goto err;
if ((s_bytes = OPENSSL_zalloc(salt_len)) == NULL)
goto err;
for (cp = s_bytes, n = salt_len; n > buf_size; n -= buf_size, cp += buf_size)
memcpy(cp, temp_buf, buf_size);
memcpy(cp, temp_buf, n);
for (n = 0; n < rounds; n++) {
if (!EVP_DigestInit_ex(md2, sha, NULL))
goto err;
if (!EVP_DigestUpdate(md2,
(n & 1) ? (const unsigned char *)p_bytes : buf,
(n & 1) ? passwd_len : buf_size))
goto err;
if (n % 3) {
if (!EVP_DigestUpdate(md2, s_bytes, salt_len))
goto err;
}
if (n % 7) {
if (!EVP_DigestUpdate(md2, p_bytes, passwd_len))
goto err;
}
if (!EVP_DigestUpdate(md2,
(n & 1) ? buf : (const unsigned char *)p_bytes,
(n & 1) ? buf_size : passwd_len))
goto err;
if (!EVP_DigestFinal_ex(md2, buf, NULL))
goto err;
}
EVP_MD_CTX_free(md2);
EVP_MD_CTX_free(md);
md2 = NULL;
md = NULL;
OPENSSL_free(p_bytes);
OPENSSL_free(s_bytes);
p_bytes = NULL;
s_bytes = NULL;
cp = out_buf + strlen(out_buf);
*cp++ = ascii_dollar[0];
# define b64_from_24bit(B2, B1, B0, N) \
do { \
unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
int i = (N); \
while (i-- > 0) \
{ \
*cp++ = cov_2char[w & 0x3f]; \
w >>= 6; \
} \
} while (0)
switch (magic[0]) {
case '5':
b64_from_24bit (buf[0], buf[10], buf[20], 4);
b64_from_24bit (buf[21], buf[1], buf[11], 4);
b64_from_24bit (buf[12], buf[22], buf[2], 4);
b64_from_24bit (buf[3], buf[13], buf[23], 4);
b64_from_24bit (buf[24], buf[4], buf[14], 4);
b64_from_24bit (buf[15], buf[25], buf[5], 4);
b64_from_24bit (buf[6], buf[16], buf[26], 4);
b64_from_24bit (buf[27], buf[7], buf[17], 4);
b64_from_24bit (buf[18], buf[28], buf[8], 4);
b64_from_24bit (buf[9], buf[19], buf[29], 4);
b64_from_24bit (0, buf[31], buf[30], 3);
break;
case '6':
b64_from_24bit (buf[0], buf[21], buf[42], 4);
b64_from_24bit (buf[22], buf[43], buf[1], 4);
b64_from_24bit (buf[44], buf[2], buf[23], 4);
b64_from_24bit (buf[3], buf[24], buf[45], 4);
b64_from_24bit (buf[25], buf[46], buf[4], 4);
b64_from_24bit (buf[47], buf[5], buf[26], 4);
b64_from_24bit (buf[6], buf[27], buf[48], 4);
b64_from_24bit (buf[28], buf[49], buf[7], 4);
b64_from_24bit (buf[50], buf[8], buf[29], 4);
b64_from_24bit (buf[9], buf[30], buf[51], 4);
b64_from_24bit (buf[31], buf[52], buf[10], 4);
b64_from_24bit (buf[53], buf[11], buf[32], 4);
b64_from_24bit (buf[12], buf[33], buf[54], 4);
b64_from_24bit (buf[34], buf[55], buf[13], 4);
b64_from_24bit (buf[56], buf[14], buf[35], 4);
b64_from_24bit (buf[15], buf[36], buf[57], 4);
b64_from_24bit (buf[37], buf[58], buf[16], 4);
b64_from_24bit (buf[59], buf[17], buf[38], 4);
b64_from_24bit (buf[18], buf[39], buf[60], 4);
b64_from_24bit (buf[40], buf[61], buf[19], 4);
b64_from_24bit (buf[62], buf[20], buf[41], 4);
b64_from_24bit (0, 0, buf[63], 2);
break;
default:
goto err;
}
*cp = '\0';
#ifdef CHARSET_EBCDIC
ascii2ebcdic(out_buf, out_buf, strlen(out_buf));
#endif
return out_buf;
err:
EVP_MD_CTX_free(md2);
EVP_MD_CTX_free(md);
OPENSSL_free(p_bytes);
OPENSSL_free(s_bytes);
OPENSSL_free(ascii_passwd);
return NULL;
}
static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
char *passwd, BIO *out, int quiet, int table,
int reverse, size_t pw_maxlen, passwd_modes mode)
{
char *hash = NULL;
assert(salt_p != NULL);
assert(salt_malloc_p != NULL);
/* first make sure we have a salt */
if (!passed_salt) {
size_t saltlen = 0;
size_t i;
if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5)
saltlen = 8;
if (mode == passwd_sha256 || mode == passwd_sha512)
saltlen = 16;
assert(saltlen != 0);
if (*salt_malloc_p == NULL)
*salt_p = *salt_malloc_p = app_malloc(saltlen + 1, "salt buffer");
if (RAND_bytes((unsigned char *)*salt_p, saltlen) <= 0)
goto end;
for (i = 0; i < saltlen; i++)
(*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */
(*salt_p)[i] = 0;
# ifdef CHARSET_EBCDIC
/* The password encryption function will convert back to ASCII */
ascii2ebcdic(*salt_p, *salt_p, saltlen);
# endif
}
assert(*salt_p != NULL);
/* truncate password if necessary */
if ((strlen(passwd) > pw_maxlen)) {
if (!quiet)
/*
* XXX: really we should know how to print a size_t, not cast it
*/
BIO_printf(bio_err,
"Warning: truncating password to %u characters\n",
(unsigned)pw_maxlen);
passwd[pw_maxlen] = 0;
}
assert(strlen(passwd) <= pw_maxlen);
/* now compute password hash */
if (mode == passwd_md5 || mode == passwd_apr1)
hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p);
if (mode == passwd_aixmd5)
hash = md5crypt(passwd, "", *salt_p);
if (mode == passwd_sha256 || mode == passwd_sha512)
hash = shacrypt(passwd, (mode == passwd_sha256 ? "5" : "6"), *salt_p);
assert(hash != NULL);
if (table && !reverse)
BIO_printf(out, "%s\t%s\n", passwd, hash);
else if (table && reverse)
BIO_printf(out, "%s\t%s\n", hash, passwd);
else
BIO_printf(out, "%s\n", hash);
return 1;
end:
return 0;
}
diff --git a/crypto/openssl/apps/pkcs12.c b/crypto/openssl/apps/pkcs12.c
index ab78903ee9cd..5146699f1672 100644
--- a/crypto/openssl/apps/pkcs12.c
+++ b/crypto/openssl/apps/pkcs12.c
@@ -1,1237 +1,1238 @@
/*
- * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "apps.h"
#include "progs.h"
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/provider.h>
#include <openssl/kdf.h>
#define NOKEYS 0x1
#define NOCERTS 0x2
#define INFO 0x4
#define CLCERTS 0x8
#define CACERTS 0x10
#define PASSWD_BUF_SIZE 2048
#define WARN_EXPORT(opt) \
BIO_printf(bio_err, "Warning: -%s option ignored with -export\n", opt);
#define WARN_NO_EXPORT(opt) \
BIO_printf(bio_err, "Warning: -%s option ignored without -export\n", opt);
static int get_cert_chain(X509 *cert, X509_STORE *store,
STACK_OF(X509) *untrusted_certs,
STACK_OF(X509) **chain);
int dump_certs_keys_p12(BIO *out, const PKCS12 *p12,
const char *pass, int passlen, int options,
char *pempass, const EVP_CIPHER *enc);
int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
const char *pass, int passlen, int options,
char *pempass, const EVP_CIPHER *enc);
int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bags,
const char *pass, int passlen,
int options, char *pempass, const EVP_CIPHER *enc);
void print_attribute(BIO *out, const ASN1_TYPE *av);
int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
const char *name);
void hex_prin(BIO *out, unsigned char *buf, int len);
static int alg_print(const X509_ALGOR *alg);
int cert_load(BIO *in, STACK_OF(X509) *sk);
static int set_pbe(int *ppbe, const char *str);
typedef enum OPTION_choice {
OPT_COMMON,
OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS,
OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
#ifndef OPENSSL_NO_DES
OPT_DESCERT,
#endif
OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_NOENC, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
OPT_INKEY, OPT_CERTFILE, OPT_UNTRUSTED, OPT_PASSCERTS,
OPT_NAME, OPT_CSP, OPT_CANAME,
OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE,
OPT_R_ENUM, OPT_PROV_ENUM,
#ifndef OPENSSL_NO_DES
OPT_LEGACY_ALG
#endif
} OPTION_CHOICE;
const OPTIONS pkcs12_options[] = {
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"in", OPT_IN, '<', "Input file"},
{"out", OPT_OUT, '>', "Output file"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
{"password", OPT_PASSWORD, 's', "Set PKCS#12 import/export password source"},
{"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"},
{"nokeys", OPT_NOKEYS, '-', "Don't output private keys"},
{"nocerts", OPT_NOCERTS, '-', "Don't output certificates"},
{"noout", OPT_NOOUT, '-', "Don't output anything, just verify PKCS#12 input"},
#ifndef OPENSSL_NO_DES
{"legacy", OPT_LEGACY_ALG, '-',
# ifdef OPENSSL_NO_RC2
"Use legacy encryption algorithm 3DES_CBC for keys and certs"
# else
"Use legacy encryption: 3DES_CBC for keys, RC2_CBC for certs"
# endif
},
#endif
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
OPT_PROV_OPTIONS,
OPT_R_OPTIONS,
OPT_SECTION("PKCS#12 import (parsing PKCS#12)"),
{"info", OPT_INFO, '-', "Print info about PKCS#12 structure"},
{"nomacver", OPT_NOMACVER, '-', "Don't verify integrity MAC"},
{"clcerts", OPT_CLCERTS, '-', "Only output client certificates"},
{"cacerts", OPT_CACERTS, '-', "Only output CA certificates"},
{"", OPT_CIPHER, '-', "Any supported cipher for output encryption"},
{"noenc", OPT_NOENC, '-', "Don't encrypt private keys"},
{"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"},
OPT_SECTION("PKCS#12 output (export)"),
{"export", OPT_EXPORT, '-', "Create PKCS12 file"},
{"inkey", OPT_INKEY, 's', "Private key, else read from -in input file"},
{"certfile", OPT_CERTFILE, '<', "Extra certificates for PKCS12 output"},
{"passcerts", OPT_PASSCERTS, 's', "Certificate file pass phrase source"},
{"chain", OPT_CHAIN, '-', "Build and add certificate chain for EE cert,"},
{OPT_MORE_STR, 0, 0,
"which is the 1st cert from -in matching the private key (if given)"},
{"untrusted", OPT_UNTRUSTED, '<', "Untrusted certificates for chain building"},
{"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"},
{"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"},
{"CAstore", OPT_CASTORE, ':', "URI to store 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"},
{"no-CAstore", OPT_NOCASTORE, '-',
"Do not load certificates from the default certificates store"},
{"name", OPT_NAME, 's', "Use name as friendly name"},
{"caname", OPT_CANAME, 's',
"Use name as CA friendly name (can be repeated)"},
{"CSP", OPT_CSP, 's', "Microsoft CSP name"},
{"LMK", OPT_LMK, '-',
"Add local machine keyset attribute to private key"},
{"keyex", OPT_KEYEX, '-', "Set key type to MS key exchange"},
{"keysig", OPT_KEYSIG, '-', "Set key type to MS key signature"},
{"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default AES-256 CBC)"},
{"certpbe", OPT_CERTPBE, 's',
"Certificate PBE algorithm (default PBES2 with PBKDF2 and AES-256 CBC)"},
#ifndef OPENSSL_NO_DES
{"descert", OPT_DESCERT, '-',
"Encrypt output with 3DES (default PBES2 with PBKDF2 and AES-256 CBC)"},
#endif
{"macalg", OPT_MACALG, 's',
"Digest algorithm to use in MAC (default SHA256)"},
{"iter", OPT_ITER, 'p', "Specify the iteration count for encryption and MAC"},
{"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
{"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration)"},
{"maciter", OPT_MACITER, '-', "Unused, kept for backwards compatibility"},
{"nomac", OPT_NOMAC, '-', "Don't generate MAC"},
{NULL}
};
int pkcs12_main(int argc, char **argv)
{
char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
char *untrusted = NULL, *ciphername = NULL, *enc_flag = NULL;
char *passcertsarg = NULL, *passcerts = NULL;
char *name = NULL, *csp_name = NULL;
char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = "";
int export_pkcs12 = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
#ifndef OPENSSL_NO_DES
int use_legacy = 0;
#endif
/* use library defaults for the iter, maciter, cert, and key PBE */
int iter = 0, maciter = 0;
int cert_pbe = NID_undef;
int key_pbe = NID_undef;
int ret = 1, macver = 1, add_lmk = 0, private = 0;
int noprompt = 0;
char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
char *passin = NULL, *passout = NULL, *macalg = NULL;
char *cpass = NULL, *mpass = NULL, *badpass = NULL;
const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL, *prog;
int noCApath = 0, noCAfile = 0, noCAstore = 0;
ENGINE *e = NULL;
BIO *in = NULL, *out = NULL;
PKCS12 *p12 = NULL;
STACK_OF(OPENSSL_STRING) *canames = NULL;
EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_aes_256_cbc();
EVP_CIPHER *enc = (EVP_CIPHER *)default_enc;
OPTION_CHOICE o;
prog = opt_init(argc, argv, pkcs12_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(pkcs12_options);
ret = 0;
goto end;
case OPT_NOKEYS:
options |= NOKEYS;
break;
case OPT_KEYEX:
keytype = KEY_EX;
break;
case OPT_KEYSIG:
keytype = KEY_SIG;
break;
case OPT_NOCERTS:
options |= NOCERTS;
break;
case OPT_CLCERTS:
options |= CLCERTS;
break;
case OPT_CACERTS:
options |= CACERTS;
break;
case OPT_NOOUT:
options |= (NOKEYS | NOCERTS);
break;
case OPT_INFO:
options |= INFO;
break;
case OPT_CHAIN:
chain = 1;
break;
case OPT_TWOPASS:
twopass = 1;
break;
case OPT_NOMACVER:
macver = 0;
break;
#ifndef OPENSSL_NO_DES
case OPT_DESCERT:
cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
break;
#endif
case OPT_EXPORT:
export_pkcs12 = 1;
break;
case OPT_NODES:
case OPT_NOENC:
/*
* |enc_flag| stores the name of the option used so it
* can be printed if an error message is output.
*/
enc_flag = opt_flag() + 1;
enc = NULL;
ciphername = NULL;
break;
case OPT_CIPHER:
ciphername = opt_unknown();
enc_flag = opt_unknown();
break;
case OPT_ITER:
maciter = iter = opt_int_arg();
break;
case OPT_NOITER:
iter = 1;
break;
case OPT_MACITER:
/* no-op */
break;
case OPT_NOMACITER:
maciter = 1;
break;
case OPT_NOMAC:
cert_pbe = -1;
maciter = -1;
break;
case OPT_MACALG:
macalg = opt_arg();
break;
case OPT_CERTPBE:
if (!set_pbe(&cert_pbe, opt_arg()))
goto opthelp;
break;
case OPT_KEYPBE:
if (!set_pbe(&key_pbe, opt_arg()))
goto opthelp;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_INKEY:
keyname = opt_arg();
break;
case OPT_CERTFILE:
certfile = opt_arg();
break;
case OPT_UNTRUSTED:
untrusted = opt_arg();
break;
case OPT_PASSCERTS:
passcertsarg = opt_arg();
break;
case OPT_NAME:
name = opt_arg();
break;
case OPT_LMK:
add_lmk = 1;
break;
case OPT_CSP:
csp_name = opt_arg();
break;
case OPT_CANAME:
if (canames == NULL
&& (canames = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(canames, opt_arg());
+ if (sk_OPENSSL_STRING_push(canames, opt_arg()) <= 0)
+ goto end;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_PASSOUT:
passoutarg = opt_arg();
break;
case OPT_PASSWORD:
passarg = opt_arg();
break;
case OPT_CAPATH:
CApath = opt_arg();
break;
case OPT_CASTORE:
CAstore = opt_arg();
break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_NOCASTORE:
noCAstore = 1;
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
#ifndef OPENSSL_NO_DES
case OPT_LEGACY_ALG:
use_legacy = 1;
break;
#endif
case OPT_PROV_CASES:
if (!opt_provider(o))
goto end;
break;
}
}
/* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
if (!app_RAND_load())
goto end;
if (ciphername != NULL) {
if (!opt_cipher_any(ciphername, &enc))
goto opthelp;
}
if (export_pkcs12) {
if ((options & INFO) != 0)
WARN_EXPORT("info");
if (macver == 0)
WARN_EXPORT("nomacver");
if ((options & CLCERTS) != 0)
WARN_EXPORT("clcerts");
if ((options & CACERTS) != 0)
WARN_EXPORT("cacerts");
if (enc != default_enc)
BIO_printf(bio_err,
"Warning: output encryption option -%s ignored with -export\n", enc_flag);
} else {
if (keyname != NULL)
WARN_NO_EXPORT("inkey");
if (certfile != NULL)
WARN_NO_EXPORT("certfile");
if (passcertsarg != NULL)
WARN_NO_EXPORT("passcerts");
if (chain)
WARN_NO_EXPORT("chain");
if (untrusted != NULL)
WARN_NO_EXPORT("untrusted");
if (CAfile != NULL)
WARN_NO_EXPORT("CAfile");
if (CApath != NULL)
WARN_NO_EXPORT("CApath");
if (CAstore != NULL)
WARN_NO_EXPORT("CAstore");
if (noCAfile)
WARN_NO_EXPORT("no-CAfile");
if (noCApath)
WARN_NO_EXPORT("no-CApath");
if (noCAstore)
WARN_NO_EXPORT("no-CAstore");
if (name != NULL)
WARN_NO_EXPORT("name");
if (canames != NULL)
WARN_NO_EXPORT("caname");
if (csp_name != NULL)
WARN_NO_EXPORT("CSP");
if (add_lmk)
WARN_NO_EXPORT("LMK");
if (keytype == KEY_EX)
WARN_NO_EXPORT("keyex");
if (keytype == KEY_SIG)
WARN_NO_EXPORT("keysig");
if (key_pbe != NID_undef)
WARN_NO_EXPORT("keypbe");
if (cert_pbe != NID_undef && cert_pbe != -1)
WARN_NO_EXPORT("certpbe and -descert");
if (macalg != NULL)
WARN_NO_EXPORT("macalg");
if (iter != 0)
WARN_NO_EXPORT("iter and -noiter");
if (maciter == 1)
WARN_NO_EXPORT("nomaciter");
if (cert_pbe == -1 && maciter == -1)
WARN_NO_EXPORT("nomac");
}
#ifndef OPENSSL_NO_DES
if (use_legacy) {
/* load the legacy provider if not loaded already*/
if (!OSSL_PROVIDER_available(app_get0_libctx(), "legacy")) {
if (!app_provider_load(app_get0_libctx(), "legacy"))
goto end;
/* load the default provider explicitly */
if (!app_provider_load(app_get0_libctx(), "default"))
goto end;
}
if (cert_pbe == NID_undef) {
/* Adapt default algorithm */
# ifndef OPENSSL_NO_RC2
cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
# else
cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
# endif
}
if (key_pbe == NID_undef)
key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
if (enc == default_enc)
enc = (EVP_CIPHER *)EVP_des_ede3_cbc();
if (macalg == NULL)
macalg = "sha1";
}
#endif
private = 1;
if (!app_passwd(passcertsarg, NULL, &passcerts, NULL)) {
BIO_printf(bio_err, "Error getting certificate file password\n");
goto end;
}
if (passarg != NULL) {
if (export_pkcs12)
passoutarg = passarg;
else
passinarg = passarg;
}
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
goto end;
}
if (cpass == NULL) {
if (export_pkcs12)
cpass = passout;
else
cpass = passin;
}
if (cpass != NULL) {
mpass = cpass;
noprompt = 1;
if (twopass) {
if (export_pkcs12)
BIO_printf(bio_err, "Option -twopass cannot be used with -passout or -password\n");
else
BIO_printf(bio_err, "Option -twopass cannot be used with -passin or -password\n");
goto end;
}
} else {
cpass = pass;
mpass = macpass;
}
if (twopass) {
/* To avoid bit rot */
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
if (EVP_read_pw_string(
macpass, sizeof(macpass), "Enter MAC Password:", export_pkcs12)) {
BIO_printf(bio_err, "Can't read Password\n");
goto end;
}
} else {
#endif
BIO_printf(bio_err, "Unsupported option -twopass\n");
goto end;
}
}
if (export_pkcs12) {
EVP_PKEY *key = NULL;
X509 *ee_cert = NULL, *x = NULL;
STACK_OF(X509) *certs = NULL;
STACK_OF(X509) *untrusted_certs = NULL;
EVP_MD *macmd = NULL;
unsigned char *catmp = NULL;
int i;
if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
BIO_printf(bio_err, "Nothing to export due to -noout or -nocerts and -nokeys\n");
goto export_end;
}
if ((options & NOCERTS) != 0) {
chain = 0;
BIO_printf(bio_err, "Warning: -chain option ignored with -nocerts\n");
}
if (!(options & NOKEYS)) {
key = load_key(keyname ? keyname : infile,
FORMAT_PEM, 1, passin, e,
keyname ?
"private key from -inkey file" :
"private key from -in file");
if (key == NULL)
goto export_end;
}
/* Load all certs in input file */
if (!(options & NOCERTS)) {
if (!load_certs(infile, 1, &certs, passin,
"certificates from -in file"))
goto export_end;
if (sk_X509_num(certs) < 1) {
BIO_printf(bio_err, "No certificate in -in file %s\n", infile);
goto export_end;
}
if (key != NULL) {
/* Look for matching private key */
for (i = 0; i < sk_X509_num(certs); i++) {
x = sk_X509_value(certs, i);
if (X509_check_private_key(x, key)) {
ee_cert = x;
/* Zero keyid and alias */
X509_keyid_set1(ee_cert, NULL, 0);
X509_alias_set1(ee_cert, NULL, 0);
/* Remove from list */
(void)sk_X509_delete(certs, i);
break;
}
}
if (ee_cert == NULL) {
BIO_printf(bio_err,
"No cert in -in file '%s' matches private key\n",
infile);
goto export_end;
}
}
}
/* Load any untrusted certificates for chain building */
if (untrusted != NULL) {
if (!load_certs(untrusted, 0, &untrusted_certs, passcerts,
"untrusted certificates"))
goto export_end;
}
/* If chaining get chain from end entity cert */
if (chain) {
int vret;
STACK_OF(X509) *chain2;
X509_STORE *store;
X509 *ee_cert_tmp = ee_cert;
/* Assume the first cert if we haven't got anything else */
if (ee_cert_tmp == NULL && certs != NULL)
ee_cert_tmp = sk_X509_value(certs, 0);
if (ee_cert_tmp == NULL) {
BIO_printf(bio_err,
"No end entity certificate to check with -chain\n");
goto export_end;
}
if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
CAstore, noCAstore))
== NULL)
goto export_end;
vret = get_cert_chain(ee_cert_tmp, store, untrusted_certs, &chain2);
X509_STORE_free(store);
if (vret == X509_V_OK) {
int add_certs;
/* Remove from chain2 the first (end entity) certificate */
X509_free(sk_X509_shift(chain2));
/* Add the remaining certs (except for duplicates) */
add_certs = X509_add_certs(certs, chain2, X509_ADD_FLAG_UP_REF
| X509_ADD_FLAG_NO_DUP);
sk_X509_pop_free(chain2, X509_free);
if (!add_certs)
goto export_end;
} else {
if (vret != X509_V_ERR_UNSPECIFIED)
BIO_printf(bio_err, "Error getting chain: %s\n",
X509_verify_cert_error_string(vret));
goto export_end;
}
}
/* Add any extra certificates asked for */
if (certfile != NULL) {
if (!load_certs(certfile, 0, &certs, passcerts,
"extra certificates from -certfile"))
goto export_end;
}
/* Add any CA names */
for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
}
if (csp_name != NULL && key != NULL)
EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
MBSTRING_ASC, (unsigned char *)csp_name,
-1);
if (add_lmk && key != NULL)
EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
if (!noprompt && !(enc == NULL && maciter == -1)) {
/* To avoid bit rot */
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
if (EVP_read_pw_string(pass, sizeof(pass),
"Enter Export Password:", 1)) {
BIO_printf(bio_err, "Can't read Password\n");
goto export_end;
}
} else {
#endif
BIO_printf(bio_err, "Password required\n");
goto export_end;
}
}
if (!twopass)
OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs,
key_pbe, cert_pbe, iter, -1, keytype,
app_get0_libctx(), app_get0_propq());
if (p12 == NULL) {
BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n",
outfile);
goto export_end;
}
if (macalg != NULL) {
if (!opt_md(macalg, &macmd))
goto opthelp;
}
if (maciter != -1)
if (!PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd)) {
BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n");
BIO_printf(bio_err, "Use -nomac if MAC not required and PKCS12KDF support not available.\n");
goto export_end;
}
assert(private);
out = bio_open_owner(outfile, FORMAT_PKCS12, private);
if (out == NULL)
goto end;
i2d_PKCS12_bio(out, p12);
ret = 0;
export_end:
EVP_PKEY_free(key);
EVP_MD_free(macmd);
sk_X509_pop_free(certs, X509_free);
sk_X509_pop_free(untrusted_certs, X509_free);
X509_free(ee_cert);
ERR_print_errors(bio_err);
goto end;
}
in = bio_open_default(infile, 'r', FORMAT_PKCS12);
if (in == NULL)
goto end;
p12 = PKCS12_init_ex(NID_pkcs7_data, app_get0_libctx(), app_get0_propq());
if (p12 == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if ((p12 = d2i_PKCS12_bio(in, &p12)) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (!noprompt) {
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
if (EVP_read_pw_string(pass, sizeof(pass), "Enter Import Password:",
0)) {
BIO_printf(bio_err, "Can't read Password\n");
goto end;
}
} else {
#endif
BIO_printf(bio_err, "Password required\n");
goto end;
}
}
if (!twopass)
OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
if ((options & INFO) && PKCS12_mac_present(p12)) {
const ASN1_INTEGER *tmaciter;
const X509_ALGOR *macalgid;
const ASN1_OBJECT *macobj;
const ASN1_OCTET_STRING *tmac;
const ASN1_OCTET_STRING *tsalt;
PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, p12);
/* current hash algorithms do not use parameters so extract just name,
in future alg_print() may be needed */
X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
BIO_puts(bio_err, "MAC: ");
i2a_ASN1_OBJECT(bio_err, macobj);
BIO_printf(bio_err, ", Iteration %ld\n",
tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n",
tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
}
if (macver) {
EVP_KDF *pkcs12kdf;
pkcs12kdf = EVP_KDF_fetch(app_get0_libctx(), "PKCS12KDF",
app_get0_propq());
if (pkcs12kdf == NULL) {
BIO_printf(bio_err, "Error verifying PKCS12 MAC; no PKCS12KDF support.\n");
BIO_printf(bio_err, "Use -nomacver if MAC verification is not required.\n");
goto end;
}
EVP_KDF_free(pkcs12kdf);
/* If we enter empty password try no password first */
if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
/* If mac and crypto pass the same set it to NULL too */
if (!twopass)
cpass = NULL;
} else if (!PKCS12_verify_mac(p12, mpass, -1)) {
/*
* May be UTF8 from previous version of OpenSSL:
* convert to a UTF8 form which will translate
* to the same Unicode password.
*/
unsigned char *utmp;
int utmplen;
unsigned long err = ERR_peek_error();
if (ERR_GET_LIB(err) == ERR_LIB_PKCS12
&& ERR_GET_REASON(err) == PKCS12_R_MAC_ABSENT) {
BIO_printf(bio_err, "Warning: MAC is absent!\n");
goto dump;
}
utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen);
if (utmp == NULL)
goto end;
badpass = OPENSSL_uni2utf8(utmp, utmplen);
OPENSSL_free(utmp);
if (!PKCS12_verify_mac(p12, badpass, -1)) {
BIO_printf(bio_err, "Mac verify error: invalid password?\n");
ERR_print_errors(bio_err);
goto end;
} else {
BIO_printf(bio_err, "Warning: using broken algorithm\n");
if (!twopass)
cpass = badpass;
}
}
}
dump:
assert(private);
out = bio_open_owner(outfile, FORMAT_PEM, private);
if (out == NULL)
goto end;
if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) {
BIO_printf(bio_err, "Error outputting keys and certificates\n");
ERR_print_errors(bio_err);
goto end;
}
ret = 0;
end:
PKCS12_free(p12);
release_engine(e);
BIO_free(in);
BIO_free_all(out);
sk_OPENSSL_STRING_free(canames);
OPENSSL_free(badpass);
OPENSSL_free(passcerts);
OPENSSL_free(passin);
OPENSSL_free(passout);
return ret;
}
int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass,
int passlen, int options, char *pempass,
const EVP_CIPHER *enc)
{
STACK_OF(PKCS7) *asafes = NULL;
STACK_OF(PKCS12_SAFEBAG) *bags;
int i, bagnid;
int ret = 0;
PKCS7 *p7;
if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
return 0;
for (i = 0; i < sk_PKCS7_num(asafes); i++) {
p7 = sk_PKCS7_value(asafes, i);
bagnid = OBJ_obj2nid(p7->type);
if (bagnid == NID_pkcs7_data) {
bags = PKCS12_unpack_p7data(p7);
if (options & INFO)
BIO_printf(bio_err, "PKCS7 Data\n");
} else if (bagnid == NID_pkcs7_encrypted) {
if (options & INFO) {
BIO_printf(bio_err, "PKCS7 Encrypted data: ");
if (p7->d.encrypted == NULL) {
BIO_printf(bio_err, "<no data>\n");
} else {
alg_print(p7->d.encrypted->enc_data->algorithm);
}
}
bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
} else {
continue;
}
if (!bags)
goto err;
if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
options, pempass, enc)) {
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
goto err;
}
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
bags = NULL;
}
ret = 1;
err:
sk_PKCS7_pop_free(asafes, PKCS7_free);
return ret;
}
int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
const char *pass, int passlen, int options,
char *pempass, const EVP_CIPHER *enc)
{
int i;
for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
if (!dump_certs_pkeys_bag(out,
sk_PKCS12_SAFEBAG_value(bags, i),
pass, passlen, options, pempass, enc))
return 0;
}
return 1;
}
int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
const char *pass, int passlen, int options,
char *pempass, const EVP_CIPHER *enc)
{
EVP_PKEY *pkey;
PKCS8_PRIV_KEY_INFO *p8;
const PKCS8_PRIV_KEY_INFO *p8c;
X509 *x509;
const STACK_OF(X509_ATTRIBUTE) *attrs;
int ret = 0;
attrs = PKCS12_SAFEBAG_get0_attrs(bag);
switch (PKCS12_SAFEBAG_get_nid(bag)) {
case NID_keyBag:
if (options & INFO)
BIO_printf(bio_err, "Key bag\n");
if (options & NOKEYS)
return 1;
print_attribs(out, attrs, "Bag Attributes");
p8c = PKCS12_SAFEBAG_get0_p8inf(bag);
if ((pkey = EVP_PKCS82PKEY(p8c)) == NULL)
return 0;
print_attribs(out, PKCS8_pkey_get0_attrs(p8c), "Key Attributes");
ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
EVP_PKEY_free(pkey);
break;
case NID_pkcs8ShroudedKeyBag:
if (options & INFO) {
const X509_SIG *tp8;
const X509_ALGOR *tp8alg;
BIO_printf(bio_err, "Shrouded Keybag: ");
tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag);
X509_SIG_get0(tp8, &tp8alg, NULL);
alg_print(tp8alg);
}
if (options & NOKEYS)
return 1;
print_attribs(out, attrs, "Bag Attributes");
if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
return 0;
if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) {
PKCS8_PRIV_KEY_INFO_free(p8);
return 0;
}
print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes");
PKCS8_PRIV_KEY_INFO_free(p8);
ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
EVP_PKEY_free(pkey);
break;
case NID_certBag:
if (options & INFO)
BIO_printf(bio_err, "Certificate bag\n");
if (options & NOCERTS)
return 1;
if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) {
if (options & CACERTS)
return 1;
} else if (options & CLCERTS)
return 1;
print_attribs(out, attrs, "Bag Attributes");
if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
return 1;
if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL)
return 0;
dump_cert_text(out, x509);
ret = PEM_write_bio_X509(out, x509);
X509_free(x509);
break;
case NID_secretBag:
if (options & INFO)
BIO_printf(bio_err, "Secret bag\n");
print_attribs(out, attrs, "Bag Attributes");
BIO_printf(bio_err, "Bag Type: ");
i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_bag_type(bag));
BIO_printf(bio_err, "\nBag Value: ");
print_attribute(out, PKCS12_SAFEBAG_get0_bag_obj(bag));
return 1;
case NID_safeContentsBag:
if (options & INFO)
BIO_printf(bio_err, "Safe Contents bag\n");
print_attribs(out, attrs, "Bag Attributes");
return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag),
pass, passlen, options, pempass, enc);
default:
BIO_printf(bio_err, "Warning unsupported bag type: ");
i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag));
BIO_printf(bio_err, "\n");
return 1;
}
return ret;
}
/* Given a single certificate return a verified chain or NULL if error */
static int get_cert_chain(X509 *cert, X509_STORE *store,
STACK_OF(X509) *untrusted_certs,
STACK_OF(X509) **chain)
{
X509_STORE_CTX *store_ctx = NULL;
STACK_OF(X509) *chn = NULL;
int i = 0;
store_ctx = X509_STORE_CTX_new_ex(app_get0_libctx(), app_get0_propq());
if (store_ctx == NULL) {
i = X509_V_ERR_UNSPECIFIED;
goto end;
}
if (!X509_STORE_CTX_init(store_ctx, store, cert, untrusted_certs)) {
i = X509_V_ERR_UNSPECIFIED;
goto end;
}
if (X509_verify_cert(store_ctx) > 0)
chn = X509_STORE_CTX_get1_chain(store_ctx);
else if ((i = X509_STORE_CTX_get_error(store_ctx)) == 0)
i = X509_V_ERR_UNSPECIFIED;
end:
X509_STORE_CTX_free(store_ctx);
*chain = chn;
return i;
}
static int alg_print(const X509_ALGOR *alg)
{
int pbenid, aparamtype;
const ASN1_OBJECT *aoid;
const void *aparam;
PBEPARAM *pbe = NULL;
X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg);
pbenid = OBJ_obj2nid(aoid);
BIO_printf(bio_err, "%s", OBJ_nid2ln(pbenid));
/*
* If PBE algorithm is PBES2 decode algorithm parameters
* for additional details.
*/
if (pbenid == NID_pbes2) {
PBE2PARAM *pbe2 = NULL;
int encnid;
if (aparamtype == V_ASN1_SEQUENCE)
pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM));
if (pbe2 == NULL) {
BIO_puts(bio_err, ", <unsupported parameters>");
goto done;
}
X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc);
pbenid = OBJ_obj2nid(aoid);
X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption);
encnid = OBJ_obj2nid(aoid);
BIO_printf(bio_err, ", %s, %s", OBJ_nid2ln(pbenid),
OBJ_nid2sn(encnid));
/* If KDF is PBKDF2 decode parameters */
if (pbenid == NID_id_pbkdf2) {
PBKDF2PARAM *kdf = NULL;
int prfnid;
if (aparamtype == V_ASN1_SEQUENCE)
kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM));
if (kdf == NULL) {
BIO_puts(bio_err, ", <unsupported parameters>");
goto done;
}
if (kdf->prf == NULL) {
prfnid = NID_hmacWithSHA1;
} else {
X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf);
prfnid = OBJ_obj2nid(aoid);
}
BIO_printf(bio_err, ", Iteration %ld, PRF %s",
ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid));
PBKDF2PARAM_free(kdf);
#ifndef OPENSSL_NO_SCRYPT
} else if (pbenid == NID_id_scrypt) {
SCRYPT_PARAMS *kdf = NULL;
if (aparamtype == V_ASN1_SEQUENCE)
kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS));
if (kdf == NULL) {
BIO_puts(bio_err, ", <unsupported parameters>");
goto done;
}
BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, "
"Block size(r): %ld, Parallelism(p): %ld",
ASN1_STRING_length(kdf->salt),
ASN1_INTEGER_get(kdf->costParameter),
ASN1_INTEGER_get(kdf->blockSize),
ASN1_INTEGER_get(kdf->parallelizationParameter));
SCRYPT_PARAMS_free(kdf);
#endif
}
PBE2PARAM_free(pbe2);
} else {
if (aparamtype == V_ASN1_SEQUENCE)
pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM));
if (pbe == NULL) {
BIO_puts(bio_err, ", <unsupported parameters>");
goto done;
}
BIO_printf(bio_err, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter));
PBEPARAM_free(pbe);
}
done:
BIO_puts(bio_err, "\n");
return 1;
}
/* Load all certificates from a given file */
int cert_load(BIO *in, STACK_OF(X509) *sk)
{
int ret = 0;
X509 *cert;
while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
ret = 1;
if (!sk_X509_push(sk, cert))
return 0;
}
if (ret)
ERR_clear_error();
return ret;
}
/* Generalised x509 attribute value print */
void print_attribute(BIO *out, const ASN1_TYPE *av)
{
char *value;
switch (av->type) {
case V_ASN1_BMPSTRING:
value = OPENSSL_uni2asc(av->value.bmpstring->data,
av->value.bmpstring->length);
BIO_printf(out, "%s\n", value);
OPENSSL_free(value);
break;
case V_ASN1_UTF8STRING:
BIO_printf(out, "%.*s\n", av->value.utf8string->length,
av->value.utf8string->data);
break;
case V_ASN1_OCTET_STRING:
hex_prin(out, av->value.octet_string->data,
av->value.octet_string->length);
BIO_printf(out, "\n");
break;
case V_ASN1_BIT_STRING:
hex_prin(out, av->value.bit_string->data,
av->value.bit_string->length);
BIO_printf(out, "\n");
break;
default:
BIO_printf(out, "<Unsupported tag %d>\n", av->type);
break;
}
}
/* Generalised attribute print: handle PKCS#8 and bag attributes */
int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
const char *name)
{
X509_ATTRIBUTE *attr;
ASN1_TYPE *av;
int i, j, attr_nid;
if (!attrlst) {
BIO_printf(out, "%s: <No Attributes>\n", name);
return 1;
}
if (!sk_X509_ATTRIBUTE_num(attrlst)) {
BIO_printf(out, "%s: <Empty Attributes>\n", name);
return 1;
}
BIO_printf(out, "%s\n", name);
for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
ASN1_OBJECT *attr_obj;
attr = sk_X509_ATTRIBUTE_value(attrlst, i);
attr_obj = X509_ATTRIBUTE_get0_object(attr);
attr_nid = OBJ_obj2nid(attr_obj);
BIO_printf(out, " ");
if (attr_nid == NID_undef) {
i2a_ASN1_OBJECT(out, attr_obj);
BIO_printf(out, ": ");
} else {
BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
}
if (X509_ATTRIBUTE_count(attr)) {
for (j = 0; j < X509_ATTRIBUTE_count(attr); j++)
{
av = X509_ATTRIBUTE_get0_type(attr, j);
print_attribute(out, av);
}
} else {
BIO_printf(out, "<No Values>\n");
}
}
return 1;
}
void hex_prin(BIO *out, unsigned char *buf, int len)
{
int i;
for (i = 0; i < len; i++)
BIO_printf(out, "%02X ", buf[i]);
}
static int set_pbe(int *ppbe, const char *str)
{
if (!str)
return 0;
if (strcmp(str, "NONE") == 0) {
*ppbe = -1;
return 1;
}
*ppbe = OBJ_txt2nid(str);
if (*ppbe == NID_undef) {
BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
return 0;
}
return 1;
}
diff --git a/crypto/openssl/apps/pkeyutl.c b/crypto/openssl/apps/pkeyutl.c
index 3c9f9025a160..5e5047137632 100644
--- a/crypto/openssl/apps/pkeyutl.c
+++ b/crypto/openssl/apps/pkeyutl.c
@@ -1,801 +1,802 @@
/*
* Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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"
#include <string.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <sys/stat.h>
#define KEY_NONE 0
#define KEY_PRIVKEY 1
#define KEY_PUBKEY 2
#define KEY_CERT 3
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
const char *keyfile, int keyform, int key_type,
char *passinarg, int pkey_op, ENGINE *e,
const int impl, int rawin, EVP_PKEY **ppkey,
EVP_MD_CTX *mctx, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq);
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
ENGINE *e);
static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
unsigned char *out, size_t *poutlen,
const unsigned char *in, size_t inlen);
static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
EVP_PKEY *pkey, BIO *in,
int filesize, unsigned char *sig, int siglen,
unsigned char **out, size_t *poutlen);
typedef enum OPTION_choice {
OPT_COMMON,
OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT,
OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN,
OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF,
OPT_KDFLEN, OPT_R_ENUM, OPT_PROV_ENUM,
OPT_CONFIG,
OPT_RAWIN, OPT_DIGEST
} OPTION_CHOICE;
const OPTIONS pkeyutl_options[] = {
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
{"engine_impl", OPT_ENGINE_IMPL, '-',
"Also use engine given by -engine for crypto operations"},
#endif
{"sign", OPT_SIGN, '-', "Sign input data with private key"},
{"verify", OPT_VERIFY, '-', "Verify with public key"},
{"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"},
{"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"},
{"derive", OPT_DERIVE, '-', "Derive shared secret"},
OPT_CONFIG_OPTION,
OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file - default stdin"},
{"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"},
{"pubin", OPT_PUBIN, '-', "Input is a public key"},
{"inkey", OPT_INKEY, 's', "Input private key file"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
{"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"},
{"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
{"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
{"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"},
{"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output file - default stdout"},
- {"asn1parse", OPT_ASN1PARSE, '-', "asn1parse the output data"},
+ {"asn1parse", OPT_ASN1PARSE, '-',
+ "parse the output as ASN.1 data to check its DER encoding and print errors"},
{"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
{"verifyrecover", OPT_VERIFYRECOVER, '-',
- "Verify with public key, recover original data"},
+ "Verify RSA signature, recovering original signature input data"},
OPT_SECTION("Signing/Derivation"),
{"digest", OPT_DIGEST, 's',
"Specify the digest algorithm when signing the raw input data"},
{"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
{"pkeyopt_passin", OPT_PKEYOPT_PASSIN, 's',
"Public key option that is read as a passphrase argument opt:passphrase"},
{"kdf", OPT_KDF, 's', "Use KDF algorithm"},
{"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"},
OPT_R_OPTIONS,
OPT_PROV_OPTIONS,
{NULL}
};
int pkeyutl_main(int argc, char **argv)
{
CONF *conf = NULL;
BIO *in = NULL, *out = NULL;
ENGINE *e = NULL;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL;
char hexdump = 0, asn1parse = 0, rev = 0, *prog;
unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
OPTION_CHOICE o;
int buf_inlen = 0, siglen = -1;
int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF;
int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
int engine_impl = 0;
int ret = 1, rv = -1;
size_t buf_outlen;
const char *inkey = NULL;
const char *peerkey = NULL;
const char *kdfalg = NULL, *digestname = NULL;
int kdflen = 0;
STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
int rawin = 0;
EVP_MD_CTX *mctx = NULL;
EVP_MD *md = NULL;
int filesize = -1;
OSSL_LIB_CTX *libctx = app_get0_libctx();
prog = opt_init(argc, argv, pkeyutl_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(pkeyutl_options);
ret = 0;
goto end;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_SIGFILE:
sigfile = opt_arg();
break;
case OPT_ENGINE_IMPL:
engine_impl = 1;
break;
case OPT_INKEY:
inkey = opt_arg();
break;
case OPT_PEERKEY:
peerkey = opt_arg();
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_PEERFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &peerform))
goto opthelp;
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_CONFIG:
conf = app_load_config_modules(opt_arg());
if (conf == NULL)
goto end;
break;
case OPT_PROV_CASES:
if (!opt_provider(o))
goto end;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_PUBIN:
key_type = KEY_PUBKEY;
break;
case OPT_CERTIN:
key_type = KEY_CERT;
break;
case OPT_ASN1PARSE:
asn1parse = 1;
break;
case OPT_HEXDUMP:
hexdump = 1;
break;
case OPT_SIGN:
pkey_op = EVP_PKEY_OP_SIGN;
break;
case OPT_VERIFY:
pkey_op = EVP_PKEY_OP_VERIFY;
break;
case OPT_VERIFYRECOVER:
pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
break;
case OPT_ENCRYPT:
pkey_op = EVP_PKEY_OP_ENCRYPT;
break;
case OPT_DECRYPT:
pkey_op = EVP_PKEY_OP_DECRYPT;
break;
case OPT_DERIVE:
pkey_op = EVP_PKEY_OP_DERIVE;
break;
case OPT_KDF:
pkey_op = EVP_PKEY_OP_DERIVE;
key_type = KEY_NONE;
kdfalg = opt_arg();
break;
case OPT_KDFLEN:
kdflen = atoi(opt_arg());
break;
case OPT_REV:
rev = 1;
break;
case OPT_PKEYOPT:
if ((pkeyopts == NULL &&
(pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) ||
sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) {
BIO_puts(bio_err, "out of memory\n");
goto end;
}
break;
case OPT_PKEYOPT_PASSIN:
if ((pkeyopts_passin == NULL &&
(pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) ||
sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) {
BIO_puts(bio_err, "out of memory\n");
goto end;
}
break;
case OPT_RAWIN:
rawin = 1;
break;
case OPT_DIGEST:
digestname = opt_arg();
break;
}
}
/* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
if (!app_RAND_load())
goto end;
if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
BIO_printf(bio_err,
"%s: -rawin can only be used with -sign or -verify\n",
prog);
goto opthelp;
}
if (digestname != NULL && !rawin) {
BIO_printf(bio_err,
"%s: -digest can only be used with -rawin\n",
prog);
goto opthelp;
}
if (rawin && rev) {
BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n",
prog);
goto opthelp;
}
if (kdfalg != NULL) {
if (kdflen == 0) {
BIO_printf(bio_err,
"%s: no KDF length given (-kdflen parameter).\n", prog);
goto opthelp;
}
} else if (inkey == NULL) {
BIO_printf(bio_err,
"%s: no private key given (-inkey parameter).\n", prog);
goto opthelp;
} else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) {
BIO_printf(bio_err,
"%s: no peer key given (-peerkey parameter).\n", prog);
goto opthelp;
}
if (rawin) {
if ((mctx = EVP_MD_CTX_new()) == NULL) {
BIO_printf(bio_err, "Error: out of memory\n");
goto end;
}
}
ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
passinarg, pkey_op, e, engine_impl, rawin, &pkey,
mctx, digestname, libctx, app_get0_propq());
if (ctx == NULL) {
BIO_printf(bio_err, "%s: Error initializing context\n", prog);
goto end;
}
if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) {
BIO_printf(bio_err, "%s: Error setting up peer key\n", prog);
goto end;
}
if (pkeyopts != NULL) {
int num = sk_OPENSSL_STRING_num(pkeyopts);
int i;
for (i = 0; i < num; ++i) {
const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i);
if (pkey_ctrl_string(ctx, opt) <= 0) {
BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
prog, opt);
goto end;
}
}
}
if (pkeyopts_passin != NULL) {
int num = sk_OPENSSL_STRING_num(pkeyopts_passin);
int i;
for (i = 0; i < num; i++) {
char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i);
char *passin = strchr(opt, ':');
char *passwd;
if (passin == NULL) {
/* Get password interactively */
char passwd_buf[4096];
int r;
BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt);
r = EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1,
passwd_buf, 0);
if (r < 0) {
if (r == -2)
BIO_puts(bio_err, "user abort\n");
else
BIO_puts(bio_err, "entry failed\n");
goto end;
}
passwd = OPENSSL_strdup(passwd_buf);
if (passwd == NULL) {
BIO_puts(bio_err, "out of memory\n");
goto end;
}
} else {
/* Get password as a passin argument: First split option name
* and passphrase argument into two strings */
*passin = 0;
passin++;
if (app_passwd(passin, NULL, &passwd, NULL) == 0) {
BIO_printf(bio_err, "failed to get '%s'\n", opt);
goto end;
}
}
if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) {
BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
prog, opt);
goto end;
}
OPENSSL_free(passwd);
}
}
if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) {
BIO_printf(bio_err,
"%s: Signature file specified for non verify\n", prog);
goto end;
}
if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) {
BIO_printf(bio_err,
"%s: No signature file specified for verify\n", prog);
goto end;
}
if (pkey_op != EVP_PKEY_OP_DERIVE) {
in = bio_open_default(infile, 'r', FORMAT_BINARY);
if (infile != NULL) {
struct stat st;
if (stat(infile, &st) == 0 && st.st_size <= INT_MAX)
filesize = (int)st.st_size;
}
if (in == NULL)
goto end;
}
out = bio_open_default(outfile, 'w', FORMAT_BINARY);
if (out == NULL)
goto end;
if (sigfile != NULL) {
BIO *sigbio = BIO_new_file(sigfile, "rb");
if (sigbio == NULL) {
BIO_printf(bio_err, "Can't open signature file %s\n", sigfile);
goto end;
}
siglen = bio_to_mem(&sig, keysize * 10, sigbio);
BIO_free(sigbio);
if (siglen < 0) {
BIO_printf(bio_err, "Error reading signature data\n");
goto end;
}
}
/* Raw input data is handled elsewhere */
if (in != NULL && !rawin) {
/* Read the input data */
buf_inlen = bio_to_mem(&buf_in, -1, in);
if (buf_inlen < 0) {
BIO_printf(bio_err, "Error reading input Data\n");
goto end;
}
if (rev) {
size_t i;
unsigned char ctmp;
size_t l = (size_t)buf_inlen;
for (i = 0; i < l / 2; i++) {
ctmp = buf_in[i];
buf_in[i] = buf_in[l - 1 - i];
buf_in[l - 1 - i] = ctmp;
}
}
}
/* Sanity check the input if the input is not raw */
if (!rawin
&& buf_inlen > EVP_MAX_MD_SIZE
&& (pkey_op == EVP_PKEY_OP_SIGN
|| pkey_op == EVP_PKEY_OP_VERIFY)) {
BIO_printf(bio_err,
"Error: The input data looks too long to be a hash\n");
goto end;
}
if (pkey_op == EVP_PKEY_OP_VERIFY) {
if (rawin) {
rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen,
NULL, 0);
} else {
rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
buf_in, (size_t)buf_inlen);
}
if (rv == 1) {
BIO_puts(out, "Signature Verified Successfully\n");
ret = 0;
} else {
BIO_puts(out, "Signature Verification Failure\n");
}
goto end;
}
if (rawin) {
/* rawin allocates the buffer in do_raw_keyop() */
rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, NULL, 0,
&buf_out, (size_t *)&buf_outlen);
} else {
if (kdflen != 0) {
buf_outlen = kdflen;
rv = 1;
} else {
rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
buf_in, (size_t)buf_inlen);
}
if (rv > 0 && buf_outlen != 0) {
buf_out = app_malloc(buf_outlen, "buffer output");
rv = do_keyop(ctx, pkey_op,
buf_out, (size_t *)&buf_outlen,
buf_in, (size_t)buf_inlen);
}
}
if (rv <= 0) {
if (pkey_op != EVP_PKEY_OP_DERIVE) {
BIO_puts(bio_err, "Public Key operation error\n");
} else {
BIO_puts(bio_err, "Key derivation failed\n");
}
goto end;
}
ret = 0;
if (asn1parse) {
if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
ERR_print_errors(bio_err); /* but still return success */
} else if (hexdump) {
BIO_dump(out, (char *)buf_out, buf_outlen);
} else {
BIO_write(out, buf_out, buf_outlen);
}
end:
if (ret != 0)
ERR_print_errors(bio_err);
EVP_MD_CTX_free(mctx);
EVP_PKEY_CTX_free(ctx);
EVP_MD_free(md);
release_engine(e);
BIO_free(in);
BIO_free_all(out);
OPENSSL_free(buf_in);
OPENSSL_free(buf_out);
OPENSSL_free(sig);
sk_OPENSSL_STRING_free(pkeyopts);
sk_OPENSSL_STRING_free(pkeyopts_passin);
NCONF_free(conf);
return ret;
}
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
const char *keyfile, int keyform, int key_type,
char *passinarg, int pkey_op, ENGINE *e,
const int engine_impl, int rawin,
EVP_PKEY **ppkey, EVP_MD_CTX *mctx, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
ENGINE *impl = NULL;
char *passin = NULL;
int rv = -1;
X509 *x;
if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
|| (pkey_op == EVP_PKEY_OP_DERIVE))
&& (key_type != KEY_PRIVKEY && kdfalg == NULL)) {
BIO_printf(bio_err, "A private key is needed for this operation\n");
goto end;
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
switch (key_type) {
case KEY_PRIVKEY:
pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
break;
case KEY_PUBKEY:
pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
break;
case KEY_CERT:
x = load_cert(keyfile, keyform, "Certificate");
if (x) {
pkey = X509_get_pubkey(x);
X509_free(x);
}
break;
case KEY_NONE:
break;
}
#ifndef OPENSSL_NO_ENGINE
if (engine_impl)
impl = e;
#endif
if (kdfalg != NULL) {
int kdfnid = OBJ_sn2nid(kdfalg);
if (kdfnid == NID_undef) {
kdfnid = OBJ_ln2nid(kdfalg);
if (kdfnid == NID_undef) {
BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n",
kdfalg);
goto end;
}
}
if (impl != NULL)
ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
else
ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq);
} else {
if (pkey == NULL)
goto end;
*pkeysize = EVP_PKEY_get_size(pkey);
if (impl != NULL)
ctx = EVP_PKEY_CTX_new(pkey, impl);
else
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
if (ppkey != NULL)
*ppkey = pkey;
EVP_PKEY_free(pkey);
}
if (ctx == NULL)
goto end;
if (rawin) {
EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
switch (pkey_op) {
case EVP_PKEY_OP_SIGN:
rv = EVP_DigestSignInit_ex(mctx, NULL, digestname, libctx, propq,
pkey, NULL);
break;
case EVP_PKEY_OP_VERIFY:
rv = EVP_DigestVerifyInit_ex(mctx, NULL, digestname, libctx, propq,
pkey, NULL);
break;
}
} else {
switch (pkey_op) {
case EVP_PKEY_OP_SIGN:
rv = EVP_PKEY_sign_init(ctx);
break;
case EVP_PKEY_OP_VERIFY:
rv = EVP_PKEY_verify_init(ctx);
break;
case EVP_PKEY_OP_VERIFYRECOVER:
rv = EVP_PKEY_verify_recover_init(ctx);
break;
case EVP_PKEY_OP_ENCRYPT:
rv = EVP_PKEY_encrypt_init(ctx);
break;
case EVP_PKEY_OP_DECRYPT:
rv = EVP_PKEY_decrypt_init(ctx);
break;
case EVP_PKEY_OP_DERIVE:
rv = EVP_PKEY_derive_init(ctx);
break;
}
}
if (rv <= 0) {
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
}
end:
OPENSSL_free(passin);
return ctx;
}
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
ENGINE *e)
{
EVP_PKEY *peer = NULL;
ENGINE *engine = NULL;
int ret;
if (peerform == FORMAT_ENGINE)
engine = e;
peer = load_pubkey(file, peerform, 0, NULL, engine, "peer key");
if (peer == NULL) {
BIO_printf(bio_err, "Error reading peer key %s\n", file);
return 0;
}
ret = EVP_PKEY_derive_set_peer(ctx, peer) > 0;
EVP_PKEY_free(peer);
return ret;
}
static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
unsigned char *out, size_t *poutlen,
const unsigned char *in, size_t inlen)
{
int rv = 0;
switch (pkey_op) {
case EVP_PKEY_OP_VERIFYRECOVER:
rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
break;
case EVP_PKEY_OP_SIGN:
rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
break;
case EVP_PKEY_OP_ENCRYPT:
rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
break;
case EVP_PKEY_OP_DECRYPT:
rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
break;
case EVP_PKEY_OP_DERIVE:
rv = EVP_PKEY_derive(ctx, out, poutlen);
break;
}
return rv;
}
#define TBUF_MAXSIZE 2048
static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
EVP_PKEY *pkey, BIO *in,
int filesize, unsigned char *sig, int siglen,
unsigned char **out, size_t *poutlen)
{
int rv = 0;
unsigned char tbuf[TBUF_MAXSIZE];
unsigned char *mbuf = NULL;
int buf_len = 0;
/* Some algorithms only support oneshot digests */
if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED25519
|| EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448) {
if (filesize < 0) {
BIO_printf(bio_err,
"Error: unable to determine file size for oneshot operation\n");
goto end;
}
mbuf = app_malloc(filesize, "oneshot sign/verify buffer");
switch(pkey_op) {
case EVP_PKEY_OP_VERIFY:
buf_len = BIO_read(in, mbuf, filesize);
if (buf_len != filesize) {
BIO_printf(bio_err, "Error reading raw input data\n");
goto end;
}
rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len);
break;
case EVP_PKEY_OP_SIGN:
buf_len = BIO_read(in, mbuf, filesize);
if (buf_len != filesize) {
BIO_printf(bio_err, "Error reading raw input data\n");
goto end;
}
rv = EVP_DigestSign(mctx, NULL, poutlen, mbuf, buf_len);
if (rv == 1 && out != NULL) {
*out = app_malloc(*poutlen, "buffer output");
rv = EVP_DigestSign(mctx, *out, poutlen, mbuf, buf_len);
}
break;
}
goto end;
}
switch(pkey_op) {
case EVP_PKEY_OP_VERIFY:
for (;;) {
buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
if (buf_len == 0)
break;
if (buf_len < 0) {
BIO_printf(bio_err, "Error reading raw input data\n");
goto end;
}
rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)buf_len);
if (rv != 1) {
BIO_printf(bio_err, "Error verifying raw input data\n");
goto end;
}
}
rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
break;
case EVP_PKEY_OP_SIGN:
for (;;) {
buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
if (buf_len == 0)
break;
if (buf_len < 0) {
BIO_printf(bio_err, "Error reading raw input data\n");
goto end;
}
rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)buf_len);
if (rv != 1) {
BIO_printf(bio_err, "Error signing raw input data\n");
goto end;
}
}
rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
if (rv == 1 && out != NULL) {
*out = app_malloc(*poutlen, "buffer output");
rv = EVP_DigestSignFinal(mctx, *out, poutlen);
}
break;
}
end:
OPENSSL_free(mbuf);
return rv;
}
diff --git a/crypto/openssl/apps/rehash.c b/crypto/openssl/apps/rehash.c
index 85eee3857942..6e0ca3642c40 100644
--- a/crypto/openssl/apps/rehash.c
+++ b/crypto/openssl/apps/rehash.c
@@ -1,584 +1,589 @@
/*
* Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2013-2014 Timo Teräs <timo.teras@gmail.com>
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
# define MAX_COLLISIONS 256
# if defined(OPENSSL_SYS_VXWORKS)
/*
* VxWorks has no symbolic links
*/
# define lstat(path, buf) stat(path, buf)
int symlink(const char *target, const char *linkpath)
{
errno = ENOSYS;
return -1;
}
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
{
errno = ENOSYS;
return -1;
}
# endif
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 (ep->filename == NULL) {
OPENSSL_free(ep);
ep = NULL;
BIO_printf(bio_err, "out of memory\n");
return 1;
}
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 (OPENSSL_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;
const 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 (OPENSSL_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);
if (!X509_digest(x->x509, evpmd, digest, NULL)) {
BIO_printf(bio_err, "out of memory\n");
++errs;
goto end;
}
} else if (x->crl != NULL) {
type = TYPE_CRL;
name = X509_CRL_get_issuer(x->crl);
if (!X509_CRL_digest(x->crl, evpmd, digest, NULL)) {
BIO_printf(bio_err, "out of memory\n");
++errs;
goto end;
}
} else {
++errs;
goto end;
}
if (name != NULL) {
if (h == HASH_NEW || h == HASH_BOTH) {
int ok;
unsigned long hash_value =
X509_NAME_hash_ex(name,
app_get0_libctx(), app_get0_propq(), &ok);
if (ok) {
errs += add_entry(type, hash_value, filename, digest, 1, ~0);
} else {
BIO_printf(bio_err, "%s: error calculating SHA1 hash value\n",
opt_getprog());
errs++;
}
}
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 == '/';
}
static int sk_strcmp(const char * const *a, const char * const *b)
{
return strcmp(*a, *b);
}
/*
* 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, dirlen, buflen, errs = 0;
size_t i, fname_max_len = 20; /* maximum length of "%08x.r%d" */
const char *pathsep = "";
const char *filename;
char *buf = NULL, *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;
}
dirlen = strlen(dirname);
if (dirlen != 0 && !ends_with_dirsep(dirname)) {
pathsep = "/";
dirlen++;
}
if (verbose)
BIO_printf(bio_out, "Doing %s\n", dirname);
if ((files = sk_OPENSSL_STRING_new(sk_strcmp)) == NULL) {
BIO_printf(bio_err, "Skipping %s, out of memory\n", dirname);
errs = 1;
goto err;
}
while ((filename = OPENSSL_DIR_read(&d, dirname)) != NULL) {
size_t fname_len = strlen(filename);
if ((copy = OPENSSL_strdup(filename)) == NULL
|| sk_OPENSSL_STRING_push(files, copy) == 0) {
OPENSSL_free(copy);
OPENSSL_DIR_end(&d);
BIO_puts(bio_err, "out of memory\n");
errs = 1;
goto err;
}
if (fname_len > fname_max_len)
fname_max_len = fname_len;
}
OPENSSL_DIR_end(&d);
sk_OPENSSL_STRING_sort(files);
buflen = dirlen + fname_max_len + 1;
buf = app_malloc(buflen, "filename buffer");
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%08x.%s%d",
dirname, pathsep, bp->hash,
suffixes[bp->type], nextid);
if (verbose)
BIO_printf(bio_out, "link %s -> %s\n",
ep->filename, &buf[dirlen]);
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%08x.%s%d",
dirname, pathsep, bp->hash,
suffixes[bp->type], ep->old_id);
if (verbose)
BIO_printf(bio_out, "unlink %s\n",
&buf[dirlen]);
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_COMMON,
OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE,
OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS rehash_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [directory...]\n"},
OPT_SECTION("General"),
{"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"},
OPT_SECTION("Output"),
{"v", OPT_VERBOSE, '-', "Verbose output"},
OPT_PROV_OPTIONS,
OPT_PARAMETERS(),
{"directory", 0, 0, "One or more directories to process (optional)"},
{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;
case OPT_PROV_CASES:
if (!opt_provider(o))
goto end;
break;
}
}
/* Optional arguments are directories to scan. */
argc = opt_num_rest();
argv = opt_rest();
evpmd = EVP_sha1();
evpmdsize = EVP_MD_get_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);
+ if (m == NULL) {
+ BIO_puts(bio_err, "out of memory\n");
+ errs = 1;
+ goto end;
+ }
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/crypto/openssl/apps/smime.c b/crypto/openssl/apps/smime.c
index 651294e46daa..790a8d06ad0c 100644
--- a/crypto/openssl/apps/smime.c
+++ b/crypto/openssl/apps/smime.c
@@ -1,710 +1,716 @@
/*
- * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* S/MIME utility function */
#include <stdio.h>
#include <string.h>
#include "apps.h"
#include "progs.h"
#include <openssl/crypto.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/x509_vfy.h>
#include <openssl/x509v3.h>
static int save_certs(char *signerfile, STACK_OF(X509) *signers);
static int smime_cb(int ok, X509_STORE_CTX *ctx);
#define SMIME_OP 0x10
#define SMIME_IP 0x20
#define SMIME_SIGNERS 0x40
#define SMIME_ENCRYPT (1 | SMIME_OP)
#define SMIME_DECRYPT (2 | SMIME_IP)
#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
#define SMIME_VERIFY (4 | SMIME_IP)
#define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP)
#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
typedef enum OPTION_choice {
OPT_COMMON,
OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY,
OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN,
OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP,
OPT_BINARY, OPT_NOSIGS, OPT_STREAM, OPT_INDEF, OPT_NOINDEF,
OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN,
OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD,
OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE,
OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE,
OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG,
OPT_V_ENUM,
OPT_IN, OPT_INFORM, OPT_OUT,
OPT_OUTFORM, OPT_CONTENT
} OPTION_CHOICE;
const OPTIONS smime_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"},
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"in", OPT_IN, '<', "Input file"},
{"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
{"out", OPT_OUT, '>', "Output file"},
{"outform", OPT_OUTFORM, 'c',
"Output format SMIME (default), PEM or DER"},
{"inkey", OPT_INKEY, 's',
"Input private key (if not signer or recipient)"},
{"keyform", OPT_KEYFORM, 'f', "Input private key format (ENGINE, other values ignored)"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{"stream", OPT_STREAM, '-', "Enable CMS streaming" },
{"indef", OPT_INDEF, '-', "Same as -stream" },
{"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
OPT_CONFIG_OPTION,
OPT_SECTION("Action"),
{"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
{"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
{"sign", OPT_SIGN, '-', "Sign message"},
{"resign", OPT_RESIGN, '-', "Resign a signed message"},
{"verify", OPT_VERIFY, '-', "Verify signed message"},
OPT_SECTION("Signing/Encryption"),
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
{"", OPT_CIPHER, '-', "Any supported cipher"},
{"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"},
{"nointern", OPT_NOINTERN, '-',
"Don't search certificates in message for signer"},
{"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
{"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
{"binary", OPT_BINARY, '-', "Don't translate message to text"},
{"signer", OPT_SIGNER, 's', "Signer certificate file"},
{"content", OPT_CONTENT, '<',
"Supply or override content for detached signature"},
{"nocerts", OPT_NOCERTS, '-',
"Don't include signers certificate when signing"},
OPT_SECTION("Verification/Decryption"),
{"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
{"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
{"certfile", OPT_CERTFILE, '<', "Other certificates file"},
{"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"},
OPT_SECTION("Email"),
{"to", OPT_TO, 's', "To address"},
{"from", OPT_FROM, 's', "From address"},
{"subject", OPT_SUBJECT, 's', "Subject"},
{"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
{"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
OPT_SECTION("Certificate chain"),
{"CApath", OPT_CAPATH, '/', "Trusted certificates directory"},
{"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
{"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
{"no-CAstore", OPT_NOCASTORE, '-',
"Do not load certificates from the default certificates store"},
{"nochain", OPT_NOCHAIN, '-',
"set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" },
{"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of LF only"},
OPT_R_OPTIONS,
OPT_V_OPTIONS,
OPT_PROV_OPTIONS,
OPT_PARAMETERS(),
{"cert", 0, 0, "Recipient certs, used when encrypting"},
{NULL}
};
int smime_main(int argc, char **argv)
{
CONF *conf = NULL;
BIO *in = NULL, *out = NULL, *indata = NULL;
EVP_PKEY *key = NULL;
PKCS7 *p7 = NULL;
STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
STACK_OF(X509) *encerts = NULL, *other = NULL;
X509 *cert = NULL, *recip = NULL, *signer = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = NULL;
EVP_CIPHER *cipher = NULL;
EVP_MD *sign_md = NULL;
const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL, *prog = NULL;
char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL;
char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL;
char *subject = NULL, *digestname = NULL, *ciphername = NULL;
OPTION_CHOICE o;
int noCApath = 0, noCAfile = 0, noCAstore = 0;
int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0;
int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform =
FORMAT_UNDEF;
int vpmtouched = 0, rv = 0;
ENGINE *e = NULL;
const char *mime_eol = "\n";
OSSL_LIB_CTX *libctx = app_get0_libctx();
if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
return 1;
prog = opt_init(argc, argv, smime_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(smime_options);
ret = 0;
goto end;
case OPT_INFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
goto opthelp;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
goto opthelp;
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_ENCRYPT:
operation = SMIME_ENCRYPT;
break;
case OPT_DECRYPT:
operation = SMIME_DECRYPT;
break;
case OPT_SIGN:
operation = SMIME_SIGN;
break;
case OPT_RESIGN:
operation = SMIME_RESIGN;
break;
case OPT_VERIFY:
operation = SMIME_VERIFY;
break;
case OPT_PK7OUT:
operation = SMIME_PK7OUT;
break;
case OPT_TEXT:
flags |= PKCS7_TEXT;
break;
case OPT_NOINTERN:
flags |= PKCS7_NOINTERN;
break;
case OPT_NOVERIFY:
flags |= PKCS7_NOVERIFY;
break;
case OPT_NOCHAIN:
flags |= PKCS7_NOCHAIN;
break;
case OPT_NOCERTS:
flags |= PKCS7_NOCERTS;
break;
case OPT_NOATTR:
flags |= PKCS7_NOATTR;
break;
case OPT_NODETACH:
flags &= ~PKCS7_DETACHED;
break;
case OPT_NOSMIMECAP:
flags |= PKCS7_NOSMIMECAP;
break;
case OPT_BINARY:
flags |= PKCS7_BINARY;
break;
case OPT_NOSIGS:
flags |= PKCS7_NOSIGS;
break;
case OPT_STREAM:
case OPT_INDEF:
indef = 1;
break;
case OPT_NOINDEF:
indef = 0;
break;
case OPT_CRLFEOL:
flags |= PKCS7_CRLFEOL;
mime_eol = "\r\n";
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_PROV_CASES:
if (!opt_provider(o))
goto end;
break;
case OPT_CONFIG:
conf = app_load_config_modules(opt_arg());
if (conf == NULL)
goto end;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_TO:
to = opt_arg();
break;
case OPT_FROM:
from = opt_arg();
break;
case OPT_SUBJECT:
subject = opt_arg();
break;
case OPT_SIGNER:
/* If previous -signer argument add signer to list */
if (signerfile != NULL) {
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0)
+ goto end;
if (keyfile == NULL)
keyfile = signerfile;
if (skkeys == NULL
&& (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(skkeys, keyfile);
+ if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0)
+ goto end;
keyfile = NULL;
}
signerfile = opt_arg();
break;
case OPT_RECIP:
recipfile = opt_arg();
break;
case OPT_MD:
digestname = opt_arg();
break;
case OPT_CIPHER:
ciphername = opt_unknown();
break;
case OPT_INKEY:
/* If previous -inkey argument add signer to list */
if (keyfile != NULL) {
if (signerfile == NULL) {
BIO_printf(bio_err,
"%s: Must have -signer before -inkey\n", prog);
goto opthelp;
}
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0)
+ goto end;
signerfile = NULL;
if (skkeys == NULL
&& (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(skkeys, keyfile);
+ if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0)
+ goto end;
}
keyfile = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
break;
case OPT_CERTFILE:
certfile = opt_arg();
break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_CAPATH:
CApath = opt_arg();
break;
case OPT_CASTORE:
CAstore = opt_arg();
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_NOCASTORE:
noCAstore = 1;
break;
case OPT_CONTENT:
contfile = opt_arg();
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto opthelp;
vpmtouched++;
break;
}
}
/* Extra arguments are files with recipient keys. */
argc = opt_num_rest();
argv = opt_rest();
if (!app_RAND_load())
goto end;
if (digestname != NULL) {
if (!opt_md(digestname, &sign_md))
goto opthelp;
}
if (ciphername != NULL) {
if (!opt_cipher_any(ciphername, &cipher))
goto opthelp;
}
if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) {
BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
goto opthelp;
}
if (!operation) {
BIO_puts(bio_err,
"No operation (-encrypt|-sign|...) specified\n");
goto opthelp;
}
if (operation & SMIME_SIGNERS) {
/* Check to see if any final signer needs to be appended */
if (keyfile && !signerfile) {
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
goto opthelp;
}
if (signerfile != NULL) {
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
- sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0)
+ goto end;
if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
if (!keyfile)
keyfile = signerfile;
- sk_OPENSSL_STRING_push(skkeys, keyfile);
+ if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0)
+ goto end;
}
if (sksigners == NULL) {
BIO_printf(bio_err, "No signer certificate specified\n");
goto opthelp;
}
signerfile = NULL;
keyfile = NULL;
} else if (operation == SMIME_DECRYPT) {
if (recipfile == NULL && keyfile == NULL) {
BIO_printf(bio_err,
"No recipient certificate or key specified\n");
goto opthelp;
}
} else if (operation == SMIME_ENCRYPT) {
if (argc == 0) {
BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
goto opthelp;
}
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
ret = 2;
if (!(operation & SMIME_SIGNERS))
flags &= ~PKCS7_DETACHED;
if (!(operation & SMIME_OP)) {
if (flags & PKCS7_BINARY)
outformat = FORMAT_BINARY;
}
if (!(operation & SMIME_IP)) {
if (flags & PKCS7_BINARY)
informat = FORMAT_BINARY;
}
if (operation == SMIME_ENCRYPT) {
if (cipher == NULL) {
#ifndef OPENSSL_NO_DES
cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
#else
BIO_printf(bio_err, "No cipher selected\n");
goto end;
#endif
}
encerts = sk_X509_new_null();
if (encerts == NULL)
goto end;
while (*argv != NULL) {
cert = load_cert(*argv, FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
if (!sk_X509_push(encerts, cert))
goto end;
cert = NULL;
argv++;
}
}
if (certfile != NULL) {
if (!load_certs(certfile, 0, &other, NULL, "certificates")) {
ERR_print_errors(bio_err);
goto end;
}
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
if ((recip = load_cert(recipfile, FORMAT_UNDEF,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (operation == SMIME_DECRYPT) {
if (keyfile == NULL)
keyfile = recipfile;
} else if (operation == SMIME_SIGN) {
if (keyfile == NULL)
keyfile = signerfile;
} else {
keyfile = NULL;
}
if (keyfile != NULL) {
key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
}
in = bio_open_default(infile, 'r', informat);
if (in == NULL)
goto end;
if (operation & SMIME_IP) {
PKCS7 *p7_in = NULL;
p7 = PKCS7_new_ex(libctx, app_get0_propq());
if (p7 == NULL) {
BIO_printf(bio_err, "Error allocating PKCS7 object\n");
goto end;
}
if (informat == FORMAT_SMIME) {
p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7);
} else if (informat == FORMAT_PEM) {
p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
p7_in = d2i_PKCS7_bio(in, &p7);
} else {
BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
goto end;
}
if (p7_in == NULL) {
BIO_printf(bio_err, "Error reading S/MIME message\n");
goto end;
}
if (contfile != NULL) {
BIO_free(indata);
if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
BIO_printf(bio_err, "Can't read content file %s\n", contfile);
goto end;
}
}
}
out = bio_open_default(outfile, 'w', outformat);
if (out == NULL)
goto end;
if (operation == SMIME_VERIFY) {
if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
CAstore, noCAstore)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, smime_cb);
if (vpmtouched)
X509_STORE_set1_param(store, vpm);
}
ret = 3;
if (operation == SMIME_ENCRYPT) {
if (indef)
flags |= PKCS7_STREAM;
p7 = PKCS7_encrypt_ex(encerts, in, cipher, flags, libctx, app_get0_propq());
} else if (operation & SMIME_SIGNERS) {
int i;
/*
* If detached data content we only enable streaming if S/MIME output
* format.
*/
if (operation == SMIME_SIGN) {
if (flags & PKCS7_DETACHED) {
if (outformat == FORMAT_SMIME)
flags |= PKCS7_STREAM;
} else if (indef) {
flags |= PKCS7_STREAM;
}
flags |= PKCS7_PARTIAL;
p7 = PKCS7_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq());
if (p7 == NULL)
goto end;
if (flags & PKCS7_NOCERTS) {
for (i = 0; i < sk_X509_num(other); i++) {
X509 *x = sk_X509_value(other, i);
PKCS7_add_certificate(p7, x);
}
}
} else {
flags |= PKCS7_REUSE_DIGEST;
}
for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
signerfile = sk_OPENSSL_STRING_value(sksigners, i);
keyfile = sk_OPENSSL_STRING_value(skkeys, i);
signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL)
goto end;
key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags))
goto end;
X509_free(signer);
signer = NULL;
EVP_PKEY_free(key);
key = NULL;
}
/* If not streaming or resigning finalize structure */
if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) {
if (!PKCS7_final(p7, in, flags))
goto end;
}
}
if (p7 == NULL) {
BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
goto end;
}
ret = 4;
if (operation == SMIME_DECRYPT) {
if (!PKCS7_decrypt(p7, key, recip, out, flags)) {
BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
goto end;
}
} else if (operation == SMIME_VERIFY) {
STACK_OF(X509) *signers;
if (PKCS7_verify(p7, other, store, indata, out, flags))
BIO_printf(bio_err, "Verification successful\n");
else {
BIO_printf(bio_err, "Verification failure\n");
goto end;
}
signers = PKCS7_get0_signers(p7, other, flags);
if (!save_certs(signerfile, signers)) {
BIO_printf(bio_err, "Error writing signers to %s\n", signerfile);
ret = 5;
goto end;
}
sk_X509_free(signers);
} else if (operation == SMIME_PK7OUT) {
PEM_write_bio_PKCS7(out, p7);
} else {
if (to)
BIO_printf(out, "To: %s%s", to, mime_eol);
if (from)
BIO_printf(out, "From: %s%s", from, mime_eol);
if (subject)
BIO_printf(out, "Subject: %s%s", subject, mime_eol);
if (outformat == FORMAT_SMIME) {
if (operation == SMIME_RESIGN)
rv = SMIME_write_PKCS7(out, p7, indata, flags);
else
rv = SMIME_write_PKCS7(out, p7, in, flags);
} else if (outformat == FORMAT_PEM) {
rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags);
} else if (outformat == FORMAT_ASN1) {
rv = i2d_PKCS7_bio_stream(out, p7, in, flags);
} else {
BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
goto end;
}
if (rv == 0) {
BIO_printf(bio_err, "Error writing output\n");
ret = 3;
goto end;
}
}
ret = 0;
end:
if (ret)
ERR_print_errors(bio_err);
sk_X509_pop_free(encerts, X509_free);
sk_X509_pop_free(other, X509_free);
X509_VERIFY_PARAM_free(vpm);
sk_OPENSSL_STRING_free(sksigners);
sk_OPENSSL_STRING_free(skkeys);
X509_STORE_free(store);
X509_free(cert);
X509_free(recip);
X509_free(signer);
EVP_PKEY_free(key);
EVP_MD_free(sign_md);
EVP_CIPHER_free(cipher);
PKCS7_free(p7);
release_engine(e);
BIO_free(in);
BIO_free(indata);
BIO_free_all(out);
OPENSSL_free(passin);
NCONF_free(conf);
return ret;
}
static int save_certs(char *signerfile, STACK_OF(X509) *signers)
{
int i;
BIO *tmp;
if (signerfile == NULL)
return 1;
tmp = BIO_new_file(signerfile, "w");
if (tmp == NULL)
return 0;
for (i = 0; i < sk_X509_num(signers); i++)
PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
BIO_free(tmp);
return 1;
}
/* Minimal callback just to output policy info (if any) */
static int smime_cb(int ok, X509_STORE_CTX *ctx)
{
int error;
error = X509_STORE_CTX_get_error(ctx);
if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
&& ((error != X509_V_OK) || (ok != 2)))
return ok;
policies_print(ctx);
return ok;
}
diff --git a/crypto/openssl/apps/speed.c b/crypto/openssl/apps/speed.c
index d8e2c70e6128..bafcacf7775e 100644
--- a/crypto/openssl/apps/speed.c
+++ b/crypto/openssl/apps/speed.c
@@ -1,3754 +1,3967 @@
/*
- * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 PKEY_SECONDS 10
#define RSA_SECONDS PKEY_SECONDS
#define DSA_SECONDS PKEY_SECONDS
#define ECDSA_SECONDS PKEY_SECONDS
#define ECDH_SECONDS PKEY_SECONDS
#define EdDSA_SECONDS PKEY_SECONDS
#define SM2_SECONDS PKEY_SECONDS
#define FFDH_SECONDS PKEY_SECONDS
/* We need to use some deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "apps.h"
#include "progs.h"
#include "internal/numbers.h"
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/core_names.h>
#include <openssl/async.h>
#if !defined(OPENSSL_SYS_MSDOS)
# include <unistd.h>
#endif
#if defined(__TANDEM)
# if defined(OPENSSL_TANDEM_FLOSS)
# include <floss.h(floss_fork)>
# endif
#endif
#if defined(_WIN32)
# include <windows.h>
#endif
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include "./testrsa.h"
#ifndef OPENSSL_NO_DH
# include <openssl/dh.h>
#endif
#include <openssl/x509.h>
#include <openssl/dsa.h>
#include "./testdsa.h"
#include <openssl/modes.h>
#ifndef HAVE_FORK
# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VXWORKS)
# define HAVE_FORK 0
# else
# define HAVE_FORK 1
# include <sys/wait.h>
# 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
#define MAX_FFDH_SIZE 1024
#ifndef RSA_DEFAULT_PRIME_NUM
# define RSA_DEFAULT_PRIME_NUM 2
#endif
typedef struct openssl_speed_sec_st {
int sym;
int rsa;
int dsa;
int ecdsa;
int ecdh;
int eddsa;
int sm2;
int ffdh;
} openssl_speed_sec_t;
static volatile int run = 0;
static int mr = 0; /* machine-readeable output format to merge fork results */
static int usertime = 1;
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
};
#define SIZE_NUM OSSL_NELEM(lengths_list)
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
# error "SIGALRM not defined and the platform is not Windows"
#endif
static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
const openssl_speed_sec_t *seconds);
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;
}
#define opt_found(value, pairs, result)\
opt_found(value, result, pairs, OSSL_NELEM(pairs))
typedef enum OPTION_choice {
OPT_COMMON,
OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM,
OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC
} OPTION_CHOICE;
const OPTIONS speed_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [algorithm...]\n"},
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"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
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
OPT_SECTION("Selection"),
{"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"},
{"hmac", OPT_HMAC, 's', "HMAC using EVP-named digest"},
{"cmac", OPT_CMAC, 's', "CMAC using EVP-named cipher"},
{"decrypt", OPT_DECRYPT, '-',
"Time decryption instead of encryption (only EVP)"},
{"aead", OPT_AEAD, '-',
"Benchmark EVP-named AEAD cipher in TLS-like sequence"},
OPT_SECTION("Timing"),
{"elapsed", OPT_ELAPSED, '-',
"Use wall-clock time instead of CPU user time as divisor"},
{"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"},
OPT_R_OPTIONS,
OPT_PROV_OPTIONS,
OPT_PARAMETERS(),
{"algorithm", 0, 0, "Algorithm(s) to test (optional; otherwise tests all)"},
{NULL}
};
enum {
D_MD2, D_MDC2, D_MD4, D_MD5, D_SHA1, D_RMD160,
D_SHA256, D_SHA512, D_WHIRLPOOL, D_HMAC,
D_CBC_DES, D_EDE3_DES, D_RC4, D_CBC_IDEA, D_CBC_SEED,
D_CBC_RC2, D_CBC_RC5, D_CBC_BF, D_CBC_CAST,
D_CBC_128_AES, D_CBC_192_AES, D_CBC_256_AES,
D_CBC_128_CML, D_CBC_192_CML, D_CBC_256_CML,
D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, ALGOR_NUM
};
/* name of algorithms to test. MUST BE KEEP IN SYNC with above enum ! */
static const char *names[ALGOR_NUM] = {
"md2", "mdc2", "md4", "md5", "sha1", "rmd160",
"sha256", "sha512", "whirlpool", "hmac(md5)",
"des-cbc", "des-ede3", "rc4", "idea-cbc", "seed-cbc",
"rc2-cbc", "rc5-cbc", "blowfish", "cast-cbc",
"aes-128-cbc", "aes-192-cbc", "aes-256-cbc",
"camellia-128-cbc", "camellia-192-cbc", "camellia-256-cbc",
"evp", "ghash", "rand", "cmac"
};
/* list of configured algorithm (remaining), with some few alias */
static const OPT_PAIR doit_choices[] = {
{"md2", D_MD2},
{"mdc2", D_MDC2},
{"md4", D_MD4},
{"md5", D_MD5},
{"hmac", D_HMAC},
{"sha1", D_SHA1},
{"sha256", D_SHA256},
{"sha512", D_SHA512},
{"whirlpool", D_WHIRLPOOL},
{"ripemd", D_RMD160},
{"rmd160", D_RMD160},
{"ripemd160", D_RMD160},
{"rc4", D_RC4},
{"des-cbc", D_CBC_DES},
{"des-ede3", D_EDE3_DES},
{"aes-128-cbc", D_CBC_128_AES},
{"aes-192-cbc", D_CBC_192_AES},
{"aes-256-cbc", D_CBC_256_AES},
{"camellia-128-cbc", D_CBC_128_CML},
{"camellia-192-cbc", D_CBC_192_CML},
{"camellia-256-cbc", D_CBC_256_CML},
{"rc2-cbc", D_CBC_RC2},
{"rc2", D_CBC_RC2},
{"rc5-cbc", D_CBC_RC5},
{"rc5", D_CBC_RC5},
{"idea-cbc", D_CBC_IDEA},
{"idea", D_CBC_IDEA},
{"seed-cbc", D_CBC_SEED},
{"seed", D_CBC_SEED},
{"bf-cbc", D_CBC_BF},
{"blowfish", D_CBC_BF},
{"bf", D_CBC_BF},
{"cast-cbc", D_CBC_CAST},
{"cast", D_CBC_CAST},
{"cast5", D_CBC_CAST},
{"ghash", D_GHASH},
{"rand", D_RAND}
};
static double results[ALGOR_NUM][SIZE_NUM];
enum { R_DSA_512, R_DSA_1024, R_DSA_2048, DSA_NUM };
static const OPT_PAIR dsa_choices[DSA_NUM] = {
{"dsa512", R_DSA_512},
{"dsa1024", R_DSA_1024},
{"dsa2048", R_DSA_2048}
};
static double dsa_results[DSA_NUM][2]; /* 2 ops: sign then verify */
enum {
R_RSA_512, R_RSA_1024, R_RSA_2048, R_RSA_3072, R_RSA_4096, R_RSA_7680,
R_RSA_15360, RSA_NUM
};
static const OPT_PAIR rsa_choices[RSA_NUM] = {
{"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}
};
static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */
#ifndef OPENSSL_NO_DH
enum ff_params_t {
R_FFDH_2048, R_FFDH_3072, R_FFDH_4096, R_FFDH_6144, R_FFDH_8192, FFDH_NUM
};
static const OPT_PAIR ffdh_choices[FFDH_NUM] = {
{"ffdh2048", R_FFDH_2048},
{"ffdh3072", R_FFDH_3072},
{"ffdh4096", R_FFDH_4096},
{"ffdh6144", R_FFDH_6144},
{"ffdh8192", R_FFDH_8192},
};
static double ffdh_results[FFDH_NUM][1]; /* 1 op: derivation */
#endif /* OPENSSL_NO_DH */
enum ec_curves_t {
R_EC_P160, R_EC_P192, R_EC_P224, R_EC_P256, R_EC_P384, R_EC_P521,
#ifndef OPENSSL_NO_EC2M
R_EC_K163, R_EC_K233, R_EC_K283, R_EC_K409, R_EC_K571,
R_EC_B163, R_EC_B233, R_EC_B283, R_EC_B409, R_EC_B571,
#endif
R_EC_BRP256R1, R_EC_BRP256T1, R_EC_BRP384R1, R_EC_BRP384T1,
R_EC_BRP512R1, R_EC_BRP512T1, ECDSA_NUM
};
/* list of ecdsa curves */
static const OPT_PAIR ecdsa_choices[ECDSA_NUM] = {
{"ecdsap160", R_EC_P160},
{"ecdsap192", R_EC_P192},
{"ecdsap224", R_EC_P224},
{"ecdsap256", R_EC_P256},
{"ecdsap384", R_EC_P384},
{"ecdsap521", R_EC_P521},
#ifndef OPENSSL_NO_EC2M
{"ecdsak163", R_EC_K163},
{"ecdsak233", R_EC_K233},
{"ecdsak283", R_EC_K283},
{"ecdsak409", R_EC_K409},
{"ecdsak571", R_EC_K571},
{"ecdsab163", R_EC_B163},
{"ecdsab233", R_EC_B233},
{"ecdsab283", R_EC_B283},
{"ecdsab409", R_EC_B409},
{"ecdsab571", R_EC_B571},
#endif
{"ecdsabrp256r1", R_EC_BRP256R1},
{"ecdsabrp256t1", R_EC_BRP256T1},
{"ecdsabrp384r1", R_EC_BRP384R1},
{"ecdsabrp384t1", R_EC_BRP384T1},
{"ecdsabrp512r1", R_EC_BRP512R1},
{"ecdsabrp512t1", R_EC_BRP512T1}
};
enum { R_EC_X25519 = ECDSA_NUM, R_EC_X448, EC_NUM };
/* list of ecdh curves, extension of |ecdsa_choices| list above */
static const OPT_PAIR ecdh_choices[EC_NUM] = {
{"ecdhp160", R_EC_P160},
{"ecdhp192", R_EC_P192},
{"ecdhp224", R_EC_P224},
{"ecdhp256", R_EC_P256},
{"ecdhp384", R_EC_P384},
{"ecdhp521", R_EC_P521},
#ifndef OPENSSL_NO_EC2M
{"ecdhk163", R_EC_K163},
{"ecdhk233", R_EC_K233},
{"ecdhk283", R_EC_K283},
{"ecdhk409", R_EC_K409},
{"ecdhk571", R_EC_K571},
{"ecdhb163", R_EC_B163},
{"ecdhb233", R_EC_B233},
{"ecdhb283", R_EC_B283},
{"ecdhb409", R_EC_B409},
{"ecdhb571", R_EC_B571},
#endif
{"ecdhbrp256r1", R_EC_BRP256R1},
{"ecdhbrp256t1", R_EC_BRP256T1},
{"ecdhbrp384r1", R_EC_BRP384R1},
{"ecdhbrp384t1", R_EC_BRP384T1},
{"ecdhbrp512r1", R_EC_BRP512R1},
{"ecdhbrp512t1", R_EC_BRP512T1},
{"ecdhx25519", R_EC_X25519},
{"ecdhx448", R_EC_X448}
};
static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */
static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */
enum { R_EC_Ed25519, R_EC_Ed448, EdDSA_NUM };
static const OPT_PAIR eddsa_choices[EdDSA_NUM] = {
{"ed25519", R_EC_Ed25519},
{"ed448", R_EC_Ed448}
};
static double eddsa_results[EdDSA_NUM][2]; /* 2 ops: sign then verify */
#ifndef OPENSSL_NO_SM2
enum { R_EC_CURVESM2, SM2_NUM };
static const OPT_PAIR sm2_choices[SM2_NUM] = {
{"curveSM2", R_EC_CURVESM2}
};
# define SM2_ID "TLSv1.3+GM+Cipher+Suite"
# define SM2_ID_LEN sizeof("TLSv1.3+GM+Cipher+Suite") - 1
static double sm2_results[SM2_NUM][2]; /* 2 ops: sign then verify */
#endif /* OPENSSL_NO_SM2 */
#define COND(unused_cond) (run && count < INT_MAX)
#define COUNT(d) (count)
+#define TAG_LEN 16
+
+static unsigned int mode_op; /* AE Mode of operation */
+static unsigned int aead = 0; /* AEAD flag */
+static unsigned char aead_iv[12]; /* For AEAD modes */
+static unsigned char aad[EVP_AEAD_TLS1_AAD_LEN] = { 0xcc };
+static int aead_ivlen = sizeof(aead_iv);
+
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 char tag[TAG_LEN];
size_t buflen;
size_t sigsize;
EVP_PKEY_CTX *rsa_sign_ctx[RSA_NUM];
EVP_PKEY_CTX *rsa_verify_ctx[RSA_NUM];
EVP_PKEY_CTX *dsa_sign_ctx[DSA_NUM];
EVP_PKEY_CTX *dsa_verify_ctx[DSA_NUM];
EVP_PKEY_CTX *ecdsa_sign_ctx[ECDSA_NUM];
EVP_PKEY_CTX *ecdsa_verify_ctx[ECDSA_NUM];
EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
EVP_MD_CTX *eddsa_ctx[EdDSA_NUM];
EVP_MD_CTX *eddsa_ctx2[EdDSA_NUM];
#ifndef OPENSSL_NO_SM2
EVP_MD_CTX *sm2_ctx[SM2_NUM];
EVP_MD_CTX *sm2_vfy_ctx[SM2_NUM];
EVP_PKEY *sm2_pkey[SM2_NUM];
#endif
unsigned char *secret_a;
unsigned char *secret_b;
size_t outlen[EC_NUM];
#ifndef OPENSSL_NO_DH
EVP_PKEY_CTX *ffdh_ctx[FFDH_NUM];
unsigned char *secret_ff_a;
unsigned char *secret_ff_b;
#endif
EVP_CIPHER_CTX *ctx;
EVP_MAC_CTX *mctx;
} 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][SIZE_NUM];
static char *evp_mac_mdname = "md5";
static char *evp_hmac_name = NULL;
static const char *evp_md_name = NULL;
static char *evp_mac_ciphername = "aes-128-cbc";
static char *evp_cmac_name = NULL;
static int have_md(const char *name)
{
int ret = 0;
EVP_MD *md = NULL;
if (opt_md_silent(name, &md)) {
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (ctx != NULL && EVP_DigestInit(ctx, md) > 0)
ret = 1;
EVP_MD_CTX_free(ctx);
EVP_MD_free(md);
}
return ret;
}
static int have_cipher(const char *name)
{
int ret = 0;
EVP_CIPHER *cipher = NULL;
if (opt_cipher_silent(name, &cipher)) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (ctx != NULL
&& EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1) > 0)
ret = 1;
EVP_CIPHER_CTX_free(ctx);
EVP_CIPHER_free(cipher);
}
return ret;
}
static int EVP_Digest_loop(const char *mdname, int algindex, void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char digest[EVP_MAX_MD_SIZE];
int count;
EVP_MD *md = NULL;
if (!opt_md_silent(mdname, &md))
return -1;
for (count = 0; COND(c[algindex][testnum]); count++) {
if (!EVP_Digest(buf, (size_t)lengths[testnum], digest, NULL, md,
NULL)) {
count = -1;
break;
}
}
EVP_MD_free(md);
return count;
}
static int EVP_Digest_md_loop(void *args)
{
return EVP_Digest_loop(evp_md_name, D_EVP, args);
}
static int EVP_Digest_MD2_loop(void *args)
{
return EVP_Digest_loop("md2", D_MD2, args);
}
static int EVP_Digest_MDC2_loop(void *args)
{
return EVP_Digest_loop("mdc2", D_MDC2, args);
}
static int EVP_Digest_MD4_loop(void *args)
{
return EVP_Digest_loop("md4", D_MD4, args);
}
static int MD5_loop(void *args)
{
return EVP_Digest_loop("md5", D_MD5, args);
}
static int EVP_MAC_loop(int algindex, void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_MAC_CTX *mctx = tempargs->mctx;
unsigned char mac[EVP_MAX_MD_SIZE];
int count;
for (count = 0; COND(c[algindex][testnum]); count++) {
size_t outl;
if (!EVP_MAC_init(mctx, NULL, 0, NULL)
|| !EVP_MAC_update(mctx, buf, lengths[testnum])
|| !EVP_MAC_final(mctx, mac, &outl, sizeof(mac)))
return -1;
}
return count;
}
static int HMAC_loop(void *args)
{
return EVP_MAC_loop(D_HMAC, args);
}
static int CMAC_loop(void *args)
{
return EVP_MAC_loop(D_EVP_CMAC, args);
}
static int SHA1_loop(void *args)
{
return EVP_Digest_loop("sha1", D_SHA1, args);
}
static int SHA256_loop(void *args)
{
return EVP_Digest_loop("sha256", D_SHA256, args);
}
static int SHA512_loop(void *args)
{
return EVP_Digest_loop("sha512", D_SHA512, args);
}
static int WHIRLPOOL_loop(void *args)
{
return EVP_Digest_loop("whirlpool", D_WHIRLPOOL, args);
}
static int EVP_Digest_RMD160_loop(void *args)
{
return EVP_Digest_loop("ripemd160", D_RMD160, args);
}
static int algindex;
static int EVP_Cipher_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
int count;
if (tempargs->ctx == NULL)
return -1;
for (count = 0; COND(c[algindex][testnum]); count++)
if (EVP_Cipher(tempargs->ctx, buf, buf, (size_t)lengths[testnum]) <= 0)
return -1;
return count;
}
static int GHASH_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_MAC_CTX *mctx = tempargs->mctx;
int count;
/* just do the update in the loop to be comparable with 1.1.1 */
for (count = 0; COND(c[D_GHASH][testnum]); count++) {
if (!EVP_MAC_update(mctx, buf, lengths[testnum]))
return -1;
}
return count;
}
#define MAX_BLOCK_SIZE 128
static unsigned char iv[2 * MAX_BLOCK_SIZE / 8];
static EVP_CIPHER_CTX *init_evp_cipher_ctx(const char *ciphername,
const unsigned char *key,
int keylen)
{
EVP_CIPHER_CTX *ctx = NULL;
EVP_CIPHER *cipher = NULL;
if (!opt_cipher_silent(ciphername, &cipher))
return NULL;
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto end;
if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1)) {
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;
goto end;
}
if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0) {
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;
goto end;
}
if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1)) {
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;
goto end;
}
end:
EVP_CIPHER_free(cipher);
return ctx;
}
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 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;
- unsigned char faketag[16] = { 0xcc };
if (decrypt) {
- if (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) {
- (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(faketag), faketag);
- }
for (count = 0; COND(c[D_EVP][testnum]); 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(c[D_EVP][testnum]); 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;
}
/*
+ * 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...
* 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)
+static int EVP_Update_loop_aead_enc(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
+ unsigned char *key = tempargs->key;
EVP_CIPHER_CTX *ctx = tempargs->ctx;
- int outl, count;
- unsigned char tag[12];
-
- if (decrypt) {
- for (count = 0; COND(c[D_EVP][testnum]); count++) {
- (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag),
- tag);
- /* reset iv */
- (void)EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
- /* counter is reset on every update */
- (void)EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ int outl, count, realcount = 0;
+
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
+ /* Set length of iv (Doesn't apply to SIV mode) */
+ if (mode_op != EVP_CIPH_SIV_MODE) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
+ aead_ivlen, NULL)) {
+ BIO_printf(bio_err, "\nFailed to set iv length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
}
- } else {
- for (count = 0; COND(c[D_EVP][testnum]); count++) {
- /* restore iv length field */
- (void)EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
- /* counter is reset on every update */
- (void)EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ /* Set tag_len (Not for GCM/SIV at encryption stage) */
+ if (mode_op != EVP_CIPH_GCM_MODE
+ && mode_op != EVP_CIPH_SIV_MODE) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ TAG_LEN, NULL)) {
+ BIO_printf(bio_err, "\nFailed to set tag length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, aead_iv, -1)) {
+ BIO_printf(bio_err, "\nFailed to set key and iv\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ /* Set total length of input. Only required for CCM */
+ if (mode_op == EVP_CIPH_CCM_MODE) {
+ if (!EVP_EncryptUpdate(ctx, NULL, &outl,
+ NULL, lengths[testnum])) {
+ BIO_printf(bio_err, "\nCouldn't set input text length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
}
+ if (aead) {
+ if (!EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad))) {
+ BIO_printf(bio_err, "\nCouldn't insert AAD when encrypting\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ if (!EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum])) {
+ BIO_printf(bio_err, "\nFailed to encrypt the data\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ if (EVP_EncryptFinal_ex(ctx, buf, &outl))
+ realcount++;
}
- if (decrypt)
- (void)EVP_DecryptFinal_ex(ctx, buf, &outl);
- else
- (void)EVP_EncryptFinal_ex(ctx, buf, &outl);
- return count;
+ return realcount;
}
/*
* 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...
+ * CCM does not support streaming. For the purpose of performance measurement,
+ * each message is decrypted using the same (key,iv)-pair. Do not use this
+ * code in your application.
+ * For decryption, we will use buf2 to preserve the input text in buf.
*/
-static int EVP_Update_loop_aead(void *args)
+static int EVP_Update_loop_aead_dec(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
+ unsigned char *outbuf = tempargs->buf2;
+ unsigned char *key = tempargs->key;
+ unsigned char tag[TAG_LEN];
EVP_CIPHER_CTX *ctx = tempargs->ctx;
- int outl, count;
- unsigned char aad[13] = { 0xcc };
- unsigned char faketag[16] = { 0xcc };
+ int outl, count, realcount = 0;
+
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
+ /* Set the length of iv (Doesn't apply to SIV mode) */
+ if (mode_op != EVP_CIPH_SIV_MODE) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
+ aead_ivlen, NULL)) {
+ BIO_printf(bio_err, "\nFailed to set iv length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
- if (decrypt) {
- for (count = 0; COND(c[D_EVP][testnum]); count++) {
- (void)EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
- (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
- sizeof(faketag), faketag);
- (void)EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
- (void)EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
- (void)EVP_DecryptFinal_ex(ctx, buf + outl, &outl);
+ /* Set the tag length (Doesn't apply to SIV mode) */
+ if (mode_op != EVP_CIPH_SIV_MODE
+ && mode_op != EVP_CIPH_GCM_MODE) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ TAG_LEN, NULL)) {
+ BIO_printf(bio_err, "\nFailed to set tag length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
}
- } else {
- for (count = 0; COND(c[D_EVP][testnum]); count++) {
- (void)EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);
- (void)EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
- (void)EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
- (void)EVP_EncryptFinal_ex(ctx, buf + outl, &outl);
+ if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, aead_iv, -1)) {
+ BIO_printf(bio_err, "\nFailed to set key and iv\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ /* Set iv before decryption (Doesn't apply to SIV mode) */
+ if (mode_op != EVP_CIPH_SIV_MODE) {
+ if (!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, aead_iv)) {
+ BIO_printf(bio_err, "\nFailed to set iv\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ memcpy(tag, tempargs->tag, TAG_LEN);
+
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ TAG_LEN, tag)) {
+ BIO_printf(bio_err, "\nFailed to set tag\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ /* Set the total length of cipher text. Only required for CCM */
+ if (mode_op == EVP_CIPH_CCM_MODE) {
+ if (!EVP_DecryptUpdate(ctx, NULL, &outl,
+ NULL, lengths[testnum])) {
+ BIO_printf(bio_err, "\nCouldn't set cipher text length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ if (aead) {
+ if (!EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad))) {
+ BIO_printf(bio_err, "\nCouldn't insert AAD when decrypting\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ if (!EVP_DecryptUpdate(ctx, outbuf, &outl, buf, lengths[testnum])) {
+ BIO_printf(bio_err, "\nFailed to decrypt the data\n");
+ ERR_print_errors(bio_err);
+ exit(1);
}
+ if (EVP_DecryptFinal_ex(ctx, outbuf, &outl))
+ realcount++;
}
- return count;
+ return realcount;
}
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;
size_t *rsa_num = &tempargs->sigsize;
EVP_PKEY_CTX **rsa_sign_ctx = tempargs->rsa_sign_ctx;
int ret, count;
for (count = 0; COND(rsa_c[testnum][0]); count++) {
*rsa_num = tempargs->buflen;
ret = EVP_PKEY_sign(rsa_sign_ctx[testnum], buf2, rsa_num, buf, 36);
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;
size_t rsa_num = tempargs->sigsize;
EVP_PKEY_CTX **rsa_verify_ctx = tempargs->rsa_verify_ctx;
int ret, count;
for (count = 0; COND(rsa_c[testnum][1]); count++) {
ret = EVP_PKEY_verify(rsa_verify_ctx[testnum], buf2, rsa_num, buf, 36);
if (ret <= 0) {
BIO_printf(bio_err, "RSA verify failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
#ifndef OPENSSL_NO_DH
static long ffdh_c[FFDH_NUM][1];
static int FFDH_derive_key_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
EVP_PKEY_CTX *ffdh_ctx = tempargs->ffdh_ctx[testnum];
unsigned char *derived_secret = tempargs->secret_ff_a;
int count;
for (count = 0; COND(ffdh_c[testnum][0]); count++) {
/* outlen can be overwritten with a too small value (no padding used) */
size_t outlen = MAX_FFDH_SIZE;
EVP_PKEY_derive(ffdh_ctx, derived_secret, &outlen);
}
return count;
}
#endif /* OPENSSL_NO_DH */
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;
size_t *dsa_num = &tempargs->sigsize;
EVP_PKEY_CTX **dsa_sign_ctx = tempargs->dsa_sign_ctx;
int ret, count;
for (count = 0; COND(dsa_c[testnum][0]); count++) {
*dsa_num = tempargs->buflen;
ret = EVP_PKEY_sign(dsa_sign_ctx[testnum], buf2, dsa_num, buf, 20);
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;
size_t dsa_num = tempargs->sigsize;
EVP_PKEY_CTX **dsa_verify_ctx = tempargs->dsa_verify_ctx;
int ret, count;
for (count = 0; COND(dsa_c[testnum][1]); count++) {
ret = EVP_PKEY_verify(dsa_verify_ctx[testnum], buf2, dsa_num, buf, 20);
if (ret <= 0) {
BIO_printf(bio_err, "DSA verify failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
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;
unsigned char *buf2 = tempargs->buf2;
size_t *ecdsa_num = &tempargs->sigsize;
EVP_PKEY_CTX **ecdsa_sign_ctx = tempargs->ecdsa_sign_ctx;
int ret, count;
for (count = 0; COND(ecdsa_c[testnum][0]); count++) {
*ecdsa_num = tempargs->buflen;
ret = EVP_PKEY_sign(ecdsa_sign_ctx[testnum], buf2, ecdsa_num, buf, 20);
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;
unsigned char *buf2 = tempargs->buf2;
size_t ecdsa_num = tempargs->sigsize;
EVP_PKEY_CTX **ecdsa_verify_ctx = tempargs->ecdsa_verify_ctx;
int ret, count;
for (count = 0; COND(ecdsa_c[testnum][1]); count++) {
ret = EVP_PKEY_verify(ecdsa_verify_ctx[testnum], buf2, ecdsa_num,
buf, 20);
if (ret <= 0) {
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_DigestSignInit(edctx[testnum], NULL, NULL, NULL, NULL);
if (ret == 0) {
BIO_printf(bio_err, "EdDSA sign init failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
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_ctx2;
unsigned char *eddsasig = tempargs->buf2;
size_t eddsasigsize = tempargs->sigsize;
int ret, count;
for (count = 0; COND(eddsa_c[testnum][1]); count++) {
ret = EVP_DigestVerifyInit(edctx[testnum], NULL, NULL, NULL, NULL);
if (ret == 0) {
BIO_printf(bio_err, "EdDSA verify init failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
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;
}
#ifndef OPENSSL_NO_SM2
static long sm2_c[SM2_NUM][2];
static int SM2_sign_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_MD_CTX **sm2ctx = tempargs->sm2_ctx;
unsigned char *sm2sig = tempargs->buf2;
size_t sm2sigsize;
int ret, count;
EVP_PKEY **sm2_pkey = tempargs->sm2_pkey;
const size_t max_size = EVP_PKEY_get_size(sm2_pkey[testnum]);
for (count = 0; COND(sm2_c[testnum][0]); count++) {
sm2sigsize = max_size;
if (!EVP_DigestSignInit(sm2ctx[testnum], NULL, EVP_sm3(),
NULL, sm2_pkey[testnum])) {
BIO_printf(bio_err, "SM2 init sign failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
ret = EVP_DigestSign(sm2ctx[testnum], sm2sig, &sm2sigsize,
buf, 20);
if (ret == 0) {
BIO_printf(bio_err, "SM2 sign failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
/* update the latest returned size and always use the fixed buffer size */
tempargs->sigsize = sm2sigsize;
}
return count;
}
static int SM2_verify_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_MD_CTX **sm2ctx = tempargs->sm2_vfy_ctx;
unsigned char *sm2sig = tempargs->buf2;
size_t sm2sigsize = tempargs->sigsize;
int ret, count;
EVP_PKEY **sm2_pkey = tempargs->sm2_pkey;
for (count = 0; COND(sm2_c[testnum][1]); count++) {
if (!EVP_DigestVerifyInit(sm2ctx[testnum], NULL, EVP_sm3(),
NULL, sm2_pkey[testnum])) {
BIO_printf(bio_err, "SM2 verify init failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
ret = EVP_DigestVerify(sm2ctx[testnum], sm2sig, sm2sigsize,
buf, 20);
if (ret != 1) {
BIO_printf(bio_err, "SM2 verify failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
#endif /* OPENSSL_NO_SM2 */
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;
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;
}
typedef struct ec_curve_st {
const char *name;
unsigned int nid;
unsigned int bits;
size_t sigsize; /* only used for EdDSA curves */
} EC_CURVE;
static EVP_PKEY *get_ecdsa(const EC_CURVE *curve)
{
EVP_PKEY_CTX *kctx = NULL;
EVP_PKEY *key = NULL;
/* 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(curve->nid, NULL);
if (kctx == NULL) {
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();
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_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM
|| ERR_GET_REASON(error) == ERR_R_UNSUPPORTED))
ERR_get_error(); /* pop error from queue */
if (ERR_peek_error()) {
BIO_printf(bio_err,
"Unhandled error in the error queue during EC key setup.\n");
ERR_print_errors(bio_err);
return NULL;
}
/* Create the context for parameter generation */
if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL
|| EVP_PKEY_paramgen_init(pctx) <= 0
|| EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
curve->nid) <= 0
|| EVP_PKEY_paramgen(pctx, &params) <= 0) {
BIO_printf(bio_err, "EC params init failure.\n");
ERR_print_errors(bio_err);
EVP_PKEY_CTX_free(pctx);
return NULL;
}
EVP_PKEY_CTX_free(pctx);
/* Create the context for the key generation */
kctx = EVP_PKEY_CTX_new(params, NULL);
EVP_PKEY_free(params);
}
if (kctx == NULL
|| EVP_PKEY_keygen_init(kctx) <= 0
|| EVP_PKEY_keygen(kctx, &key) <= 0) {
BIO_printf(bio_err, "EC key generation failure.\n");
ERR_print_errors(bio_err);
key = NULL;
}
EVP_PKEY_CTX_free(kctx);
return key;
}
#define stop_it(do_it, test_num)\
memset(do_it + test_num, 0, OSSL_NELEM(do_it) - test_num);
int speed_main(int argc, char **argv)
{
ENGINE *e = NULL;
loopargs_t *loopargs = NULL;
const char *prog;
const char *engine_id = NULL;
EVP_CIPHER *evp_cipher = NULL;
EVP_MAC *mac = NULL;
double d = 0.0;
OPTION_CHOICE o;
int async_init = 0, multiblock = 0, pr_header = 0;
uint8_t doit[ALGOR_NUM] = { 0 };
- int ret = 1, misalign = 0, lengths_single = 0, aead = 0;
+ int ret = 1, misalign = 0, lengths_single = 0;
long count = 0;
unsigned int size_num = SIZE_NUM;
unsigned int i, k, loopargs_len = 0, async_jobs = 0;
- int keylen;
+ int keylen = 0;
int buflen;
BIGNUM *bn = NULL;
EVP_PKEY_CTX *genctx = NULL;
#ifndef NO_FORK
int multi = 0;
#endif
long op_count = 1;
openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS,
ECDSA_SECONDS, ECDH_SECONDS,
EdDSA_SECONDS, SM2_SECONDS,
FFDH_SECONDS };
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
};
static const unsigned char deskey[] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, /* key1 */
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, /* key2 */
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 /* key3 */
};
static const struct {
const unsigned char *data;
unsigned int length;
unsigned int bits;
} rsa_keys[] = {
{ test512, sizeof(test512), 512 },
{ test1024, sizeof(test1024), 1024 },
{ test2048, sizeof(test2048), 2048 },
{ test3072, sizeof(test3072), 3072 },
{ test4096, sizeof(test4096), 4096 },
{ test7680, sizeof(test7680), 7680 },
{ test15360, sizeof(test15360), 15360 }
};
uint8_t rsa_doit[RSA_NUM] = { 0 };
int primes = RSA_DEFAULT_PRIME_NUM;
#ifndef OPENSSL_NO_DH
typedef struct ffdh_params_st {
const char *name;
unsigned int nid;
unsigned int bits;
} FFDH_PARAMS;
static const FFDH_PARAMS ffdh_params[FFDH_NUM] = {
{"ffdh2048", NID_ffdhe2048, 2048},
{"ffdh3072", NID_ffdhe3072, 3072},
{"ffdh4096", NID_ffdhe4096, 4096},
{"ffdh6144", NID_ffdhe6144, 6144},
{"ffdh8192", NID_ffdhe8192, 8192}
};
uint8_t ffdh_doit[FFDH_NUM] = { 0 };
#endif /* OPENSSL_NO_DH */
static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
uint8_t dsa_doit[DSA_NUM] = { 0 };
/*
* 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| and |ecdsa_choices|
* lists accordingly.
*/
static const EC_CURVE ec_curves[EC_NUM] = {
/* Prime Curves */
{"secp160r1", NID_secp160r1, 160},
{"nistp192", NID_X9_62_prime192v1, 192},
{"nistp224", NID_secp224r1, 224},
{"nistp256", NID_X9_62_prime256v1, 256},
{"nistp384", NID_secp384r1, 384},
{"nistp521", NID_secp521r1, 521},
#ifndef OPENSSL_NO_EC2M
/* Binary Curves */
{"nistk163", NID_sect163k1, 163},
{"nistk233", NID_sect233k1, 233},
{"nistk283", NID_sect283k1, 283},
{"nistk409", NID_sect409k1, 409},
{"nistk571", NID_sect571k1, 571},
{"nistb163", NID_sect163r2, 163},
{"nistb233", NID_sect233r1, 233},
{"nistb283", NID_sect283r1, 283},
{"nistb409", NID_sect409r1, 409},
{"nistb571", NID_sect571r1, 571},
#endif
{"brainpoolP256r1", NID_brainpoolP256r1, 256},
{"brainpoolP256t1", NID_brainpoolP256t1, 256},
{"brainpoolP384r1", NID_brainpoolP384r1, 384},
{"brainpoolP384t1", NID_brainpoolP384t1, 384},
{"brainpoolP512r1", NID_brainpoolP512r1, 512},
{"brainpoolP512t1", NID_brainpoolP512t1, 512},
/* Other and ECDH only ones */
{"X25519", NID_X25519, 253},
{"X448", NID_X448, 448}
};
static const EC_CURVE ed_curves[EdDSA_NUM] = {
/* EdDSA */
{"Ed25519", NID_ED25519, 253, 64},
{"Ed448", NID_ED448, 456, 114}
};
#ifndef OPENSSL_NO_SM2
static const EC_CURVE sm2_curves[SM2_NUM] = {
/* SM2 */
{"CurveSM2", NID_sm2, 256}
};
uint8_t sm2_doit[SM2_NUM] = { 0 };
#endif
uint8_t ecdsa_doit[ECDSA_NUM] = { 0 };
uint8_t ecdh_doit[EC_NUM] = { 0 };
uint8_t eddsa_doit[EdDSA_NUM] = { 0 };
/* checks declarated curves against choices list. */
OPENSSL_assert(ed_curves[EdDSA_NUM - 1].nid == NID_ED448);
OPENSSL_assert(strcmp(eddsa_choices[EdDSA_NUM - 1].name, "ed448") == 0);
OPENSSL_assert(ec_curves[EC_NUM - 1].nid == NID_X448);
OPENSSL_assert(strcmp(ecdh_choices[EC_NUM - 1].name, "ecdhx448") == 0);
OPENSSL_assert(ec_curves[ECDSA_NUM - 1].nid == NID_brainpoolP512t1);
OPENSSL_assert(strcmp(ecdsa_choices[ECDSA_NUM - 1].name, "ecdsabrp512t1") == 0);
#ifndef OPENSSL_NO_SM2
OPENSSL_assert(sm2_curves[SM2_NUM - 1].nid == NID_sm2);
OPENSSL_assert(strcmp(sm2_choices[SM2_NUM - 1].name, "curveSM2") == 0);
#endif
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:
if (doit[D_EVP]) {
BIO_printf(bio_err, "%s: -evp option cannot be used more than once\n", prog);
goto opterr;
}
ERR_set_mark();
if (!opt_cipher_silent(opt_arg(), &evp_cipher)) {
if (have_md(opt_arg()))
evp_md_name = opt_arg();
}
if (evp_cipher == NULL && evp_md_name == NULL) {
ERR_clear_last_mark();
BIO_printf(bio_err,
"%s: %s is an unknown cipher or digest\n",
prog, opt_arg());
goto end;
}
ERR_pop_to_mark();
doit[D_EVP] = 1;
break;
case OPT_HMAC:
if (!have_md(opt_arg())) {
BIO_printf(bio_err, "%s: %s is an unknown digest\n",
prog, opt_arg());
goto end;
}
evp_mac_mdname = opt_arg();
doit[D_HMAC] = 1;
break;
case OPT_CMAC:
if (!have_cipher(opt_arg())) {
BIO_printf(bio_err, "%s: %s is an unknown cipher\n",
prog, opt_arg());
goto end;
}
evp_mac_ciphername = opt_arg();
doit[D_EVP_CMAC] = 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());
if ((size_t)multi >= SIZE_MAX / sizeof(int)) {
BIO_printf(bio_err, "%s: multi argument too large\n", prog);
return 0;
}
#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:
misalign = opt_int_arg();
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_PROV_CASES:
if (!opt_provider(o))
goto end;
break;
case OPT_PRIMES:
primes = opt_int_arg();
break;
case OPT_SECONDS:
seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa
= seconds.ecdh = seconds.eddsa
= seconds.sm2 = seconds.ffdh = 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;
}
}
/* Remaining arguments are algorithms. */
argc = opt_num_rest();
argv = opt_rest();
if (!app_RAND_load())
goto end;
for (; *argv; argv++) {
const char *algo = *argv;
if (opt_found(algo, doit_choices, &i)) {
doit[i] = 1;
continue;
}
if (strcmp(algo, "des") == 0) {
doit[D_CBC_DES] = doit[D_EDE3_DES] = 1;
continue;
}
if (strcmp(algo, "sha") == 0) {
doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1;
continue;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
if (strcmp(algo, "openssl") == 0) /* just for compatibility */
continue;
#endif
if (strncmp(algo, "rsa", 3) == 0) {
if (algo[3] == '\0') {
memset(rsa_doit, 1, sizeof(rsa_doit));
continue;
}
if (opt_found(algo, rsa_choices, &i)) {
rsa_doit[i] = 1;
continue;
}
}
#ifndef OPENSSL_NO_DH
if (strncmp(algo, "ffdh", 4) == 0) {
if (algo[4] == '\0') {
memset(ffdh_doit, 1, sizeof(ffdh_doit));
continue;
}
if (opt_found(algo, ffdh_choices, &i)) {
ffdh_doit[i] = 2;
continue;
}
}
#endif
if (strncmp(algo, "dsa", 3) == 0) {
if (algo[3] == '\0') {
memset(dsa_doit, 1, sizeof(dsa_doit));
continue;
}
if (opt_found(algo, dsa_choices, &i)) {
dsa_doit[i] = 2;
continue;
}
}
if (strcmp(algo, "aes") == 0) {
doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1;
continue;
}
if (strcmp(algo, "camellia") == 0) {
doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1;
continue;
}
if (strncmp(algo, "ecdsa", 5) == 0) {
if (algo[5] == '\0') {
memset(ecdsa_doit, 1, sizeof(ecdsa_doit));
continue;
}
if (opt_found(algo, ecdsa_choices, &i)) {
ecdsa_doit[i] = 2;
continue;
}
}
if (strncmp(algo, "ecdh", 4) == 0) {
if (algo[4] == '\0') {
memset(ecdh_doit, 1, sizeof(ecdh_doit));
continue;
}
if (opt_found(algo, ecdh_choices, &i)) {
ecdh_doit[i] = 2;
continue;
}
}
if (strcmp(algo, "eddsa") == 0) {
memset(eddsa_doit, 1, sizeof(eddsa_doit));
continue;
}
if (opt_found(algo, eddsa_choices, &i)) {
eddsa_doit[i] = 2;
continue;
}
#ifndef OPENSSL_NO_SM2
if (strcmp(algo, "sm2") == 0) {
memset(sm2_doit, 1, sizeof(sm2_doit));
continue;
}
if (opt_found(algo, sm2_choices, &i)) {
sm2_doit[i] = 2;
continue;
}
#endif
BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo);
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_get_flags(evp_cipher) &
EVP_CIPH_FLAG_AEAD_CIPHER)) {
BIO_printf(bio_err, "%s is not an AEAD cipher\n",
EVP_CIPHER_get0_name(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_get_flags(evp_cipher) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
BIO_printf(bio_err, "%s is not a multi-block capable\n",
EVP_CIPHER_get0_name(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 benchmark */
buflen = 36;
if (INT_MAX - (MAX_MISALIGNMENT + 1) < buflen) {
BIO_printf(bio_err, "Error: buffer size too large\n");
goto end;
}
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;
loopargs[i].buflen = buflen - misalign;
loopargs[i].sigsize = buflen - misalign;
loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a");
loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b");
#ifndef OPENSSL_NO_DH
loopargs[i].secret_ff_a = app_malloc(MAX_FFDH_SIZE, "FFDH secret a");
loopargs[i].secret_ff_b = app_malloc(MAX_FFDH_SIZE, "FFDH 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] && !doit[D_HMAC] && !doit[D_EVP_CMAC]) {
memset(doit, 1, sizeof(doit));
doit[D_EVP] = doit[D_EVP_CMAC] = 0;
ERR_set_mark();
for (i = D_MD2; i <= D_WHIRLPOOL; i++) {
if (!have_md(names[i]))
doit[i] = 0;
}
for (i = D_CBC_DES; i <= D_CBC_256_CML; i++) {
if (!have_cipher(names[i]))
doit[i] = 0;
}
if ((mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC",
app_get0_propq())) != NULL) {
EVP_MAC_free(mac);
mac = NULL;
} else {
doit[D_GHASH] = 0;
}
if ((mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC",
app_get0_propq())) != NULL) {
EVP_MAC_free(mac);
mac = NULL;
} else {
doit[D_HMAC] = 0;
}
ERR_pop_to_mark();
memset(rsa_doit, 1, sizeof(rsa_doit));
#ifndef OPENSSL_NO_DH
memset(ffdh_doit, 1, sizeof(ffdh_doit));
#endif
memset(dsa_doit, 1, sizeof(dsa_doit));
memset(ecdsa_doit, 1, sizeof(ecdsa_doit));
memset(ecdh_doit, 1, sizeof(ecdh_doit));
memset(eddsa_doit, 1, sizeof(eddsa_doit));
#ifndef OPENSSL_NO_SM2
memset(sm2_doit, 1, sizeof(sm2_doit));
#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");
#if SIGALRM > 0
signal(SIGALRM, alarmed);
#endif
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);
if (count < 0)
break;
}
}
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);
if (count < 0)
break;
}
}
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);
if (count < 0)
break;
}
}
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 (count < 0)
break;
}
}
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 (count < 0)
break;
}
}
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 (count < 0)
break;
}
}
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);
if (count < 0)
break;
}
}
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);
if (count < 0)
break;
}
}
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);
if (count < 0)
break;
}
}
if (doit[D_HMAC]) {
static const char hmac_key[] = "This is a key...";
int len = strlen(hmac_key);
+ size_t hmac_name_len = sizeof("hmac()") + strlen(evp_mac_mdname);
OSSL_PARAM params[3];
mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC", app_get0_propq());
if (mac == NULL || evp_mac_mdname == NULL)
goto end;
-
- evp_hmac_name = app_malloc(sizeof("hmac()") + strlen(evp_mac_mdname),
- "HMAC name");
- sprintf(evp_hmac_name, "hmac(%s)", evp_mac_mdname);
+ evp_hmac_name = app_malloc(hmac_name_len, "HMAC name");
+ BIO_snprintf(evp_hmac_name, hmac_name_len, "hmac(%s)", evp_mac_mdname);
names[D_HMAC] = evp_hmac_name;
params[0] =
OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
evp_mac_mdname, 0);
params[1] =
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
(char *)hmac_key, len);
params[2] = OSSL_PARAM_construct_end();
for (i = 0; i < loopargs_len; i++) {
loopargs[i].mctx = EVP_MAC_CTX_new(mac);
if (loopargs[i].mctx == NULL)
goto end;
if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
goto skip_hmac; /* Digest not found */
}
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);
if (count < 0)
break;
}
for (i = 0; i < loopargs_len; i++)
EVP_MAC_CTX_free(loopargs[i].mctx);
EVP_MAC_free(mac);
mac = NULL;
}
skip_hmac:
if (doit[D_CBC_DES]) {
int st = 1;
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].ctx = init_evp_cipher_ctx("des-cbc", deskey,
sizeof(deskey) / 3);
st = loopargs[i].ctx != NULL;
}
algindex = D_CBC_DES;
for (testnum = 0; st && 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, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(D_CBC_DES, testnum, count, d);
}
for (i = 0; i < loopargs_len; i++)
EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
if (doit[D_EDE3_DES]) {
int st = 1;
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].ctx = init_evp_cipher_ctx("des-ede3-cbc", deskey,
sizeof(deskey));
st = loopargs[i].ctx != NULL;
}
algindex = D_EDE3_DES;
for (testnum = 0; st && 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, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(D_EDE3_DES, testnum, count, d);
}
for (i = 0; i < loopargs_len; i++)
EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
for (k = 0; k < 3; k++) {
algindex = D_CBC_128_AES + k;
if (doit[algindex]) {
int st = 1;
keylen = 16 + k * 8;
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
key32, keylen);
st = loopargs[i].ctx != NULL;
}
for (testnum = 0; st && testnum < size_num; testnum++) {
print_message(names[algindex], c[algindex][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(algindex, testnum, count, d);
}
for (i = 0; i < loopargs_len; i++)
EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
for (k = 0; k < 3; k++) {
algindex = D_CBC_128_CML + k;
if (doit[algindex]) {
int st = 1;
keylen = 16 + k * 8;
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
key32, keylen);
st = loopargs[i].ctx != NULL;
}
for (testnum = 0; st && testnum < size_num; testnum++) {
print_message(names[algindex], c[algindex][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(algindex, testnum, count, d);
}
for (i = 0; i < loopargs_len; i++)
EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
for (algindex = D_RC4; algindex <= D_CBC_CAST; algindex++) {
if (doit[algindex]) {
int st = 1;
keylen = 16;
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
key32, keylen);
st = loopargs[i].ctx != NULL;
}
for (testnum = 0; st && testnum < size_num; testnum++) {
print_message(names[algindex], c[algindex][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(algindex, testnum, count, d);
}
for (i = 0; i < loopargs_len; i++)
EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
if (doit[D_GHASH]) {
static const char gmac_iv[] = "0123456789ab";
OSSL_PARAM params[3];
mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC", app_get0_propq());
if (mac == NULL)
goto end;
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER,
"aes-128-gcm", 0);
params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_IV,
(char *)gmac_iv,
sizeof(gmac_iv) - 1);
params[2] = OSSL_PARAM_construct_end();
for (i = 0; i < loopargs_len; i++) {
loopargs[i].mctx = EVP_MAC_CTX_new(mac);
if (loopargs[i].mctx == NULL)
goto end;
if (!EVP_MAC_init(loopargs[i].mctx, key32, 16, params))
goto end;
}
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, GHASH_loop, loopargs);
d = Time_F(STOP);
print_result(D_GHASH, testnum, count, d);
if (count < 0)
break;
}
for (i = 0; i < loopargs_len; i++)
EVP_MAC_CTX_free(loopargs[i].mctx);
EVP_MAC_free(mac);
mac = NULL;
}
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);
}
}
+ /*-
+ * There are three scenarios for D_EVP:
+ * 1- Using authenticated encryption (AE) e.g. CCM, GCM, OCB etc.
+ * 2- Using AE + associated data (AD) i.e. AEAD using CCM, GCM, OCB etc.
+ * 3- Not using AE or AD e.g. ECB, CBC, CFB etc.
+ */
if (doit[D_EVP]) {
if (evp_cipher != NULL) {
- int (*loopfunc) (void *) = EVP_Update_loop;
+ int (*loopfunc) (void *);
+ int outlen = 0;
+ unsigned int ae_mode = 0;
- if (multiblock && (EVP_CIPHER_get_flags(evp_cipher) &
- EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
+ if (multiblock && (EVP_CIPHER_get_flags(evp_cipher)
+ & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
multiblock_speed(evp_cipher, lengths_single, &seconds);
ret = 0;
goto end;
}
names[D_EVP] = EVP_CIPHER_get0_name(evp_cipher);
- if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_CCM_MODE) {
- loopfunc = EVP_Update_loop_ccm;
- } else if (aead && (EVP_CIPHER_get_flags(evp_cipher) &
- EVP_CIPH_FLAG_AEAD_CIPHER)) {
- loopfunc = EVP_Update_loop_aead;
+ mode_op = EVP_CIPHER_get_mode(evp_cipher);
+
+ if (aead) {
if (lengths == lengths_list) {
lengths = aead_lengths_list;
size_num = OSSL_NELEM(aead_lengths_list);
}
}
+ if (mode_op == EVP_CIPH_GCM_MODE
+ || mode_op == EVP_CIPH_CCM_MODE
+ || mode_op == EVP_CIPH_OCB_MODE
+ || mode_op == EVP_CIPH_SIV_MODE) {
+ ae_mode = 1;
+ if (decrypt)
+ loopfunc = EVP_Update_loop_aead_dec;
+ else
+ loopfunc = EVP_Update_loop_aead_enc;
+ } else {
+ loopfunc = EVP_Update_loop;
+ }
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum],
seconds.sym);
for (k = 0; k < loopargs_len; k++) {
loopargs[k].ctx = EVP_CIPHER_CTX_new();
if (loopargs[k].ctx == NULL) {
BIO_printf(bio_err, "\nEVP_CIPHER_CTX_new failure\n");
exit(1);
}
- if (!EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL,
- NULL, iv, decrypt ? 0 : 1)) {
- BIO_printf(bio_err, "\nEVP_CipherInit_ex failure\n");
+
+ /*
+ * For AE modes, we must first encrypt the data to get
+ * a valid tag that enables us to decrypt. If we don't
+ * encrypt first, we won't have a valid tag that enables
+ * authenticity and hence decryption will fail.
+ */
+ if (!EVP_CipherInit_ex(loopargs[k].ctx,
+ evp_cipher, NULL, NULL, NULL,
+ ae_mode ? 1 : !decrypt)) {
+ BIO_printf(bio_err, "\nCouldn't init the context\n");
ERR_print_errors(bio_err);
exit(1);
}
+ /* Padding isn't needed */
EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0);
keylen = EVP_CIPHER_CTX_get_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);
- if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
- loopargs[k].key, NULL, -1)) {
- BIO_printf(bio_err, "\nEVP_CipherInit_ex failure\n");
- ERR_print_errors(bio_err);
- exit(1);
- }
- OPENSSL_clear_free(loopargs[k].key, keylen);
- /* SIV mode only allows for a single Update operation */
- if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_SIV_MODE)
- (void)EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
- EVP_CTRL_SET_SPEED, 1, NULL);
+ if (!ae_mode) {
+ if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
+ loopargs[k].key, iv, -1)) {
+ BIO_printf(bio_err, "\nFailed to set the key\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ } else if (mode_op == EVP_CIPH_SIV_MODE) {
+ EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
+ EVP_CTRL_SET_SPEED, 1, NULL);
+ }
+ if (ae_mode && decrypt) {
+ /* Set length of iv (Doesn't apply to SIV mode) */
+ if (mode_op != EVP_CIPH_SIV_MODE) {
+ if (!EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
+ EVP_CTRL_AEAD_SET_IVLEN,
+ aead_ivlen, NULL)) {
+ BIO_printf(bio_err, "\nFailed to set iv length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ /* Set tag_len (Not for SIV at encryption stage) */
+ if (mode_op != EVP_CIPH_GCM_MODE
+ && mode_op != EVP_CIPH_SIV_MODE) {
+ if (!EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
+ EVP_CTRL_AEAD_SET_TAG,
+ TAG_LEN, NULL)) {
+ BIO_printf(bio_err,
+ "\nFailed to set tag length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
+ loopargs[k].key, aead_iv, -1)) {
+ BIO_printf(bio_err, "\nFailed to set the key\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ /* Set total length of input. Only required for CCM */
+ if (mode_op == EVP_CIPH_CCM_MODE) {
+ if (!EVP_EncryptUpdate(loopargs[k].ctx, NULL,
+ &outlen, NULL,
+ lengths[testnum])) {
+ BIO_printf(bio_err,
+ "\nCouldn't set input text length\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ if (aead) {
+ if (!EVP_EncryptUpdate(loopargs[k].ctx, NULL,
+ &outlen, aad, sizeof(aad))) {
+ BIO_printf(bio_err,
+ "\nCouldn't insert AAD when encrypting\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ }
+ if (!EVP_EncryptUpdate(loopargs[k].ctx, loopargs[k].buf,
+ &outlen, loopargs[k].buf,
+ lengths[testnum])) {
+ BIO_printf(bio_err,
+ "\nFailed to to encrypt the data\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+
+ if (!EVP_EncryptFinal_ex(loopargs[k].ctx,
+ loopargs[k].buf, &outlen)) {
+ BIO_printf(bio_err,
+ "\nFailed finalize the encryption\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+
+ if (!EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
+ EVP_CTRL_AEAD_GET_TAG,
+ TAG_LEN, &loopargs[k].tag)) {
+ BIO_printf(bio_err, "\nFailed to get the tag\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+
+ EVP_CIPHER_CTX_free(loopargs[k].ctx);
+ loopargs[k].ctx = EVP_CIPHER_CTX_new();
+ if (loopargs[k].ctx == NULL) {
+ BIO_printf(bio_err,
+ "\nEVP_CIPHER_CTX_new failure\n");
+ exit(1);
+ }
+ if (!EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher,
+ NULL, NULL, NULL, 0)) {
+ BIO_printf(bio_err,
+ "\nFailed initializing the context\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+
+ EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0);
+
+ /* SIV only allows for one Update operation */
+ if (mode_op == EVP_CIPH_SIV_MODE)
+ EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
+ EVP_CTRL_SET_SPEED, 1, NULL);
+ }
}
Time_F(START);
count = run_benchmark(async_jobs, loopfunc, loopargs);
d = Time_F(STOP);
- for (k = 0; k < loopargs_len; k++)
+ for (k = 0; k < loopargs_len; k++) {
+ OPENSSL_clear_free(loopargs[k].key, keylen);
EVP_CIPHER_CTX_free(loopargs[k].ctx);
+ }
print_result(D_EVP, testnum, count, d);
}
} else if (evp_md_name != NULL) {
names[D_EVP] = evp_md_name;
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, EVP_Digest_md_loop, loopargs);
d = Time_F(STOP);
print_result(D_EVP, testnum, count, d);
if (count < 0)
break;
}
}
}
if (doit[D_EVP_CMAC]) {
+ size_t len = sizeof("cmac()") + strlen(evp_mac_ciphername);
OSSL_PARAM params[3];
EVP_CIPHER *cipher = NULL;
mac = EVP_MAC_fetch(app_get0_libctx(), "CMAC", app_get0_propq());
if (mac == NULL || evp_mac_ciphername == NULL)
goto end;
if (!opt_cipher(evp_mac_ciphername, &cipher))
goto end;
keylen = EVP_CIPHER_get_key_length(cipher);
EVP_CIPHER_free(cipher);
if (keylen <= 0 || keylen > (int)sizeof(key32)) {
BIO_printf(bio_err, "\nRequested CMAC cipher with unsupported key length.\n");
goto end;
}
- evp_cmac_name = app_malloc(sizeof("cmac()")
- + strlen(evp_mac_ciphername), "CMAC name");
- sprintf(evp_cmac_name, "cmac(%s)", evp_mac_ciphername);
+ evp_cmac_name = app_malloc(len, "CMAC name");
+ BIO_snprintf(evp_cmac_name, len, "cmac(%s)", evp_mac_ciphername);
names[D_EVP_CMAC] = evp_cmac_name;
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER,
evp_mac_ciphername, 0);
params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
(char *)key32, keylen);
params[2] = OSSL_PARAM_construct_end();
for (i = 0; i < loopargs_len; i++) {
loopargs[i].mctx = EVP_MAC_CTX_new(mac);
if (loopargs[i].mctx == NULL)
goto end;
if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
goto end;
}
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_EVP_CMAC], c[D_EVP_CMAC][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, CMAC_loop, loopargs);
d = Time_F(STOP);
print_result(D_EVP_CMAC, testnum, count, d);
if (count < 0)
break;
}
for (i = 0; i < loopargs_len; i++)
EVP_MAC_CTX_free(loopargs[i].mctx);
EVP_MAC_free(mac);
mac = NULL;
}
for (i = 0; i < loopargs_len; i++)
if (RAND_bytes(loopargs[i].buf, 36) <= 0)
goto end;
for (testnum = 0; testnum < RSA_NUM; testnum++) {
EVP_PKEY *rsa_key = NULL;
int st = 0;
if (!rsa_doit[testnum])
continue;
if (primes > RSA_DEFAULT_PRIME_NUM) {
/* we haven't set keys yet, generate multi-prime RSA keys */
bn = BN_new();
st = bn != NULL
&& BN_set_word(bn, RSA_F4)
&& init_gen_str(&genctx, "RSA", NULL, 0, NULL, NULL)
&& EVP_PKEY_CTX_set_rsa_keygen_bits(genctx, rsa_keys[testnum].bits) > 0
&& EVP_PKEY_CTX_set1_rsa_keygen_pubexp(genctx, bn) > 0
&& EVP_PKEY_CTX_set_rsa_keygen_primes(genctx, primes) > 0
&& EVP_PKEY_keygen(genctx, &rsa_key);
BN_free(bn);
bn = NULL;
EVP_PKEY_CTX_free(genctx);
genctx = NULL;
} else {
const unsigned char *p = rsa_keys[testnum].data;
st = (rsa_key = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &p,
rsa_keys[testnum].length)) != NULL;
}
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].rsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key, NULL);
loopargs[i].sigsize = loopargs[i].buflen;
if (loopargs[i].rsa_sign_ctx[testnum] == NULL
|| EVP_PKEY_sign_init(loopargs[i].rsa_sign_ctx[testnum]) <= 0
|| EVP_PKEY_sign(loopargs[i].rsa_sign_ctx[testnum],
loopargs[i].buf2,
&loopargs[i].sigsize,
loopargs[i].buf, 36) <= 0)
st = 0;
}
if (!st) {
BIO_printf(bio_err,
"RSA sign setup failure. No RSA sign will be done.\n");
ERR_print_errors(bio_err);
op_count = 1;
} else {
pkey_print_message("private", "rsa",
rsa_c[testnum][0], rsa_keys[testnum].bits,
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_keys[testnum].bits, d);
rsa_results[testnum][0] = (double)count / d;
op_count = count;
}
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].rsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key,
NULL);
if (loopargs[i].rsa_verify_ctx[testnum] == NULL
|| EVP_PKEY_verify_init(loopargs[i].rsa_verify_ctx[testnum]) <= 0
|| EVP_PKEY_verify(loopargs[i].rsa_verify_ctx[testnum],
loopargs[i].buf2,
loopargs[i].sigsize,
loopargs[i].buf, 36) <= 0)
st = 0;
}
if (!st) {
BIO_printf(bio_err,
"RSA verify setup 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_keys[testnum].bits,
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_keys[testnum].bits, d);
rsa_results[testnum][1] = (double)count / d;
}
if (op_count <= 1) {
/* if longer than 10s, don't do any more */
stop_it(rsa_doit, testnum);
}
EVP_PKEY_free(rsa_key);
}
for (testnum = 0; testnum < DSA_NUM; testnum++) {
EVP_PKEY *dsa_key = NULL;
int st;
if (!dsa_doit[testnum])
continue;
st = (dsa_key = get_dsa(dsa_bits[testnum])) != NULL;
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].dsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(dsa_key,
NULL);
loopargs[i].sigsize = loopargs[i].buflen;
if (loopargs[i].dsa_sign_ctx[testnum] == NULL
|| EVP_PKEY_sign_init(loopargs[i].dsa_sign_ctx[testnum]) <= 0
|| EVP_PKEY_sign(loopargs[i].dsa_sign_ctx[testnum],
loopargs[i].buf2,
&loopargs[i].sigsize,
loopargs[i].buf, 20) <= 0)
st = 0;
}
if (!st) {
BIO_printf(bio_err,
"DSA sign setup failure. No DSA sign will be done.\n");
ERR_print_errors(bio_err);
op_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;
op_count = count;
}
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].dsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(dsa_key,
NULL);
if (loopargs[i].dsa_verify_ctx[testnum] == NULL
|| EVP_PKEY_verify_init(loopargs[i].dsa_verify_ctx[testnum]) <= 0
|| EVP_PKEY_verify(loopargs[i].dsa_verify_ctx[testnum],
loopargs[i].buf2,
loopargs[i].sigsize,
loopargs[i].buf, 36) <= 0)
st = 0;
}
if (!st) {
BIO_printf(bio_err,
"DSA verify setup 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 (op_count <= 1) {
/* if longer than 10s, don't do any more */
stop_it(dsa_doit, testnum);
}
EVP_PKEY_free(dsa_key);
}
for (testnum = 0; testnum < ECDSA_NUM; testnum++) {
EVP_PKEY *ecdsa_key = NULL;
int st;
if (!ecdsa_doit[testnum])
continue;
st = (ecdsa_key = get_ecdsa(&ec_curves[testnum])) != NULL;
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].ecdsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(ecdsa_key,
NULL);
loopargs[i].sigsize = loopargs[i].buflen;
if (loopargs[i].ecdsa_sign_ctx[testnum] == NULL
|| EVP_PKEY_sign_init(loopargs[i].ecdsa_sign_ctx[testnum]) <= 0
|| EVP_PKEY_sign(loopargs[i].ecdsa_sign_ctx[testnum],
loopargs[i].buf2,
&loopargs[i].sigsize,
loopargs[i].buf, 20) <= 0)
st = 0;
}
if (!st) {
BIO_printf(bio_err,
"ECDSA sign setup failure. No ECDSA sign will be done.\n");
ERR_print_errors(bio_err);
op_count = 1;
} else {
pkey_print_message("sign", "ecdsa",
ecdsa_c[testnum][0], ec_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, ec_curves[testnum].bits, d);
ecdsa_results[testnum][0] = (double)count / d;
op_count = count;
}
for (i = 0; st && i < loopargs_len; i++) {
loopargs[i].ecdsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(ecdsa_key,
NULL);
if (loopargs[i].ecdsa_verify_ctx[testnum] == NULL
|| EVP_PKEY_verify_init(loopargs[i].ecdsa_verify_ctx[testnum]) <= 0
|| EVP_PKEY_verify(loopargs[i].ecdsa_verify_ctx[testnum],
loopargs[i].buf2,
loopargs[i].sigsize,
loopargs[i].buf, 20) <= 0)
st = 0;
}
if (!st) {
BIO_printf(bio_err,
"ECDSA verify setup 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], ec_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, ec_curves[testnum].bits, d);
ecdsa_results[testnum][1] = (double)count / d;
}
if (op_count <= 1) {
/* if longer than 10s, don't do any more */
stop_it(ecdsa_doit, testnum);
}
}
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 *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;
if ((key_A = get_ecdsa(&ec_curves[testnum])) == NULL /* generate secret key A */
|| (key_B = get_ecdsa(&ec_curves[testnum])) == NULL /* generate secret key B */
|| (ctx = EVP_PKEY_CTX_new(key_A, NULL)) == NULL /* derivation ctx from skeyA */
|| EVP_PKEY_derive_init(ctx) <= 0 /* init derivation ctx */
|| EVP_PKEY_derive_set_peer(ctx, key_B) <= 0 /* set peer pubkey in ctx */
|| EVP_PKEY_derive(ctx, NULL, &outlen) <= 0 /* 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);
op_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)) == NULL /* test ctx from skeyB */
|| EVP_PKEY_derive_init(test_ctx) <= 0 /* init derivation test_ctx */
|| EVP_PKEY_derive_set_peer(test_ctx, key_A) <= 0 /* set peer pubkey in test_ctx */
|| EVP_PKEY_derive(test_ctx, NULL, &test_outlen) <= 0 /* determine max length */
|| EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) <= 0 /* compute a*B */
|| EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) <= 0 /* 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);
op_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);
op_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(test_ctx);
test_ctx = NULL;
}
if (ecdh_checks != 0) {
pkey_print_message("", "ecdh",
ecdh_c[testnum][0],
ec_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,
ec_curves[testnum].bits, d);
ecdh_results[testnum][0] = (double)count / d;
op_count = count;
}
if (op_count <= 1) {
/* if longer than 10s, don't do any more */
stop_it(ecdh_doit, testnum);
}
}
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;
}
loopargs[i].eddsa_ctx2[testnum] = EVP_MD_CTX_new();
if (loopargs[i].eddsa_ctx2[testnum] == NULL) {
st = 0;
break;
}
if ((ed_pctx = EVP_PKEY_CTX_new_id(ed_curves[testnum].nid,
NULL)) == NULL
|| EVP_PKEY_keygen_init(ed_pctx) <= 0
|| EVP_PKEY_keygen(ed_pctx, &ed_pkey) <= 0) {
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;
}
if (!EVP_DigestVerifyInit(loopargs[i].eddsa_ctx2[testnum], NULL,
NULL, NULL, ed_pkey)) {
st = 0;
EVP_PKEY_free(ed_pkey);
break;
}
EVP_PKEY_free(ed_pkey);
ed_pkey = NULL;
}
if (st == 0) {
BIO_printf(bio_err, "EdDSA failure.\n");
ERR_print_errors(bio_err);
op_count = 1;
} else {
for (i = 0; i < loopargs_len; i++) {
/* Perform EdDSA signature test */
loopargs[i].sigsize = 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);
op_count = 1;
} else {
pkey_print_message("sign", ed_curves[testnum].name,
eddsa_c[testnum][0],
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, ed_curves[testnum].bits,
ed_curves[testnum].name, d);
eddsa_results[testnum][0] = (double)count / d;
op_count = count;
}
/* Perform EdDSA verification test */
for (i = 0; i < loopargs_len; i++) {
st = EVP_DigestVerify(loopargs[i].eddsa_ctx2[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", ed_curves[testnum].name,
eddsa_c[testnum][1],
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, ed_curves[testnum].bits,
ed_curves[testnum].name, d);
eddsa_results[testnum][1] = (double)count / d;
}
if (op_count <= 1) {
/* if longer than 10s, don't do any more */
stop_it(eddsa_doit, testnum);
}
}
}
#ifndef OPENSSL_NO_SM2
for (testnum = 0; testnum < SM2_NUM; testnum++) {
int st = 1;
EVP_PKEY *sm2_pkey = NULL;
if (!sm2_doit[testnum])
continue; /* Ignore Curve */
/* Init signing and verification */
for (i = 0; i < loopargs_len; i++) {
EVP_PKEY_CTX *sm2_pctx = NULL;
EVP_PKEY_CTX *sm2_vfy_pctx = NULL;
EVP_PKEY_CTX *pctx = NULL;
st = 0;
loopargs[i].sm2_ctx[testnum] = EVP_MD_CTX_new();
loopargs[i].sm2_vfy_ctx[testnum] = EVP_MD_CTX_new();
if (loopargs[i].sm2_ctx[testnum] == NULL
|| loopargs[i].sm2_vfy_ctx[testnum] == NULL)
break;
sm2_pkey = NULL;
st = !((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL)) == NULL
|| EVP_PKEY_keygen_init(pctx) <= 0
|| EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
sm2_curves[testnum].nid) <= 0
|| EVP_PKEY_keygen(pctx, &sm2_pkey) <= 0);
EVP_PKEY_CTX_free(pctx);
if (st == 0)
break;
st = 0; /* set back to zero */
/* attach it sooner to rely on main final cleanup */
loopargs[i].sm2_pkey[testnum] = sm2_pkey;
loopargs[i].sigsize = EVP_PKEY_get_size(sm2_pkey);
sm2_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
sm2_vfy_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
if (sm2_pctx == NULL || sm2_vfy_pctx == NULL) {
EVP_PKEY_CTX_free(sm2_vfy_pctx);
break;
}
/* attach them directly to respective ctx */
EVP_MD_CTX_set_pkey_ctx(loopargs[i].sm2_ctx[testnum], sm2_pctx);
EVP_MD_CTX_set_pkey_ctx(loopargs[i].sm2_vfy_ctx[testnum], sm2_vfy_pctx);
/*
* No need to allow user to set an explicit ID here, just use
* the one defined in the 'draft-yang-tls-tl13-sm-suites' I-D.
*/
if (EVP_PKEY_CTX_set1_id(sm2_pctx, SM2_ID, SM2_ID_LEN) != 1
|| EVP_PKEY_CTX_set1_id(sm2_vfy_pctx, SM2_ID, SM2_ID_LEN) != 1)
break;
if (!EVP_DigestSignInit(loopargs[i].sm2_ctx[testnum], NULL,
EVP_sm3(), NULL, sm2_pkey))
break;
if (!EVP_DigestVerifyInit(loopargs[i].sm2_vfy_ctx[testnum], NULL,
EVP_sm3(), NULL, sm2_pkey))
break;
st = 1; /* mark loop as succeeded */
}
if (st == 0) {
BIO_printf(bio_err, "SM2 init failure.\n");
ERR_print_errors(bio_err);
op_count = 1;
} else {
for (i = 0; i < loopargs_len; i++) {
/* Perform SM2 signature test */
st = EVP_DigestSign(loopargs[i].sm2_ctx[testnum],
loopargs[i].buf2, &loopargs[i].sigsize,
loopargs[i].buf, 20);
if (st == 0)
break;
}
if (st == 0) {
BIO_printf(bio_err,
"SM2 sign failure. No SM2 sign will be done.\n");
ERR_print_errors(bio_err);
op_count = 1;
} else {
pkey_print_message("sign", sm2_curves[testnum].name,
sm2_c[testnum][0],
sm2_curves[testnum].bits, seconds.sm2);
Time_F(START);
count = run_benchmark(async_jobs, SM2_sign_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R10:%ld:%u:%s:%.2f\n" :
"%ld %u bits %s signs in %.2fs \n",
count, sm2_curves[testnum].bits,
sm2_curves[testnum].name, d);
sm2_results[testnum][0] = (double)count / d;
op_count = count;
}
/* Perform SM2 verification test */
for (i = 0; i < loopargs_len; i++) {
st = EVP_DigestVerify(loopargs[i].sm2_vfy_ctx[testnum],
loopargs[i].buf2, loopargs[i].sigsize,
loopargs[i].buf, 20);
if (st != 1)
break;
}
if (st != 1) {
BIO_printf(bio_err,
"SM2 verify failure. No SM2 verify will be done.\n");
ERR_print_errors(bio_err);
sm2_doit[testnum] = 0;
} else {
pkey_print_message("verify", sm2_curves[testnum].name,
sm2_c[testnum][1],
sm2_curves[testnum].bits, seconds.sm2);
Time_F(START);
count = run_benchmark(async_jobs, SM2_verify_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R11:%ld:%u:%s:%.2f\n"
: "%ld %u bits %s verify in %.2fs\n",
count, sm2_curves[testnum].bits,
sm2_curves[testnum].name, d);
sm2_results[testnum][1] = (double)count / d;
}
if (op_count <= 1) {
/* if longer than 10s, don't do any more */
for (testnum++; testnum < SM2_NUM; testnum++)
sm2_doit[testnum] = 0;
}
}
}
#endif /* OPENSSL_NO_SM2 */
#ifndef OPENSSL_NO_DH
for (testnum = 0; testnum < FFDH_NUM; testnum++) {
int ffdh_checks = 1;
if (!ffdh_doit[testnum])
continue;
for (i = 0; i < loopargs_len; i++) {
EVP_PKEY *pkey_A = NULL;
EVP_PKEY *pkey_B = NULL;
EVP_PKEY_CTX *ffdh_ctx = NULL;
EVP_PKEY_CTX *test_ctx = NULL;
size_t secret_size;
size_t test_out;
/* 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);
}
pkey_A = EVP_PKEY_new();
if (!pkey_A) {
BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
pkey_B = EVP_PKEY_new();
if (!pkey_B) {
BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
ffdh_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
if (!ffdh_ctx) {
BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_keygen_init(ffdh_ctx) <= 0) {
BIO_printf(bio_err, "Error while initialising EVP_PKEY_CTX.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_CTX_set_dh_nid(ffdh_ctx, ffdh_params[testnum].nid) <= 0) {
BIO_printf(bio_err, "Error setting DH key size for keygen.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_keygen(ffdh_ctx, &pkey_A) <= 0 ||
EVP_PKEY_keygen(ffdh_ctx, &pkey_B) <= 0) {
BIO_printf(bio_err, "FFDH key generation failure.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
EVP_PKEY_CTX_free(ffdh_ctx);
/*
* check if the derivation works correctly both ways so that
* we know if future derive calls will fail, and we can skip
* error checking in benchmarked code
*/
ffdh_ctx = EVP_PKEY_CTX_new(pkey_A, NULL);
if (ffdh_ctx == NULL) {
BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive_init(ffdh_ctx) <= 0) {
BIO_printf(bio_err, "FFDH derivation context init failure.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive_set_peer(ffdh_ctx, pkey_B) <= 0) {
BIO_printf(bio_err, "Assigning peer key for derivation failed.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive(ffdh_ctx, NULL, &secret_size) <= 0) {
BIO_printf(bio_err, "Checking size of shared secret failed.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
if (secret_size > MAX_FFDH_SIZE) {
BIO_printf(bio_err, "Assertion failure: shared secret too large.\n");
op_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive(ffdh_ctx,
loopargs[i].secret_ff_a,
&secret_size) <= 0) {
BIO_printf(bio_err, "Shared secret derive failure.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
/* Now check from side B */
test_ctx = EVP_PKEY_CTX_new(pkey_B, NULL);
if (!test_ctx) {
BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive_init(test_ctx) <= 0 ||
EVP_PKEY_derive_set_peer(test_ctx, pkey_A) <= 0 ||
EVP_PKEY_derive(test_ctx, NULL, &test_out) <= 0 ||
EVP_PKEY_derive(test_ctx, loopargs[i].secret_ff_b, &test_out) <= 0 ||
test_out != secret_size) {
BIO_printf(bio_err, "FFDH computation failure.\n");
op_count = 1;
ffdh_checks = 0;
break;
}
/* compare the computed secrets */
if (CRYPTO_memcmp(loopargs[i].secret_ff_a,
loopargs[i].secret_ff_b, secret_size)) {
BIO_printf(bio_err, "FFDH computations don't match.\n");
ERR_print_errors(bio_err);
op_count = 1;
ffdh_checks = 0;
break;
}
loopargs[i].ffdh_ctx[testnum] = ffdh_ctx;
EVP_PKEY_free(pkey_A);
pkey_A = NULL;
EVP_PKEY_free(pkey_B);
pkey_B = NULL;
EVP_PKEY_CTX_free(test_ctx);
test_ctx = NULL;
}
if (ffdh_checks != 0) {
pkey_print_message("", "ffdh", ffdh_c[testnum][0],
ffdh_params[testnum].bits, seconds.ffdh);
Time_F(START);
count =
run_benchmark(async_jobs, FFDH_derive_key_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R12:%ld:%d:%.2f\n" :
"%ld %u-bits FFDH ops in %.2fs\n", count,
ffdh_params[testnum].bits, d);
ffdh_results[testnum][0] = (double)count / d;
op_count = count;
}
if (op_count <= 1) {
/* if longer than 10s, don't do any more */
stop_it(ffdh_doit, testnum);
}
}
#endif /* OPENSSL_NO_DH */
#ifndef NO_FORK
show_res:
#endif
if (!mr) {
printf("version: %s\n", OpenSSL_version(OPENSSL_FULL_VERSION_STRING));
printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
printf("options: %s\n", BN_options());
printf("%s\n", OpenSSL_version(OPENSSL_CFLAGS));
printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO));
}
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++) {
const char *alg_name = names[k];
if (!doit[k])
continue;
if (k == D_EVP) {
if (evp_cipher == NULL)
alg_name = evp_md_name;
else if ((alg_name = EVP_CIPHER_get0_name(evp_cipher)) == NULL)
app_bail_out("failed to get name of cipher '%s'\n", evp_cipher);
}
if (mr)
printf("+F:%u:%s", k, alg_name);
else
printf("%-13s", alg_name);
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");
}
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_keys[k].bits, rsa_results[k][0], rsa_results[k][1]);
else
printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
rsa_keys[k].bits, 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1],
rsa_results[k][0], rsa_results[k][1]);
}
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]);
}
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, ec_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",
ec_curves[k].bits, ec_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, ec_curves[k].bits,
ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
else
printf("%4u bits ecdh (%s) %8.4fs %8.1f\n",
ec_curves[k].bits, ec_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, ed_curves[k].bits, 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",
ed_curves[k].bits, ed_curves[k].name,
1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1],
eddsa_results[k][0], eddsa_results[k][1]);
}
#ifndef OPENSSL_NO_SM2
testnum = 1;
for (k = 0; k < OSSL_NELEM(sm2_doit); k++) {
if (!sm2_doit[k])
continue;
if (testnum && !mr) {
printf("%30ssign verify sign/s verify/s\n", " ");
testnum = 0;
}
if (mr)
printf("+F7:%u:%u:%s:%f:%f\n",
k, sm2_curves[k].bits, sm2_curves[k].name,
sm2_results[k][0], sm2_results[k][1]);
else
printf("%4u bits SM2 (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
sm2_curves[k].bits, sm2_curves[k].name,
1.0 / sm2_results[k][0], 1.0 / sm2_results[k][1],
sm2_results[k][0], sm2_results[k][1]);
}
#endif
#ifndef OPENSSL_NO_DH
testnum = 1;
for (k = 0; k < FFDH_NUM; k++) {
if (!ffdh_doit[k])
continue;
if (testnum && !mr) {
printf("%23sop op/s\n", " ");
testnum = 0;
}
if (mr)
printf("+F8:%u:%u:%f:%f\n",
k, ffdh_params[k].bits,
ffdh_results[k][0], 1.0 / ffdh_results[k][0]);
else
printf("%4u bits ffdh %8.4fs %8.1f\n",
ffdh_params[k].bits,
1.0 / ffdh_results[k][0], ffdh_results[k][0]);
}
#endif /* OPENSSL_NO_DH */
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);
BN_free(bn);
EVP_PKEY_CTX_free(genctx);
for (k = 0; k < RSA_NUM; k++) {
EVP_PKEY_CTX_free(loopargs[i].rsa_sign_ctx[k]);
EVP_PKEY_CTX_free(loopargs[i].rsa_verify_ctx[k]);
}
#ifndef OPENSSL_NO_DH
OPENSSL_free(loopargs[i].secret_ff_a);
OPENSSL_free(loopargs[i].secret_ff_b);
for (k = 0; k < FFDH_NUM; k++)
EVP_PKEY_CTX_free(loopargs[i].ffdh_ctx[k]);
#endif
for (k = 0; k < DSA_NUM; k++) {
EVP_PKEY_CTX_free(loopargs[i].dsa_sign_ctx[k]);
EVP_PKEY_CTX_free(loopargs[i].dsa_verify_ctx[k]);
}
for (k = 0; k < ECDSA_NUM; k++) {
EVP_PKEY_CTX_free(loopargs[i].ecdsa_sign_ctx[k]);
EVP_PKEY_CTX_free(loopargs[i].ecdsa_verify_ctx[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]);
EVP_MD_CTX_free(loopargs[i].eddsa_ctx2[k]);
}
#ifndef OPENSSL_NO_SM2
for (k = 0; k < SM2_NUM; k++) {
EVP_PKEY_CTX *pctx = NULL;
/* free signing ctx */
if (loopargs[i].sm2_ctx[k] != NULL
&& (pctx = EVP_MD_CTX_get_pkey_ctx(loopargs[i].sm2_ctx[k])) != NULL)
EVP_PKEY_CTX_free(pctx);
EVP_MD_CTX_free(loopargs[i].sm2_ctx[k]);
/* free verification ctx */
if (loopargs[i].sm2_vfy_ctx[k] != NULL
&& (pctx = EVP_MD_CTX_get_pkey_ctx(loopargs[i].sm2_vfy_ctx[k])) != NULL)
EVP_PKEY_CTX_free(pctx);
EVP_MD_CTX_free(loopargs[i].sm2_vfy_ctx[k]);
/* free pkey */
EVP_PKEY_free(loopargs[i].sm2_pkey[k]);
}
#endif
OPENSSL_free(loopargs[i].secret_a);
OPENSSL_free(loopargs[i].secret_b);
}
OPENSSL_free(evp_hmac_name);
OPENSSL_free(evp_cmac_name);
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);
EVP_CIPHER_free(evp_cipher);
EVP_MAC_free(mac);
return ret;
}
static void print_message(const char *s, long num, int length, int tm)
{
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);
run = 1;
alarm(tm);
}
static void pkey_print_message(const char *str, const char *str2, long num,
unsigned int bits, int tm)
{
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);
run = 1;
alarm(tm);
}
static void print_result(int alg, int run_no, int count, double time_used)
{
if (count == -1) {
BIO_printf(bio_err, "%s error!\n", names[alg]);
ERR_print_errors(bio_err);
return;
}
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;
int status;
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;
OPENSSL_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;
if ((f = fdopen(fds[n], "r")) == NULL) {
BIO_printf(bio_err, "fdopen failure with 0x%x\n",
errno);
OPENSSL_free(fds);
return 1;
}
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;
} 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;
} 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);
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
eddsa_results[k][0] += d;
d = atof(sstrsep(&p, sep));
eddsa_results[k][1] += d;
# ifndef OPENSSL_NO_SM2
} else if (strncmp(buf, "+F7:", 4) == 0) {
int k;
double d;
p = buf + 4;
k = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
sm2_results[k][0] += d;
d = atof(sstrsep(&p, sep));
sm2_results[k][1] += d;
# endif /* OPENSSL_NO_SM2 */
# ifndef OPENSSL_NO_DH
} else if (strncmp(buf, "+F8:", 4) == 0) {
int k;
double d;
p = buf + 4;
k = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
ffdh_results[k][0] += d;
# endif /* OPENSSL_NO_DH */
} else if (strncmp(buf, "+H:", 3) == 0) {
;
} else {
BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf,
n);
}
}
fclose(f);
}
OPENSSL_free(fds);
for (n = 0; n < multi; ++n) {
while (wait(&status) == -1)
if (errno != EINTR) {
BIO_printf(bio_err, "Waitng for child failed with 0x%x\n",
errno);
return 1;
}
if (WIFEXITED(status) && WEXITSTATUS(status)) {
BIO_printf(bio_err, "Child exited with %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
BIO_printf(bio_err, "Child terminated by signal %d\n",
WTERMSIG(status));
}
}
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 = NULL, *out = NULL, *key, no_key[32], no_iv[16];
EVP_CIPHER_CTX *ctx = NULL;
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");
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
app_bail_out("failed to allocate cipher context\n");
if (!EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv))
app_bail_out("failed to initialise cipher context\n");
if ((keylen = EVP_CIPHER_CTX_get_key_length(ctx)) < 0) {
BIO_printf(bio_err, "Impossible negative key length: %d\n", keylen);
goto err;
}
key = app_malloc(keylen, "evp_cipher key");
if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
app_bail_out("failed to generate random cipher key\n");
if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL))
app_bail_out("failed to set cipher key\n");
OPENSSL_clear_free(key, keylen);
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY,
sizeof(no_key), no_key) <= 0)
app_bail_out("failed to set AEAD key\n");
if ((alg_name = EVP_CIPHER_get0_name(evp_cipher)) == NULL)
app_bail_out("failed to get cipher name\n");
for (j = 0; j < num; j++) {
print_message(alg_name, 0, mblengths[j], seconds->sym);
Time_F(START);
for (count = 0; run && count < INT_MAX; 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;
(void)EVP_CIPHER_CTX_ctrl(ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
sizeof(mb_param), &mb_param);
} else {
int pad;
if (RAND_bytes(inp, 16) <= 0)
app_bail_out("error setting random bytes\n");
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");
}
err:
OPENSSL_free(inp);
OPENSSL_free(out);
EVP_CIPHER_CTX_free(ctx);
}
diff --git a/crypto/openssl/configdata.pm.in b/crypto/openssl/configdata.pm.in
index 04b901144f47..a4ae90729995 100644
--- a/crypto/openssl/configdata.pm.in
+++ b/crypto/openssl/configdata.pm.in
@@ -1,487 +1,487 @@
#! {- $config{HASHBANGPERL} -}
# -*- mode: perl -*-
{-
# We must make sourcedir() return an absolute path, because configdata.pm
# may be loaded as a module from any script in any directory, making
# relative paths untrustable. Because the result is used with 'use lib',
# we must ensure that it returns a Unix style path. Mixing File::Spec
# and File::Spec::Unix does just that.
use File::Spec::Unix;
use File::Spec;
use Cwd qw(abs_path);
sub _fixup_path {
my $path = shift;
# Make the path absolute at all times
$path = abs_path($path);
if ($^O eq 'VMS') {
# Convert any path of the VMS form VOLUME:[DIR1.DIR2]FILE to the
# Unix form /VOLUME/DIR1/DIR2/FILE, which is what VMS perl supports
# for 'use lib'.
# Start with spliting the native path
(my $vol, my $dirs, my $file) = File::Spec->splitpath($path);
my @dirs = File::Spec->splitdir($dirs);
# Reassemble it as a Unix path
$vol =~ s|:$||;
$dirs = File::Spec::Unix->catdir('', $vol, @dirs);
$path = File::Spec::Unix->catpath('', $dirs, $file);
}
return $path;
}
sub sourcedir {
return _fixup_path(File::Spec->catdir($config{sourcedir}, @_))
}
sub sourcefile {
return _fixup_path(File::Spec->catfile($config{sourcedir}, @_))
}
use lib sourcedir('util', 'perl');
use OpenSSL::Util;
-}
package configdata;
use strict;
use warnings;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
%config %target %disabled %withargs %unified_info
@disablables @disablables_int
);
our %config = ({- dump_data(\%config, indent => 0); -});
our %target = ({- dump_data(\%target, indent => 0); -});
our @disablables = ({- dump_data(\@disablables, indent => 0) -});
our @disablables_int = ({- dump_data(\@disablables_int, indent => 0) -});
our %disabled = ({- dump_data(\%disabled, indent => 0); -});
our %withargs = ({- dump_data(\%withargs, indent => 0); -});
our %unified_info = ({- dump_data(\%unified_info, indent => 0); -});
# Unexported, only used by OpenSSL::Test::Utils::available_protocols()
our %available_protocols = (
tls => [{- dump_data(\@tls, indent => 0) -}],
dtls => [{- dump_data(\@dtls, indent => 0) -}],
);
# The following data is only used when this files is use as a script
my @makevars = ({- dump_data(\@makevars, indent => 0); -});
my %disabled_info = ({- dump_data(\%disabled_info, indent => 0); -});
my @user_crossable = qw( {- join (' ', @user_crossable) -} );
# If run directly, we can give some answers, and even reconfigure
unless (caller) {
use Getopt::Long;
use File::Spec::Functions;
use File::Basename;
use File::Compare qw(compare_text);
use File::Copy;
use Pod::Usage;
use lib '{- sourcedir('util', 'perl') -}';
use OpenSSL::fallback '{- sourcefile('external', 'perl', 'MODULES.txt') -}';
my $here = dirname($0);
if (scalar @ARGV == 0) {
# With no arguments, re-create the build file
# We do that in two steps, where the first step emits perl
# snipets.
my $buildfile = $config{build_file};
my $buildfile_template = "$buildfile.in";
my @autowarntext = (
'WARNING: do not edit!',
"Generated by configdata.pm from "
.join(", ", @{$config{build_file_templates}}),
"via $buildfile_template"
);
my %gendata = (
config => \%config,
target => \%target,
disabled => \%disabled,
withargs => \%withargs,
unified_info => \%unified_info,
autowarntext => \@autowarntext,
);
use lib '.';
use lib '{- sourcedir('Configurations') -}';
use gentemplate;
open my $buildfile_template_fh, ">$buildfile_template"
or die "Trying to create $buildfile_template: $!";
foreach (@{$config{build_file_templates}}) {
copy($_, $buildfile_template_fh)
or die "Trying to copy $_ into $buildfile_template: $!";
}
gentemplate(output => $buildfile_template_fh, %gendata);
close $buildfile_template_fh;
print 'Created ',$buildfile_template,"\n";
use OpenSSL::Template;
my $prepend = <<'_____';
use File::Spec::Functions;
use lib '{- sourcedir('util', 'perl') -}';
use lib '{- sourcedir('Configurations') -}';
use lib '{- $config{builddir} -}';
use platform;
_____
my $tmpl;
open BUILDFILE, ">$buildfile.new"
or die "Trying to create $buildfile.new: $!";
$tmpl = OpenSSL::Template->new(TYPE => 'FILE',
SOURCE => $buildfile_template);
$tmpl->fill_in(FILENAME => $_,
OUTPUT => \*BUILDFILE,
HASH => \%gendata,
PREPEND => $prepend,
# To ensure that global variables and functions
# defined in one template stick around for the
# next, making them combinable
PACKAGE => 'OpenSSL::safe')
- or die $Text::Template::ERROR;
+ or die $OpenSSL::Template::ERROR;
close BUILDFILE;
rename("$buildfile.new", $buildfile)
or die "Trying to rename $buildfile.new to $buildfile: $!";
print 'Created ',$buildfile,"\n";
my $configuration_h =
catfile('include', 'openssl', 'configuration.h');
my $configuration_h_in =
catfile($config{sourcedir}, 'include', 'openssl', 'configuration.h.in');
open CONFIGURATION_H, ">${configuration_h}.new"
or die "Trying to create ${configuration_h}.new: $!";
$tmpl = OpenSSL::Template->new(TYPE => 'FILE',
SOURCE => $configuration_h_in);
$tmpl->fill_in(FILENAME => $_,
OUTPUT => \*CONFIGURATION_H,
HASH => \%gendata,
PREPEND => $prepend,
# To ensure that global variables and functions
# defined in one template stick around for the
# next, making them combinable
PACKAGE => 'OpenSSL::safe')
- or die $Text::Template::ERROR;
+ or die $OpenSSL::Template::ERROR;
close CONFIGURATION_H;
# When using stat() on Windows, we can get it to perform better by
# avoid some data. This doesn't affect the mtime field, so we're not
# losing anything...
${^WIN32_SLOPPY_STAT} = 1;
my $update_configuration_h = 0;
if (-f $configuration_h) {
my $configuration_h_mtime = (stat($configuration_h))[9];
my $configuration_h_in_mtime = (stat($configuration_h_in))[9];
# If configuration.h.in was updated after the last configuration.h,
# or if configuration.h.new differs configuration.h, we update
# configuration.h
if ($configuration_h_mtime < $configuration_h_in_mtime
|| compare_text("${configuration_h}.new", $configuration_h) != 0) {
$update_configuration_h = 1;
} else {
# If nothing has changed, let's just drop the new one and
# pretend like nothing happened
unlink "${configuration_h}.new"
}
} else {
$update_configuration_h = 1;
}
if ($update_configuration_h) {
rename("${configuration_h}.new", $configuration_h)
or die "Trying to rename ${configuration_h}.new to $configuration_h: $!";
print 'Created ',$configuration_h,"\n";
}
exit(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 $query = 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,
'query|q=s' => \$query,
'help' => \$help,
'man' => \$man)
or die "Errors in command line arguments\n";
# We allow extra arguments with --query. That allows constructs like
# this:
# ./configdata.pm --query 'get_sources(@ARGV)' file1 file2 file3
if (!$query && scalar @ARGV > 0) {
print STDERR <<"_____";
Unrecognised arguments.
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 {
if (defined $_) {
(my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""
} else {
"undef";
}
} @_;
};
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';
}
if ($query) {
use OpenSSL::Config::Query;
my $confquery = OpenSSL::Config::Query->new(info => \%unified_info,
config => \%config);
my $result = eval "\$confquery->$query";
# We may need a result class with a printing function at some point.
# Until then, we assume that we get a scalar, or a list or a hash table
# with scalar values and simply print them in some orderly fashion.
if (ref $result eq 'ARRAY') {
print "$_\n" foreach @$result;
} elsif (ref $result eq 'HASH') {
print "$_ : \\\n ", join(" \\\n ", @{$result->{$_}}), "\n"
foreach sort keys %$result;
} elsif (ref $result eq 'SCALAR') {
print "$$result\n";
}
}
}
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.
If run with no arguments, it will rebuild the build file (Makefile or
corresponding).
With at least one option, it will instead get the information you ask for, or
re-run the configuration process.
See L</OPTIONS> below for more information.
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>
Re-run the configuration process.
=item B<--verbose> | B<-v>
Verbose output.
=back
=cut
EOF
diff --git a/crypto/openssl/crypto/asn1/a_bitstr.c b/crypto/openssl/crypto/asn1/a_bitstr.c
index 4930d5022ee3..549c0e885549 100644
--- a/crypto/openssl/crypto/asn1/a_bitstr.c
+++ b/crypto/openssl/crypto/asn1/a_bitstr.c
@@ -1,222 +1,227 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include "asn1_local.h"
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
{
return ASN1_STRING_set(x, d, len);
}
int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
{
int ret, j, bits, len;
unsigned char *p, *d;
if (a == NULL)
return 0;
len = a->length;
if (len > 0) {
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
bits = (int)a->flags & 0x07;
} else {
for (; len > 0; len--) {
if (a->data[len - 1])
break;
}
- j = a->data[len - 1];
- if (j & 0x01)
+
+ if (len == 0) {
bits = 0;
- else if (j & 0x02)
- bits = 1;
- else if (j & 0x04)
- bits = 2;
- else if (j & 0x08)
- bits = 3;
- else if (j & 0x10)
- bits = 4;
- else if (j & 0x20)
- bits = 5;
- else if (j & 0x40)
- bits = 6;
- else if (j & 0x80)
- bits = 7;
- else
- bits = 0; /* should not happen */
+ } else {
+ j = a->data[len - 1];
+ if (j & 0x01)
+ bits = 0;
+ else if (j & 0x02)
+ bits = 1;
+ else if (j & 0x04)
+ bits = 2;
+ else if (j & 0x08)
+ bits = 3;
+ else if (j & 0x10)
+ bits = 4;
+ else if (j & 0x20)
+ bits = 5;
+ else if (j & 0x40)
+ bits = 6;
+ else if (j & 0x80)
+ bits = 7;
+ else
+ bits = 0; /* should not happen */
+ }
}
} else
bits = 0;
ret = 1 + len;
if (pp == NULL)
return ret;
p = *pp;
*(p++) = (unsigned char)bits;
d = a->data;
if (len > 0) {
memcpy(p, d, len);
p += len;
p[-1] &= (0xff << bits);
}
*pp = p;
return ret;
}
ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long len)
{
ASN1_BIT_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
int i;
if (len < 1) {
i = ASN1_R_STRING_TOO_SHORT;
goto err;
}
if (len > INT_MAX) {
i = ASN1_R_STRING_TOO_LONG;
goto err;
}
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = ASN1_BIT_STRING_new()) == NULL)
return NULL;
} else
ret = (*a);
p = *pp;
i = *(p++);
if (i > 7) {
i = ASN1_R_INVALID_BIT_STRING_BITS_LEFT;
goto err;
}
/*
* We do this to preserve the settings. If we modify the settings, via
* the _set_bit function, we will recalculate on output
*/
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | i); /* set */
if (len-- > 1) { /* using one because of the bits left byte */
s = OPENSSL_malloc((int)len);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
memcpy(s, p, (int)len);
s[len - 1] &= (0xff << i);
p += len;
} else
s = NULL;
ret->length = (int)len;
OPENSSL_free(ret->data);
ret->data = s;
ret->type = V_ASN1_BIT_STRING;
if (a != NULL)
(*a) = ret;
*pp = p;
return ret;
err:
ERR_raise(ERR_LIB_ASN1, i);
if ((a == NULL) || (*a != ret))
ASN1_BIT_STRING_free(ret);
return NULL;
}
/*
* These next 2 functions from Goetz Babin-Ebell.
*/
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
{
int w, v, iv;
unsigned char *c;
if (n < 0)
return 0;
w = n / 8;
v = 1 << (7 - (n & 0x07));
iv = ~v;
if (!value)
v = 0;
if (a == NULL)
return 0;
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
if ((a->length < (w + 1)) || (a->data == NULL)) {
if (!value)
return 1; /* Don't need to set */
c = OPENSSL_clear_realloc(a->data, a->length, w + 1);
if (c == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (w + 1 - a->length > 0)
memset(c + a->length, 0, w + 1 - a->length);
a->data = c;
a->length = w + 1;
}
a->data[w] = ((a->data[w]) & iv) | v;
while ((a->length > 0) && (a->data[a->length - 1] == 0))
a->length--;
return 1;
}
int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
{
int w, v;
if (n < 0)
return 0;
w = n / 8;
v = 1 << (7 - (n & 0x07));
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
return 0;
return ((a->data[w] & v) != 0);
}
/*
* Checks if the given bit string contains only bits specified by
* the flags vector. Returns 0 if there is at least one bit set in 'a'
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a,
const unsigned char *flags, int flags_len)
{
int i, ok;
/* Check if there is one bit set at all. */
if (!a || !a->data)
return 1;
/*
* Check each byte of the internal representation of the bit string.
*/
ok = 1;
for (i = 0; i < a->length && ok; ++i) {
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
/* We are done if there is an unneeded bit set. */
ok = (a->data[i] & mask) == 0;
}
return ok;
}
diff --git a/crypto/openssl/crypto/asn1/a_strnid.c b/crypto/openssl/crypto/asn1/a_strnid.c
index d052935661d3..20cfabc8a7a4 100644
--- a/crypto/openssl/crypto/asn1/a_strnid.c
+++ b/crypto/openssl/crypto/asn1/a_strnid.c
@@ -1,224 +1,224 @@
/*
- * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/asn1.h>
#include <openssl/objects.h>
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
static void st_free(ASN1_STRING_TABLE *tbl);
static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
const ASN1_STRING_TABLE *const *b);
/*
* This is the global mask for the mbstring functions: this is use to mask
* out certain types (such as BMPString and UTF8String) because certain
* software (e.g. Netscape) has problems with them.
*/
static unsigned long global_mask = B_ASN1_UTF8STRING;
void ASN1_STRING_set_default_mask(unsigned long mask)
{
global_mask = mask;
}
unsigned long ASN1_STRING_get_default_mask(void)
{
return global_mask;
}
/*-
* This function sets the default to various "flavours" of configuration.
* based on an ASCII string. Currently this is:
* MASK:XXXX : a numerical mask value.
- * nobmp : Don't use BMPStrings (just Printable, T61).
- * pkix : PKIX recommendation in RFC2459.
- * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
- * default: the default value, Printable, T61, BMP.
+ * default : use Printable, IA5, T61, BMP, and UTF8 string types
+ * nombstr : any string type except variable-sized BMPStrings or UTF8Strings
+ * pkix : PKIX recommendation in RFC2459
+ * utf8only : this is the default, use UTF8Strings
*/
int ASN1_STRING_set_default_mask_asc(const char *p)
{
unsigned long mask;
char *end;
if (strncmp(p, "MASK:", 5) == 0) {
if (p[5] == '\0')
return 0;
mask = strtoul(p + 5, &end, 0);
if (*end)
return 0;
} else if (strcmp(p, "nombstr") == 0)
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
else if (strcmp(p, "pkix") == 0)
mask = ~((unsigned long)B_ASN1_T61STRING);
else if (strcmp(p, "utf8only") == 0)
mask = B_ASN1_UTF8STRING;
else if (strcmp(p, "default") == 0)
mask = 0xFFFFFFFFL;
else
return 0;
ASN1_STRING_set_default_mask(mask);
return 1;
}
/*
* The following function generates an ASN1_STRING based on limits in a
* table. Frequently the types and length of an ASN1_STRING are restricted by
* a corresponding OID. For example certificates and certificate requests.
*/
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
const unsigned char *in, int inlen,
int inform, int nid)
{
ASN1_STRING_TABLE *tbl;
ASN1_STRING *str = NULL;
unsigned long mask;
int ret;
if (out == NULL)
out = &str;
tbl = ASN1_STRING_TABLE_get(nid);
if (tbl != NULL) {
mask = tbl->mask;
if (!(tbl->flags & STABLE_NO_MASK))
mask &= global_mask;
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
tbl->minsize, tbl->maxsize);
} else {
ret = ASN1_mbstring_copy(out, in, inlen, inform,
DIRSTRING_TYPE & global_mask);
}
if (ret <= 0)
return NULL;
return *out;
}
/*
* Now the tables and helper functions for the string table:
*/
#include "tbl_standard.h"
static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
const ASN1_STRING_TABLE *const *b)
{
return (*a)->nid - (*b)->nid;
}
DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
{
return a->nid - b->nid;
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
{
int idx;
ASN1_STRING_TABLE fnd;
#ifndef OPENSSL_NO_AUTOLOAD_CONFIG
/* "stable" can be impacted by config, so load the config file first */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
#endif
fnd.nid = nid;
if (stable) {
idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
if (idx >= 0)
return sk_ASN1_STRING_TABLE_value(stable, idx);
}
return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard));
}
/*
* Return a string table pointer which can be modified: either directly from
* table or a copy of an internal value added to the table.
*/
static ASN1_STRING_TABLE *stable_get(int nid)
{
ASN1_STRING_TABLE *tmp, *rv;
/* Always need a string table so allocate one if NULL */
if (stable == NULL) {
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
if (stable == NULL)
return NULL;
}
tmp = ASN1_STRING_TABLE_get(nid);
if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC)
return tmp;
if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
OPENSSL_free(rv);
return NULL;
}
if (tmp != NULL) {
rv->nid = tmp->nid;
rv->minsize = tmp->minsize;
rv->maxsize = tmp->maxsize;
rv->mask = tmp->mask;
rv->flags = tmp->flags | STABLE_FLAGS_MALLOC;
} else {
rv->nid = nid;
rv->minsize = -1;
rv->maxsize = -1;
rv->flags = STABLE_FLAGS_MALLOC;
}
return rv;
}
int ASN1_STRING_TABLE_add(int nid,
long minsize, long maxsize, unsigned long mask,
unsigned long flags)
{
ASN1_STRING_TABLE *tmp;
tmp = stable_get(nid);
if (tmp == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (minsize >= 0)
tmp->minsize = minsize;
if (maxsize >= 0)
tmp->maxsize = maxsize;
if (mask)
tmp->mask = mask;
if (flags)
tmp->flags = STABLE_FLAGS_MALLOC | flags;
return 1;
}
void ASN1_STRING_TABLE_cleanup(void)
{
STACK_OF(ASN1_STRING_TABLE) *tmp;
tmp = stable;
if (tmp == NULL)
return;
stable = NULL;
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
}
static void st_free(ASN1_STRING_TABLE *tbl)
{
if (tbl->flags & STABLE_FLAGS_MALLOC)
OPENSSL_free(tbl);
}
diff --git a/crypto/openssl/crypto/asn1/a_time.c b/crypto/openssl/crypto/asn1/a_time.c
index 9b3074e47e84..5ef6d0d1cd1c 100644
--- a/crypto/openssl/crypto/asn1/a_time.c
+++ b/crypto/openssl/crypto/asn1/a_time.c
@@ -1,591 +1,586 @@
/*
- * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 is an implementation of the ASN1 Time structure which is:
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
*/
#include <stdio.h>
#include <time.h>
#include "crypto/asn1.h"
#include "crypto/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include "asn1_local.h"
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_TIME)
static int is_utc(const int year)
{
if (50 <= year && year <= 149)
return 1;
return 0;
}
static int leap_year(const int year)
{
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
return 1;
return 0;
}
/*
* Compute the day of the week and the day of the year from the year, month
* and day. The day of the year is straightforward, the day of the week uses
* a form of Zeller's congruence. For this months start with March and are
* numbered 4 through 15.
*/
static void determine_days(struct tm *tm)
{
static const int ydays[12] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
int y = tm->tm_year + 1900;
int m = tm->tm_mon;
int d = tm->tm_mday;
int c;
tm->tm_yday = ydays[m] + d - 1;
if (m >= 2) {
/* March and onwards can be one day further into the year */
tm->tm_yday += leap_year(y);
m += 2;
} else {
/* Treat January and February as part of the previous year */
m += 14;
y--;
}
c = y / 100;
y %= 100;
/* Zeller's congruence */
tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7;
}
int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
{
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char *a;
int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md;
struct tm tmp;
#if defined(CHARSET_EBCDIC)
const char upper_z = 0x5A, num_zero = 0x30, period = 0x2E, minus = 0x2D, plus = 0x2B;
#else
const char upper_z = 'Z', num_zero = '0', period = '.', minus = '-', plus = '+';
#endif
/*
* ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280
* time string format, in which:
*
* 1. "seconds" is a 'MUST'
* 2. "Zulu" timezone is a 'MUST'
* 3. "+|-" is not allowed to indicate a time zone
*/
if (d->type == V_ASN1_UTCTIME) {
if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
min_l = 13;
strict = 1;
}
} else if (d->type == V_ASN1_GENERALIZEDTIME) {
end = 7;
btz = 6;
if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
min_l = 15;
strict = 1;
} else {
min_l = 13;
}
} else {
return 0;
}
l = d->length;
a = (char *)d->data;
o = 0;
memset(&tmp, 0, sizeof(tmp));
/*
* GENERALIZEDTIME is similar to UTCTIME except the year is represented
* as YYYY. This stuff treats everything as a two digit field so make
* first two fields 00 to 99
*/
if (l < min_l)
goto err;
for (i = 0; i < end; i++) {
if (!strict && (i == btz) && ((a[o] == upper_z) || (a[o] == plus) || (a[o] == minus))) {
i++;
break;
}
if (!ossl_ascii_isdigit(a[o]))
goto err;
n = a[o] - num_zero;
/* incomplete 2-digital number */
if (++o == l)
goto err;
if (!ossl_ascii_isdigit(a[o]))
goto err;
n = (n * 10) + a[o] - num_zero;
/* no more bytes to read, but we haven't seen time-zone yet */
if (++o == l)
goto err;
i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
if ((n < min[i2]) || (n > max[i2]))
goto err;
switch (i2) {
case 0:
/* UTC will never be here */
tmp.tm_year = n * 100 - 1900;
break;
case 1:
if (d->type == V_ASN1_UTCTIME)
tmp.tm_year = n < 50 ? n + 100 : n;
else
tmp.tm_year += n;
break;
case 2:
tmp.tm_mon = n - 1;
break;
case 3:
/* check if tm_mday is valid in tm_mon */
if (tmp.tm_mon == 1) {
/* it's February */
md = mdays[1] + leap_year(tmp.tm_year + 1900);
} else {
md = mdays[tmp.tm_mon];
}
if (n > md)
goto err;
tmp.tm_mday = n;
determine_days(&tmp);
break;
case 4:
tmp.tm_hour = n;
break;
case 5:
tmp.tm_min = n;
break;
case 6:
tmp.tm_sec = n;
break;
}
}
/*
* Optional fractional seconds: decimal point followed by one or more
* digits.
*/
if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == period) {
if (strict)
/* RFC 5280 forbids fractional seconds */
goto err;
if (++o == l)
goto err;
i = o;
while ((o < l) && ossl_ascii_isdigit(a[o]))
o++;
/* Must have at least one digit after decimal point */
if (i == o)
goto err;
/* no more bytes to read, but we haven't seen time-zone yet */
if (o == l)
goto err;
}
/*
* 'o' will never point to '\0' at this point, the only chance
* 'o' can point to '\0' is either the subsequent if or the first
* else if is true.
*/
if (a[o] == upper_z) {
o++;
} else if (!strict && ((a[o] == plus) || (a[o] == minus))) {
int offsign = a[o] == minus ? 1 : -1;
int offset = 0;
o++;
/*
* if not equal, no need to do subsequent checks
* since the following for-loop will add 'o' by 4
* and the final return statement will check if 'l'
* and 'o' are equal.
*/
if (o + 4 != l)
goto err;
for (i = end; i < end + 2; i++) {
if (!ossl_ascii_isdigit(a[o]))
goto err;
n = a[o] - num_zero;
o++;
if (!ossl_ascii_isdigit(a[o]))
goto err;
n = (n * 10) + a[o] - num_zero;
i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
if ((n < min[i2]) || (n > max[i2]))
goto err;
/* if tm is NULL, no need to adjust */
if (tm != NULL) {
if (i == end)
offset = n * 3600;
else if (i == end + 1)
offset += n * 60;
}
o++;
}
if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign))
goto err;
} else {
/* not Z, or not +/- in non-strict mode */
goto err;
}
if (o == l) {
/* success, check if tm should be filled */
if (tm != NULL)
*tm = tmp;
return 1;
}
err:
return 0;
}
ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
{
char* p;
ASN1_TIME *tmps = NULL;
const size_t len = 20;
if (type == V_ASN1_UNDEF) {
if (is_utc(ts->tm_year))
type = V_ASN1_UTCTIME;
else
type = V_ASN1_GENERALIZEDTIME;
} else if (type == V_ASN1_UTCTIME) {
if (!is_utc(ts->tm_year))
goto err;
} else if (type != V_ASN1_GENERALIZEDTIME) {
goto err;
}
if (s == NULL)
tmps = ASN1_STRING_new();
else
tmps = s;
if (tmps == NULL)
return NULL;
if (!ASN1_STRING_set(tmps, NULL, len))
goto err;
tmps->type = type;
p = (char*)tmps->data;
if (type == V_ASN1_GENERALIZEDTIME)
tmps->length = BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ",
ts->tm_year + 1900, ts->tm_mon + 1,
ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
else
tmps->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ",
ts->tm_year % 100, ts->tm_mon + 1,
ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
#ifdef CHARSET_EBCDIC
ebcdic2ascii(tmps->data, tmps->data, tmps->length);
#endif
return tmps;
err:
if (tmps != s)
ASN1_STRING_free(tmps);
return NULL;
}
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
{
return ASN1_TIME_adj(s, t, 0, 0);
}
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
int offset_day, long offset_sec)
{
struct tm *ts;
struct tm data;
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_GETTING_TIME);
return NULL;
}
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL;
}
return ossl_asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
}
int ASN1_TIME_check(const ASN1_TIME *t)
{
if (t->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_check(t);
else if (t->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_check(t);
return 0;
}
/* Convert an ASN1_TIME structure to GeneralizedTime */
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *ret = NULL;
struct tm tm;
if (!ASN1_TIME_to_tm(t, &tm))
return NULL;
if (out != NULL)
ret = *out;
ret = ossl_asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
if (out != NULL && ret != NULL)
*out = ret;
return ret;
}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
/* Try UTC, if that fails, try GENERALIZED */
if (ASN1_UTCTIME_set_string(s, str))
return 1;
return ASN1_GENERALIZEDTIME_set_string(s, str);
}
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
{
ASN1_TIME t;
struct tm tm;
int rv = 0;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = ASN1_STRING_FLAG_X509_TIME;
t.type = V_ASN1_UTCTIME;
if (!ASN1_TIME_check(&t)) {
t.type = V_ASN1_GENERALIZEDTIME;
if (!ASN1_TIME_check(&t))
goto out;
}
/*
* Per RFC 5280 (section 4.1.2.5.), the valid input time
* strings should be encoded with the following rules:
*
* 1. UTC: YYMMDDHHMMSSZ, if YY < 50 (20YY) --> UTC: YYMMDDHHMMSSZ
* 2. UTC: YYMMDDHHMMSSZ, if YY >= 50 (19YY) --> UTC: YYMMDDHHMMSSZ
* 3. G'd: YYYYMMDDHHMMSSZ, if YYYY >= 2050 --> G'd: YYYYMMDDHHMMSSZ
* 4. G'd: YYYYMMDDHHMMSSZ, if YYYY < 2050 --> UTC: YYMMDDHHMMSSZ
*
* Only strings of the 4th rule should be reformatted, but since a
* UTC can only present [1950, 2050), so if the given time string
* is less than 1950 (e.g. 19230419000000Z), we do nothing...
*/
if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) {
if (!ossl_asn1_time_to_tm(&tm, &t))
goto out;
if (is_utc(tm.tm_year)) {
t.length -= 2;
/*
* it's OK to let original t.data go since that's assigned
* to a piece of memory allocated outside of this function.
* new t.data would be freed after ASN1_STRING_copy is done.
*/
t.data = OPENSSL_zalloc(t.length + 1);
if (t.data == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto out;
}
memcpy(t.data, str + 2, t.length);
t.type = V_ASN1_UTCTIME;
}
}
if (s == NULL || ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
rv = 1;
if (t.data != (unsigned char *)str)
OPENSSL_free(t.data);
out:
return rv;
}
int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
{
if (s == NULL) {
time_t now_t;
time(&now_t);
memset(tm, 0, sizeof(*tm));
if (OPENSSL_gmtime(&now_t, tm) != NULL)
return 1;
return 0;
}
return ossl_asn1_time_to_tm(tm, s);
}
int ASN1_TIME_diff(int *pday, int *psec,
const ASN1_TIME *from, const ASN1_TIME *to)
{
struct tm tm_from, tm_to;
if (!ASN1_TIME_to_tm(from, &tm_from))
return 0;
if (!ASN1_TIME_to_tm(to, &tm_to))
return 0;
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
}
static const char _asn1_mon[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
/* prints the time with the default date format (RFC 822) */
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
{
return ASN1_TIME_print_ex(bp, tm, ASN1_DTFLGS_RFC822);
}
/* returns 1 on success, 0 on BIO write error or parse failure */
int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
{
return ossl_asn1_time_print_ex(bp, tm, flags) > 0;
}
/* prints the time with the date format of ISO 8601 */
/* returns 0 on BIO write error, else -1 in case of parse failure, else 1 */
int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
{
char *v;
- int gmt = 0, l;
+ int l;
struct tm stm;
- const char upper_z = 0x5A, period = 0x2E;
+ const char period = 0x2E;
/* ossl_asn1_time_to_tm will check the time type */
if (!ossl_asn1_time_to_tm(&stm, tm))
return BIO_write(bp, "Bad time value", 14) ? -1 : 0;
l = tm->length;
v = (char *)tm->data;
- if (v[l - 1] == upper_z)
- gmt = 1;
if (tm->type == V_ASN1_GENERALIZEDTIME) {
char *f = NULL;
int f_len = 0;
/*
* Try to parse fractional seconds. '14' is the place of
* 'fraction point' in a GeneralizedTime string.
*/
if (tm->length > 15 && v[14] == period) {
- f = &v[14];
- f_len = 1;
- while (14 + f_len < l && ossl_ascii_isdigit(f[f_len]))
+ /* exclude the . itself */
+ f = &v[15];
+ f_len = 0;
+ while (15 + f_len < l && ossl_ascii_isdigit(f[f_len]))
++f_len;
}
- if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
- return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%.*s%s",
- stm.tm_year + 1900, stm.tm_mon + 1,
- stm.tm_mday, stm.tm_hour,
- stm.tm_min, stm.tm_sec, f_len, f,
- (gmt ? "Z" : "")) > 0;
- }
- else {
- return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
- _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
- stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900,
- (gmt ? " GMT" : "")) > 0;
+ if (f_len > 0) {
+ if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+ return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d.%.*sZ",
+ stm.tm_year + 1900, stm.tm_mon + 1,
+ stm.tm_mday, stm.tm_hour,
+ stm.tm_min, stm.tm_sec, f_len, f) > 0;
+ } else {
+ return BIO_printf(bp, "%s %2d %02d:%02d:%02d.%.*s %d GMT",
+ _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
+ stm.tm_min, stm.tm_sec, f_len, f,
+ stm.tm_year + 1900) > 0;
+ }
}
- } else {
- if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
- return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%s",
+ }
+ if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+ return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02dZ",
stm.tm_year + 1900, stm.tm_mon + 1,
stm.tm_mday, stm.tm_hour,
- stm.tm_min, stm.tm_sec,
- (gmt ? "Z" : "")) > 0;
- }
- else {
- return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
+ stm.tm_min, stm.tm_sec) > 0;
+ } else {
+ return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d GMT",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
- stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
- (gmt ? " GMT" : "")) > 0;
- }
+ stm.tm_min, stm.tm_sec, stm.tm_year + 1900) > 0;
}
}
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
{
struct tm stm, ttm;
int day, sec;
if (!ASN1_TIME_to_tm(s, &stm))
return -2;
if (!OPENSSL_gmtime(&t, &ttm))
return -2;
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2;
if (day > 0 || sec > 0)
return 1;
if (day < 0 || sec < 0)
return -1;
return 0;
}
int ASN1_TIME_normalize(ASN1_TIME *t)
{
struct tm tm;
if (!ASN1_TIME_to_tm(t, &tm))
return 0;
return ossl_asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
}
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b)
{
int day, sec;
if (!ASN1_TIME_diff(&day, &sec, b, a))
return -2;
if (day > 0 || sec > 0)
return 1;
if (day < 0 || sec < 0)
return -1;
return 0;
}
diff --git a/crypto/openssl/crypto/asn1/asn1_gen.c b/crypto/openssl/crypto/asn1/asn1_gen.c
index 402ab34e6a46..152dc870a558 100644
--- a/crypto/openssl/crypto/asn1/asn1_gen.c
+++ b/crypto/openssl/crypto/asn1/asn1_gen.c
@@ -1,789 +1,790 @@
/*
- * Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/asn1.h>
#include <openssl/x509v3.h>
#define ASN1_GEN_FLAG 0x10000
#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1)
#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2)
#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3)
#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4)
#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5)
#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6)
#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7)
#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8)
#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val}
#define ASN1_FLAG_EXP_MAX 20
/* Maximum number of nested sequences */
#define ASN1_GEN_SEQ_MAX_DEPTH 50
/* Input formats */
/* ASCII: default */
#define ASN1_GEN_FORMAT_ASCII 1
/* UTF8 */
#define ASN1_GEN_FORMAT_UTF8 2
/* Hex */
#define ASN1_GEN_FORMAT_HEX 3
/* List of bits */
#define ASN1_GEN_FORMAT_BITLIST 4
struct tag_name_st {
const char *strnam;
int len;
int tag;
};
typedef struct {
int exp_tag;
int exp_class;
int exp_constructed;
int exp_pad;
long exp_len;
} tag_exp_type;
typedef struct {
int imp_tag;
int imp_class;
int utype;
int format;
const char *str;
tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
int exp_count;
} tag_exp_arg;
static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
int *perr);
static int bitstr_cb(const char *elem, int len, void *bitstr);
static int asn1_cb(const char *elem, int len, void *bitstr);
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
int exp_constructed, int exp_pad, int imp_ok);
static int parse_tagging(const char *vstart, int vlen, int *ptag,
int *pclass);
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
int depth, int *perr);
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
static int asn1_str2tag(const char *tagstr, int len);
ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf)
{
X509V3_CTX cnf;
if (!nconf)
return ASN1_generate_v3(str, NULL);
X509V3_set_nconf(&cnf, nconf);
return ASN1_generate_v3(str, &cnf);
}
ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
{
int err = 0;
ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err);
if (err)
ERR_raise(ERR_LIB_ASN1, err);
return ret;
}
static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
int *perr)
{
ASN1_TYPE *ret;
tag_exp_arg asn1_tags;
tag_exp_type *etmp;
int i, len;
unsigned char *orig_der = NULL, *new_der = NULL;
const unsigned char *cpy_start;
unsigned char *p;
const unsigned char *cp;
int cpy_len;
long hdr_len = 0;
int hdr_constructed = 0, hdr_tag, hdr_class;
int r;
asn1_tags.imp_tag = -1;
asn1_tags.imp_class = -1;
asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
asn1_tags.exp_count = 0;
if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) {
*perr = ASN1_R_UNKNOWN_TAG;
return NULL;
}
if ((asn1_tags.utype == V_ASN1_SEQUENCE)
|| (asn1_tags.utype == V_ASN1_SET)) {
if (!cnf) {
*perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG;
return NULL;
}
if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) {
*perr = ASN1_R_ILLEGAL_NESTED_TAGGING;
return NULL;
}
ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr);
} else
ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
if (!ret)
return NULL;
/* If no tagging return base type */
if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
return ret;
/* Generate the encoding */
cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
ASN1_TYPE_free(ret);
ret = NULL;
/* Set point to start copying for modified encoding */
cpy_start = orig_der;
/* Do we need IMPLICIT tagging? */
if (asn1_tags.imp_tag != -1) {
/* If IMPLICIT we will replace the underlying tag */
/* Skip existing tag+len */
r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class,
cpy_len);
if (r & 0x80)
goto err;
/* Update copy length */
cpy_len -= cpy_start - orig_der;
/*
* For IMPLICIT tagging the length should match the original length
* and constructed flag should be consistent.
*/
if (r & 0x1) {
/* Indefinite length constructed */
hdr_constructed = 2;
hdr_len = 0;
} else
/* Just retain constructed flag */
hdr_constructed = r & V_ASN1_CONSTRUCTED;
/*
* Work out new length with IMPLICIT tag: ignore constructed because
* it will mess up if indefinite length
*/
len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
} else
len = cpy_len;
/* Work out length in any EXPLICIT, starting from end */
for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1;
i < asn1_tags.exp_count; i++, etmp--) {
/* Content length: number of content octets + any padding */
len += etmp->exp_pad;
etmp->exp_len = len;
/* Total object length: length including new header */
len = ASN1_object_size(0, len, etmp->exp_tag);
}
/* Allocate buffer for new encoding */
new_der = OPENSSL_malloc(len);
if (new_der == NULL)
goto err;
/* Generate tagged encoding */
p = new_der;
/* Output explicit tags first */
for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count;
i++, etmp++) {
ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
etmp->exp_tag, etmp->exp_class);
if (etmp->exp_pad)
*p++ = 0;
}
/* If IMPLICIT, output tag */
if (asn1_tags.imp_tag != -1) {
if (asn1_tags.imp_class == V_ASN1_UNIVERSAL
&& (asn1_tags.imp_tag == V_ASN1_SEQUENCE
|| asn1_tags.imp_tag == V_ASN1_SET))
hdr_constructed = V_ASN1_CONSTRUCTED;
ASN1_put_object(&p, hdr_constructed, hdr_len,
asn1_tags.imp_tag, asn1_tags.imp_class);
}
/* Copy across original encoding */
memcpy(p, cpy_start, cpy_len);
cp = new_der;
/* Obtain new ASN1_TYPE structure */
ret = d2i_ASN1_TYPE(NULL, &cp, len);
err:
OPENSSL_free(orig_der);
OPENSSL_free(new_der);
return ret;
}
static int asn1_cb(const char *elem, int len, void *bitstr)
{
tag_exp_arg *arg = bitstr;
int i;
int utype;
int vlen = 0;
const char *p, *vstart = NULL;
int tmp_tag, tmp_class;
if (elem == NULL)
return -1;
for (i = 0, p = elem; i < len; p++, i++) {
/* Look for the ':' in name value pairs */
if (*p == ':') {
vstart = p + 1;
vlen = len - (vstart - elem);
len = p - elem;
break;
}
}
utype = asn1_str2tag(elem, len);
if (utype == -1) {
ERR_raise_data(ERR_LIB_ASN1, ASN1_R_UNKNOWN_TAG, "tag=%s", elem);
return -1;
}
/* If this is not a modifier mark end of string and exit */
if (!(utype & ASN1_GEN_FLAG)) {
arg->utype = utype;
arg->str = vstart;
/* If no value and not end of string, error */
if (!vstart && elem[len]) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_VALUE);
return -1;
}
return 0;
}
switch (utype) {
case ASN1_GEN_FLAG_IMP:
/* Check for illegal multiple IMPLICIT tagging */
if (arg->imp_tag != -1) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING);
return -1;
}
if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
return -1;
break;
case ASN1_GEN_FLAG_EXP:
if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
return -1;
if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
return -1;
break;
case ASN1_GEN_FLAG_SEQWRAP:
if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_SETWRAP:
if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_BITWRAP:
if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
return -1;
break;
case ASN1_GEN_FLAG_OCTWRAP:
if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_FORMAT:
if (!vstart) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if (strncmp(vstart, "ASCII", 5) == 0)
arg->format = ASN1_GEN_FORMAT_ASCII;
else if (strncmp(vstart, "UTF8", 4) == 0)
arg->format = ASN1_GEN_FORMAT_UTF8;
else if (strncmp(vstart, "HEX", 3) == 0)
arg->format = ASN1_GEN_FORMAT_HEX;
else if (strncmp(vstart, "BITLIST", 7) == 0)
arg->format = ASN1_GEN_FORMAT_BITLIST;
else {
ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
break;
}
return 1;
}
static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
{
long tag_num;
char *eptr;
if (!vstart)
return 0;
tag_num = strtoul(vstart, &eptr, 10);
/* Check we haven't gone past max length: should be impossible */
if (eptr && *eptr && (eptr > vstart + vlen))
return 0;
if (tag_num < 0) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER);
return 0;
}
*ptag = tag_num;
/* If we have non numeric characters, parse them */
if (eptr)
vlen -= eptr - vstart;
else
vlen = 0;
if (vlen) {
switch (*eptr) {
case 'U':
*pclass = V_ASN1_UNIVERSAL;
break;
case 'A':
*pclass = V_ASN1_APPLICATION;
break;
case 'P':
*pclass = V_ASN1_PRIVATE;
break;
case 'C':
*pclass = V_ASN1_CONTEXT_SPECIFIC;
break;
default:
ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MODIFIER,
"Char=%c", *eptr);
return 0;
}
} else
*pclass = V_ASN1_CONTEXT_SPECIFIC;
return 1;
}
/* Handle multiple types: SET and SEQUENCE */
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
int depth, int *perr)
{
ASN1_TYPE *ret = NULL;
STACK_OF(ASN1_TYPE) *sk = NULL;
STACK_OF(CONF_VALUE) *sect = NULL;
unsigned char *der = NULL;
int derlen;
int i;
sk = sk_ASN1_TYPE_new_null();
if (!sk)
goto bad;
if (section) {
if (!cnf)
goto bad;
sect = X509V3_get_section(cnf, (char *)section);
if (!sect)
goto bad;
for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
ASN1_TYPE *typ =
generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf,
depth + 1, perr);
if (!typ)
goto bad;
if (!sk_ASN1_TYPE_push(sk, typ))
goto bad;
}
}
/*
* Now we has a STACK of the components, convert to the correct form
*/
if (utype == V_ASN1_SET)
derlen = i2d_ASN1_SET_ANY(sk, &der);
else
derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
if (derlen < 0)
goto bad;
if ((ret = ASN1_TYPE_new()) == NULL)
goto bad;
if ((ret->value.asn1_string = ASN1_STRING_type_new(utype)) == NULL)
goto bad;
ret->type = utype;
ret->value.asn1_string->data = der;
ret->value.asn1_string->length = derlen;
der = NULL;
bad:
OPENSSL_free(der);
sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
X509V3_section_free(cnf, sect);
return ret;
}
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
int exp_constructed, int exp_pad, int imp_ok)
{
tag_exp_type *exp_tmp;
/* Can only have IMPLICIT if permitted */
if ((arg->imp_tag != -1) && !imp_ok) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG);
return 0;
}
if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_DEPTH_EXCEEDED);
return 0;
}
exp_tmp = &arg->exp_list[arg->exp_count++];
/*
* If IMPLICIT set tag to implicit value then reset implicit tag since it
* has been used.
*/
if (arg->imp_tag != -1) {
exp_tmp->exp_tag = arg->imp_tag;
exp_tmp->exp_class = arg->imp_class;
arg->imp_tag = -1;
arg->imp_class = -1;
} else {
exp_tmp->exp_tag = exp_tag;
exp_tmp->exp_class = exp_class;
}
exp_tmp->exp_constructed = exp_constructed;
exp_tmp->exp_pad = exp_pad;
return 1;
}
static int asn1_str2tag(const char *tagstr, int len)
{
unsigned int i;
- static const struct tag_name_st *tntmp, tnst[] = {
+ const struct tag_name_st *tntmp;
+ static const struct tag_name_st tnst[] = {
ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
ASN1_GEN_STR("NULL", V_ASN1_NULL),
ASN1_GEN_STR("INT", V_ASN1_INTEGER),
ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
ASN1_GEN_STR("OID", V_ASN1_OBJECT),
ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
ASN1_GEN_STR("T61", V_ASN1_T61STRING),
ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
/* Special cases */
ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
ASN1_GEN_STR("SET", V_ASN1_SET),
/* type modifiers */
/* Explicit tag */
ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
/* Implicit tag */
ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
/* OCTET STRING wrapper */
ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
/* SEQUENCE wrapper */
ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
/* SET wrapper */
ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
/* BIT STRING wrapper */
ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
};
if (len == -1)
len = strlen(tagstr);
tntmp = tnst;
for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) {
if ((len == tntmp->len)
&& (OPENSSL_strncasecmp(tntmp->strnam, tagstr, len) == 0))
return tntmp->tag;
}
return -1;
}
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
{
ASN1_TYPE *atmp = NULL;
CONF_VALUE vtmp;
unsigned char *rdata;
long rdlen;
int no_unused = 1;
if ((atmp = ASN1_TYPE_new()) == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!str)
str = "";
switch (utype) {
case V_ASN1_NULL:
if (str && *str) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL_VALUE);
goto bad_form;
}
break;
case V_ASN1_BOOLEAN:
if (format != ASN1_GEN_FORMAT_ASCII) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ASCII_FORMAT);
goto bad_form;
}
vtmp.name = NULL;
vtmp.section = NULL;
vtmp.value = (char *)str;
if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BOOLEAN);
goto bad_str;
}
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
if (format != ASN1_GEN_FORMAT_ASCII) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.integer
= s2i_ASN1_INTEGER(NULL, str)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_INTEGER);
goto bad_str;
}
break;
case V_ASN1_OBJECT:
if (format != ASN1_GEN_FORMAT_ASCII) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT);
goto bad_str;
}
break;
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
if (format != ASN1_GEN_FORMAT_ASCII) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
atmp->value.asn1_string->type = utype;
if (!ASN1_TIME_check(atmp->value.asn1_string)) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_TIME_VALUE);
goto bad_str;
}
break;
case V_ASN1_BMPSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_IA5STRING:
case V_ASN1_T61STRING:
case V_ASN1_UTF8STRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_NUMERICSTRING:
if (format == ASN1_GEN_FORMAT_ASCII)
format = MBSTRING_ASC;
else if (format == ASN1_GEN_FORMAT_UTF8)
format = MBSTRING_UTF8;
else {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_FORMAT);
goto bad_form;
}
if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
-1, format, ASN1_tag2bit(utype)) <= 0) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
break;
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_form;
}
if (format == ASN1_GEN_FORMAT_HEX) {
if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_HEX);
goto bad_str;
}
atmp->value.asn1_string->data = rdata;
atmp->value.asn1_string->length = rdlen;
atmp->value.asn1_string->type = utype;
} else if (format == ASN1_GEN_FORMAT_ASCII) {
if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
} else if ((format == ASN1_GEN_FORMAT_BITLIST)
&& (utype == V_ASN1_BIT_STRING)) {
if (!CONF_parse_list
(str, ',', 1, bitstr_cb, atmp->value.bit_string)) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_LIST_ERROR);
goto bad_str;
}
no_unused = 0;
} else {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
goto bad_form;
}
if ((utype == V_ASN1_BIT_STRING) && no_unused) {
atmp->value.asn1_string->flags
&= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT;
}
break;
default:
ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
goto bad_str;
}
atmp->type = utype;
return atmp;
bad_str:
ERR_add_error_data(2, "string=", str);
bad_form:
ASN1_TYPE_free(atmp);
return NULL;
}
static int bitstr_cb(const char *elem, int len, void *bitstr)
{
long bitnum;
char *eptr;
if (!elem)
return 0;
bitnum = strtoul(elem, &eptr, 10);
if (eptr && *eptr && (eptr != elem + len))
return 0;
if (bitnum < 0) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER);
return 0;
}
if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
static int mask_cb(const char *elem, int len, void *arg)
{
unsigned long *pmask = arg, tmpmask;
int tag;
if (elem == NULL)
return 0;
if ((len == 3) && (strncmp(elem, "DIR", 3) == 0)) {
*pmask |= B_ASN1_DIRECTORYSTRING;
return 1;
}
tag = asn1_str2tag(elem, len);
if (!tag || (tag & ASN1_GEN_FLAG))
return 0;
tmpmask = ASN1_tag2bit(tag);
if (!tmpmask)
return 0;
*pmask |= tmpmask;
return 1;
}
int ASN1_str2mask(const char *str, unsigned long *pmask)
{
*pmask = 0;
return CONF_parse_list(str, '|', 1, mask_cb, pmask);
}
diff --git a/crypto/openssl/crypto/asn1/asn_mime.c b/crypto/openssl/crypto/asn1/asn_mime.c
index 9fc52d047626..8bb7089292d0 100644
--- a/crypto/openssl/crypto/asn1/asn_mime.c
+++ b/crypto/openssl/crypto/asn1/asn_mime.c
@@ -1,1036 +1,1038 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 "crypto/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/cms.h>
#include "crypto/evp.h"
#include "internal/bio.h"
#include "asn1_local.h"
/*
* Generalised MIME like utilities for streaming ASN1. Although many have a
* PKCS7/CMS like flavour others are more general purpose.
*/
/*
* MIME format structures Note that all are translated to lower case apart
* from parameter values. Quotes are stripped off
*/
struct mime_param_st {
char *param_name; /* Param name e.g. "micalg" */
char *param_value; /* Param value e.g. "sha1" */
};
struct mime_header_st {
char *name; /* Name of line e.g. "content-type" */
char *value; /* Value of line e.g. "text/plain" */
STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */
};
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
const ASN1_ITEM *it);
static char *strip_ends(char *name);
static char *strip_start(char *name);
static char *strip_end(char *name);
static MIME_HEADER *mime_hdr_new(const char *name, const char *value);
static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value);
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio);
static int mime_hdr_cmp(const MIME_HEADER *const *a,
const MIME_HEADER *const *b);
static int mime_param_cmp(const MIME_PARAM *const *a,
const MIME_PARAM *const *b);
static void mime_param_free(MIME_PARAM *param);
static int mime_bound_check(char *line, int linelen, const char *bound, int blen);
static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO) **ret);
static int strip_eol(char *linebuf, int *plen, int flags);
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name);
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name);
static void mime_hdr_free(MIME_HEADER *hdr);
#define MAX_SMLEN 1024
#define mime_debug(x) /* x */
/* Output an ASN1 structure in BER format streaming if necessary */
/* unfortunately cannot constify this due to CMS_stream() and PKCS7_stream() */
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const ASN1_ITEM *it)
{
int rv = 1;
/* If streaming create stream BIO and copy all content through it */
if (flags & SMIME_STREAM) {
BIO *bio, *tbio;
bio = BIO_new_NDEF(out, val, it);
if (!bio) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!SMIME_crlf_copy(in, bio, flags)) {
rv = 0;
}
(void)BIO_flush(bio);
/* Free up successive BIOs until we hit the old output BIO */
do {
tbio = BIO_pop(bio);
BIO_free(bio);
bio = tbio;
} while (bio != out);
}
/*
* else just write out ASN1 structure which will have all content stored
* internally
*/
else
ASN1_item_i2d_bio(it, out, val);
return rv;
}
/* Base 64 read and write of ASN1 structure */
static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const ASN1_ITEM *it)
{
BIO *b64;
int r;
b64 = BIO_new(BIO_f_base64());
if (b64 == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
* prepend the b64 BIO so all data is base64 encoded.
*/
out = BIO_push(b64, out);
r = i2d_ASN1_bio_stream(out, val, in, flags, it);
(void)BIO_flush(out);
BIO_pop(out);
BIO_free(b64);
return r;
}
/* Streaming ASN1 PEM write */
int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const char *hdr, const ASN1_ITEM *it)
{
int r;
BIO_printf(out, "-----BEGIN %s-----\n", hdr);
r = B64_write_ASN1(out, val, in, flags, it);
BIO_printf(out, "-----END %s-----\n", hdr);
return r;
}
static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x,
OSSL_LIB_CTX *libctx, const char *propq)
{
BIO *b64;
ASN1_VALUE *val;
if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
bio = BIO_push(b64, bio);
val = ASN1_item_d2i_bio_ex(it, bio, x, libctx, propq);
if (!val)
ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR);
(void)BIO_flush(bio);
BIO_pop(bio);
BIO_free(b64);
return val;
}
/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
{
const EVP_MD *md;
int i, have_unknown = 0, write_comma, ret = 0, md_nid;
have_unknown = 0;
write_comma = 0;
for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) {
if (write_comma)
BIO_write(out, ",", 1);
write_comma = 1;
md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm);
md = EVP_get_digestbynid(md_nid);
if (md && md->md_ctrl) {
int rv;
char *micstr;
rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr);
if (rv > 0) {
BIO_puts(out, micstr);
OPENSSL_free(micstr);
continue;
}
if (rv != -2)
goto err;
}
switch (md_nid) {
case NID_sha1:
BIO_puts(out, "sha1");
break;
case NID_md5:
BIO_puts(out, "md5");
break;
case NID_sha256:
BIO_puts(out, "sha-256");
break;
case NID_sha384:
BIO_puts(out, "sha-384");
break;
case NID_sha512:
BIO_puts(out, "sha-512");
break;
case NID_id_GostR3411_94:
BIO_puts(out, "gostr3411-94");
goto err;
case NID_id_GostR3411_2012_256:
BIO_puts(out, "gostr3411-2012-256");
goto err;
case NID_id_GostR3411_2012_512:
BIO_puts(out, "gostr3411-2012-512");
goto err;
default:
if (have_unknown) {
write_comma = 0;
} else {
BIO_puts(out, "unknown");
have_unknown = 1;
}
break;
}
}
ret = 1;
err:
return ret;
}
/* SMIME sender */
int SMIME_write_ASN1_ex(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
int ctype_nid, int econt_nid,
STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it,
OSSL_LIB_CTX *libctx, const char *propq)
{
char bound[33], c;
int i;
const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
const char *msg_type = NULL;
if (flags & SMIME_OLDMIME)
mime_prefix = "application/x-pkcs7-";
else
mime_prefix = "application/pkcs7-";
if (flags & SMIME_CRLFEOL)
mime_eol = "\r\n";
else
mime_eol = "\n";
if ((flags & SMIME_DETACHED) && data) {
/* We want multipart/signed */
/* Generate a random boundary */
if (RAND_bytes_ex(libctx, (unsigned char *)bound, 32, 0) <= 0)
return 0;
for (i = 0; i < 32; i++) {
c = bound[i] & 0xf;
if (c < 10)
c += '0';
else
c += 'A' - 10;
bound[i] = c;
}
bound[32] = 0;
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
BIO_printf(bio, "Content-Type: multipart/signed;");
BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
BIO_puts(bio, " micalg=\"");
asn1_write_micalg(bio, mdalgs);
BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
bound, mime_eol, mime_eol);
BIO_printf(bio, "This is an S/MIME signed message%s%s",
mime_eol, mime_eol);
/* Now write out the first part */
BIO_printf(bio, "------%s%s", bound, mime_eol);
if (!asn1_output_data(bio, data, val, flags, it))
return 0;
BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
/* Headers for signature */
BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
BIO_printf(bio, "Content-Transfer-Encoding: base64%s", mime_eol);
BIO_printf(bio, "Content-Disposition: attachment;");
BIO_printf(bio, " filename=\"smime.p7s\"%s%s", mime_eol, mime_eol);
B64_write_ASN1(bio, val, NULL, 0, it);
BIO_printf(bio, "%s------%s--%s%s", mime_eol, bound,
mime_eol, mime_eol);
return 1;
}
/* Determine smime-type header */
if (ctype_nid == NID_pkcs7_enveloped) {
msg_type = "enveloped-data";
+ } else if (ctype_nid == NID_id_smime_ct_authEnvelopedData) {
+ msg_type = "authEnveloped-data";
} else if (ctype_nid == NID_pkcs7_signed) {
if (econt_nid == NID_id_smime_ct_receipt)
msg_type = "signed-receipt";
else if (sk_X509_ALGOR_num(mdalgs) >= 0)
msg_type = "signed-data";
else
msg_type = "certs-only";
} else if (ctype_nid == NID_id_smime_ct_compressedData) {
msg_type = "compressed-data";
cname = "smime.p7z";
}
/* MIME headers */
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
BIO_printf(bio, "Content-Disposition: attachment;");
BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol);
BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
if (msg_type)
BIO_printf(bio, " smime-type=%s;", msg_type);
BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
mime_eol, mime_eol);
if (!B64_write_ASN1(bio, val, data, flags, it))
return 0;
BIO_printf(bio, "%s", mime_eol);
return 1;
}
int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
int ctype_nid, int econt_nid,
STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
{
return SMIME_write_ASN1_ex(bio, val, data, flags, ctype_nid, econt_nid,
mdalgs, it, NULL, NULL);
}
/* Handle output of ASN1 data */
/* cannot constify val because of CMS_dataFinal() */
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
const ASN1_ITEM *it)
{
BIO *tmpbio;
const ASN1_AUX *aux = it->funcs;
ASN1_STREAM_ARG sarg;
int rv = 1;
/*
* If data is not detached or resigning then the output BIO is already
* set up to finalise when it is written through.
*/
if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) {
return SMIME_crlf_copy(data, out, flags);
}
if (!aux || !aux->asn1_cb) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
return 0;
}
sarg.out = out;
sarg.ndef_bio = NULL;
sarg.boundary = NULL;
/* Let ASN1 code prepend any needed BIOs */
if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0)
return 0;
/* Copy data across, passing through filter BIOs for processing */
if (!SMIME_crlf_copy(data, sarg.ndef_bio, flags))
rv = 0;
/* Finalize structure */
if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
rv = 0;
/* Now remove any digests prepended to the BIO */
while (sarg.ndef_bio != out) {
tmpbio = BIO_pop(sarg.ndef_bio);
BIO_free(sarg.ndef_bio);
sarg.ndef_bio = tmpbio;
}
return rv;
}
/*
* SMIME reader: handle multipart/signed and opaque signing. in multipart
* case the content is placed in a memory BIO pointed to by "bcont". In
* opaque this is set to NULL
*/
ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont,
const ASN1_ITEM *it, ASN1_VALUE **x,
OSSL_LIB_CTX *libctx, const char *propq)
{
BIO *asnin;
STACK_OF(MIME_HEADER) *headers = NULL;
STACK_OF(BIO) *parts = NULL;
MIME_HEADER *hdr;
MIME_PARAM *prm;
ASN1_VALUE *val;
int ret;
if (bcont)
*bcont = NULL;
if ((headers = mime_parse_hdr(bio)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR);
return NULL;
}
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_CONTENT_TYPE);
return NULL;
}
/* Handle multipart/signed */
if (strcmp(hdr->value, "multipart/signed") == 0) {
/* Split into two parts */
prm = mime_param_find(hdr, "boundary");
if (prm == NULL || prm->param_value == NULL) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
return NULL;
}
ret = multi_split(bio, flags, prm->param_value, &parts);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
if (!ret || (sk_BIO_num(parts) != 2)) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
/* Parse the signature piece */
asnin = sk_BIO_value(parts, 1);
if ((headers = mime_parse_hdr(asnin)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
/* Get content type */
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
strcmp(hdr->value, "application/pkcs7-signature")) {
ERR_raise_data(ERR_LIB_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE,
"type: %s", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
/* Read in ASN1 */
if ((val = b64_read_asn1(asnin, it, x, libctx, propq)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
if (bcont) {
*bcont = sk_BIO_value(parts, 0);
BIO_free(asnin);
sk_BIO_free(parts);
} else {
sk_BIO_pop_free(parts, BIO_vfree);
}
return val;
}
/* OK, if not multipart/signed try opaque signature */
if (strcmp(hdr->value, "application/x-pkcs7-mime") &&
strcmp(hdr->value, "application/pkcs7-mime")) {
ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE,
"type: %s", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return NULL;
}
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
if ((val = b64_read_asn1(bio, it, x, libctx, propq)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR);
return NULL;
}
return val;
}
ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
{
return SMIME_read_ASN1_ex(bio, 0, bcont, it, NULL, NULL, NULL);
}
/* Copy text from one BIO to another making the output CRLF at EOL */
int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
{
BIO *bf;
char eol;
int len;
char linebuf[MAX_SMLEN];
int ret;
if (in == NULL || out == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/*
* Buffer output so we don't write one line at a time. This is useful
* when streaming as we don't end up with one OCTET STRING per line.
*/
bf = BIO_new(BIO_f_buffer());
if (bf == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
out = BIO_push(bf, out);
if (flags & SMIME_BINARY) {
while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
BIO_write(out, linebuf, len);
} else {
int eolcnt = 0;
if (flags & SMIME_TEXT)
BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
eol = strip_eol(linebuf, &len, flags);
if (len > 0) {
/* Not EOF: write out all CRLF */
if (flags & SMIME_ASCIICRLF) {
int i;
for (i = 0; i < eolcnt; i++)
BIO_write(out, "\r\n", 2);
eolcnt = 0;
}
BIO_write(out, linebuf, len);
if (eol)
BIO_write(out, "\r\n", 2);
} else if (flags & SMIME_ASCIICRLF) {
eolcnt++;
} else if (eol) {
BIO_write(out, "\r\n", 2);
}
}
}
ret = BIO_flush(out);
BIO_pop(out);
BIO_free(bf);
if (ret <= 0)
return 0;
return 1;
}
/* Strip off headers if they are text/plain */
int SMIME_text(BIO *in, BIO *out)
{
char iobuf[4096];
int len;
STACK_OF(MIME_HEADER) *headers;
MIME_HEADER *hdr;
if ((headers = mime_parse_hdr(in)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR);
return 0;
}
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_NO_CONTENT_TYPE);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return 0;
}
if (strcmp(hdr->value, "text/plain")) {
ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE,
"type: %s", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return 0;
}
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
BIO_write(out, iobuf, len);
if (len < 0)
return 0;
return 1;
}
/*
* Split a multipart/XXX message body into component parts: result is
* canonical parts in a STACK of bios
*/
static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO) **ret)
{
char linebuf[MAX_SMLEN];
int len, blen;
int eol = 0, next_eol = 0;
BIO *bpart = NULL;
STACK_OF(BIO) *parts;
char state, part, first;
blen = strlen(bound);
part = 0;
state = 0;
first = 1;
parts = sk_BIO_new_null();
*ret = parts;
if (*ret == NULL)
return 0;
while ((len = BIO_get_line(bio, linebuf, MAX_SMLEN)) > 0) {
state = mime_bound_check(linebuf, len, bound, blen);
if (state == 1) {
first = 1;
part++;
} else if (state == 2) {
if (!sk_BIO_push(parts, bpart)) {
BIO_free(bpart);
return 0;
}
return 1;
} else if (part != 0) {
/* Strip (possibly CR +) LF from linebuf */
next_eol = strip_eol(linebuf, &len, flags);
if (first) {
first = 0;
if (bpart)
if (!sk_BIO_push(parts, bpart)) {
BIO_free(bpart);
return 0;
}
bpart = BIO_new(BIO_s_mem());
if (bpart == NULL)
return 0;
BIO_set_mem_eof_return(bpart, 0);
} else if (eol) {
if (
#ifndef OPENSSL_NO_CMS
(flags & CMS_BINARY) == 0
#else
1
#endif
|| (flags & SMIME_CRLFEOL) != 0)
BIO_write(bpart, "\r\n", 2);
else
BIO_write(bpart, "\n", 1);
}
eol = next_eol;
if (len > 0)
BIO_write(bpart, linebuf, len);
}
}
BIO_free(bpart);
return 0;
}
/* This is the big one: parse MIME header lines up to message body */
#define MIME_INVALID 0
#define MIME_START 1
#define MIME_TYPE 2
#define MIME_NAME 3
#define MIME_VALUE 4
#define MIME_QUOTE 5
#define MIME_COMMENT 6
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
{
char *p, *q, c;
char *ntmp;
char linebuf[MAX_SMLEN];
MIME_HEADER *mhdr = NULL, *new_hdr = NULL;
STACK_OF(MIME_HEADER) *headers;
int len, state, save_state = 0;
headers = sk_MIME_HEADER_new(mime_hdr_cmp);
if (headers == NULL)
return NULL;
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
/* If whitespace at line start then continuation line */
if (mhdr && ossl_isspace(linebuf[0]))
state = MIME_NAME;
else
state = MIME_START;
ntmp = NULL;
/* Go through all characters */
for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
p++) {
/*
* State machine to handle MIME headers if this looks horrible
* that's because it *is*
*/
switch (state) {
case MIME_START:
if (c == ':') {
state = MIME_TYPE;
*p = 0;
ntmp = strip_ends(q);
q = p + 1;
}
break;
case MIME_TYPE:
if (c == ';') {
mime_debug("Found End Value\n");
*p = 0;
new_hdr = mime_hdr_new(ntmp, strip_ends(q));
if (new_hdr == NULL)
goto err;
if (!sk_MIME_HEADER_push(headers, new_hdr))
goto err;
mhdr = new_hdr;
new_hdr = NULL;
ntmp = NULL;
q = p + 1;
state = MIME_NAME;
} else if (c == '(') {
save_state = state;
state = MIME_COMMENT;
}
break;
case MIME_COMMENT:
if (c == ')') {
state = save_state;
}
break;
case MIME_NAME:
if (c == '=') {
state = MIME_VALUE;
*p = 0;
ntmp = strip_ends(q);
q = p + 1;
}
break;
case MIME_VALUE:
if (c == ';') {
state = MIME_NAME;
*p = 0;
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
ntmp = NULL;
q = p + 1;
} else if (c == '"') {
mime_debug("Found Quote\n");
state = MIME_QUOTE;
} else if (c == '(') {
save_state = state;
state = MIME_COMMENT;
}
break;
case MIME_QUOTE:
if (c == '"') {
mime_debug("Found Match Quote\n");
state = MIME_VALUE;
}
break;
}
}
if (state == MIME_TYPE) {
new_hdr = mime_hdr_new(ntmp, strip_ends(q));
if (new_hdr == NULL)
goto err;
if (!sk_MIME_HEADER_push(headers, new_hdr))
goto err;
mhdr = new_hdr;
new_hdr = NULL;
} else if (state == MIME_VALUE) {
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
}
if (p == linebuf)
break; /* Blank line means end of headers */
}
return headers;
err:
mime_hdr_free(new_hdr);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return NULL;
}
static char *strip_ends(char *name)
{
return strip_end(strip_start(name));
}
/* Strip a parameter of whitespace from start of param */
static char *strip_start(char *name)
{
char *p, c;
/* Look for first non whitespace or quote */
for (p = name; (c = *p); p++) {
if (c == '"') {
/* Next char is start of string if non null */
if (p[1])
return p + 1;
/* Else null string */
return NULL;
}
if (!ossl_isspace(c))
return p;
}
return NULL;
}
/* As above but strip from end of string : maybe should handle brackets? */
static char *strip_end(char *name)
{
char *p, c;
if (!name)
return NULL;
/* Look for first non whitespace or quote */
for (p = name + strlen(name) - 1; p >= name; p--) {
c = *p;
if (c == '"') {
if (p - 1 == name)
return NULL;
*p = 0;
return name;
}
if (ossl_isspace(c))
*p = 0;
else
return name;
}
return NULL;
}
static MIME_HEADER *mime_hdr_new(const char *name, const char *value)
{
MIME_HEADER *mhdr = NULL;
char *tmpname = NULL, *tmpval = NULL, *p;
if (name) {
if ((tmpname = OPENSSL_strdup(name)) == NULL)
return NULL;
for (p = tmpname; *p; p++)
*p = ossl_tolower(*p);
}
if (value) {
if ((tmpval = OPENSSL_strdup(value)) == NULL)
goto err;
for (p = tmpval; *p; p++)
*p = ossl_tolower(*p);
}
mhdr = OPENSSL_malloc(sizeof(*mhdr));
if (mhdr == NULL)
goto err;
mhdr->name = tmpname;
mhdr->value = tmpval;
if ((mhdr->params = sk_MIME_PARAM_new(mime_param_cmp)) == NULL)
goto err;
return mhdr;
err:
OPENSSL_free(tmpname);
OPENSSL_free(tmpval);
OPENSSL_free(mhdr);
return NULL;
}
static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value)
{
char *tmpname = NULL, *tmpval = NULL, *p;
MIME_PARAM *mparam = NULL;
if (name) {
tmpname = OPENSSL_strdup(name);
if (!tmpname)
goto err;
for (p = tmpname; *p; p++)
*p = ossl_tolower(*p);
}
if (value) {
tmpval = OPENSSL_strdup(value);
if (!tmpval)
goto err;
}
/* Parameter values are case sensitive so leave as is */
mparam = OPENSSL_malloc(sizeof(*mparam));
if (mparam == NULL)
goto err;
mparam->param_name = tmpname;
mparam->param_value = tmpval;
if (!sk_MIME_PARAM_push(mhdr->params, mparam))
goto err;
return 1;
err:
OPENSSL_free(tmpname);
OPENSSL_free(tmpval);
OPENSSL_free(mparam);
return 0;
}
static int mime_hdr_cmp(const MIME_HEADER *const *a,
const MIME_HEADER *const *b)
{
if ((*a)->name == NULL || (*b)->name == NULL)
return ((*a)->name != NULL) - ((*b)->name != NULL);
return strcmp((*a)->name, (*b)->name);
}
static int mime_param_cmp(const MIME_PARAM *const *a,
const MIME_PARAM *const *b)
{
if ((*a)->param_name == NULL || (*b)->param_name == NULL)
return ((*a)->param_name != NULL) - ((*b)->param_name != NULL);
return strcmp((*a)->param_name, (*b)->param_name);
}
/* Find a header with a given name (if possible) */
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name)
{
MIME_HEADER htmp;
int idx;
htmp.name = (char *)name;
htmp.value = NULL;
htmp.params = NULL;
idx = sk_MIME_HEADER_find(hdrs, &htmp);
return sk_MIME_HEADER_value(hdrs, idx);
}
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name)
{
MIME_PARAM param;
int idx;
param.param_name = (char *)name;
param.param_value = NULL;
idx = sk_MIME_PARAM_find(hdr->params, &param);
return sk_MIME_PARAM_value(hdr->params, idx);
}
static void mime_hdr_free(MIME_HEADER *hdr)
{
if (hdr == NULL)
return;
OPENSSL_free(hdr->name);
OPENSSL_free(hdr->value);
if (hdr->params)
sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
OPENSSL_free(hdr);
}
static void mime_param_free(MIME_PARAM *param)
{
OPENSSL_free(param->param_name);
OPENSSL_free(param->param_value);
OPENSSL_free(param);
}
/*-
* Check for a multipart boundary. Returns:
* 0 : no boundary
* 1 : part boundary
* 2 : final boundary
*/
static int mime_bound_check(char *line, int linelen, const char *bound, int blen)
{
if (linelen == -1)
linelen = strlen(line);
if (blen == -1)
blen = strlen(bound);
/* Quickly eliminate if line length too short */
if (blen + 2 > linelen)
return 0;
/* Check for part boundary */
if ((strncmp(line, "--", 2) == 0)
&& strncmp(line + 2, bound, blen) == 0) {
if (strncmp(line + blen + 2, "--", 2) == 0)
return 2;
else
return 1;
}
return 0;
}
static int strip_eol(char *linebuf, int *plen, int flags)
{
int len = *plen;
char *p, c;
int is_eol = 0;
#ifndef OPENSSL_NO_CMS
if ((flags & CMS_BINARY) != 0) {
if (len <= 0 || linebuf[len - 1] != '\n')
return 0;
if ((flags & SMIME_CRLFEOL) != 0) {
if (len <= 1 || linebuf[len - 2] != '\r')
return 0;
len--;
}
len--;
*plen = len;
return 1;
}
#endif
for (p = linebuf + len - 1; len > 0; len--, p--) {
c = *p;
if (c == '\n') {
is_eol = 1;
} else if (is_eol && (flags & SMIME_ASCIICRLF) != 0 && c == 32) {
/* Strip trailing space on a line; 32 == ASCII for ' ' */
continue;
} else if (c != '\r') {
break;
}
}
*plen = len;
return is_eol;
}
diff --git a/crypto/openssl/crypto/bio/bio_addr.c b/crypto/openssl/crypto/bio/bio_addr.c
index 04d62f45b198..d462f424d3a4 100644
--- a/crypto/openssl/crypto/bio/bio_addr.c
+++ b/crypto/openssl/crypto/bio/bio_addr.c
@@ -1,937 +1,942 @@
/*
- * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
/*
* VC configurations may define UNICODE, to indicate to the C RTL that
* WCHAR functions are preferred.
* This affects functions like gai_strerror(), which is implemented as
* an alias macro for gai_strerrorA() (which returns a const char *) or
* gai_strerrorW() (which returns a const WCHAR *). This source file
* assumes POSIX declarations, so prefer the non-UNICODE definitions.
*/
#undef UNICODE
#include <assert.h>
#include <string.h>
#include "bio_local.h"
#include <openssl/crypto.h>
#ifndef OPENSSL_NO_SOCK
#include <openssl/err.h>
#include <openssl/buffer.h>
#include "internal/thread_once.h"
CRYPTO_RWLOCK *bio_lookup_lock;
static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT;
/*
* Throughout this file and bio_local.h, the existence of the macro
* AI_PASSIVE is used to detect the availability of struct addrinfo,
* getnameinfo() and getaddrinfo(). If that macro doesn't exist,
* we use our own implementation instead, using gethostbyname,
* getservbyname and a few other.
*/
/**********************************************************************
*
* Address structure
*
*/
BIO_ADDR *BIO_ADDR_new(void)
{
BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->sa.sa_family = AF_UNSPEC;
return ret;
}
void BIO_ADDR_free(BIO_ADDR *ap)
{
OPENSSL_free(ap);
}
void BIO_ADDR_clear(BIO_ADDR *ap)
{
memset(ap, 0, sizeof(*ap));
ap->sa.sa_family = AF_UNSPEC;
}
/*
* BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents
* of a struct sockaddr.
*/
int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in));
return 1;
}
#ifdef AF_INET6
if (sa->sa_family == AF_INET6) {
memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6));
return 1;
}
#endif
#ifdef AF_UNIX
if (sa->sa_family == AF_UNIX) {
memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un));
return 1;
}
#endif
return 0;
}
int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
const void *where, size_t wherelen,
unsigned short port)
{
#ifdef AF_UNIX
if (family == AF_UNIX) {
if (wherelen + 1 > sizeof(ap->s_un.sun_path))
return 0;
memset(&ap->s_un, 0, sizeof(ap->s_un));
ap->s_un.sun_family = family;
strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1);
return 1;
}
#endif
if (family == AF_INET) {
if (wherelen != sizeof(struct in_addr))
return 0;
memset(&ap->s_in, 0, sizeof(ap->s_in));
ap->s_in.sin_family = family;
ap->s_in.sin_port = port;
ap->s_in.sin_addr = *(struct in_addr *)where;
return 1;
}
#ifdef AF_INET6
if (family == AF_INET6) {
if (wherelen != sizeof(struct in6_addr))
return 0;
memset(&ap->s_in6, 0, sizeof(ap->s_in6));
ap->s_in6.sin6_family = family;
ap->s_in6.sin6_port = port;
ap->s_in6.sin6_addr = *(struct in6_addr *)where;
return 1;
}
#endif
return 0;
}
int BIO_ADDR_family(const BIO_ADDR *ap)
{
return ap->sa.sa_family;
}
int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l)
{
size_t len = 0;
const void *addrptr = NULL;
if (ap->sa.sa_family == AF_INET) {
len = sizeof(ap->s_in.sin_addr);
addrptr = &ap->s_in.sin_addr;
}
#ifdef AF_INET6
else if (ap->sa.sa_family == AF_INET6) {
len = sizeof(ap->s_in6.sin6_addr);
addrptr = &ap->s_in6.sin6_addr;
}
#endif
#ifdef AF_UNIX
else if (ap->sa.sa_family == AF_UNIX) {
len = strlen(ap->s_un.sun_path);
addrptr = &ap->s_un.sun_path;
}
#endif
if (addrptr == NULL)
return 0;
if (p != NULL) {
memcpy(p, addrptr, len);
}
if (l != NULL)
*l = len;
return 1;
}
unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap)
{
if (ap->sa.sa_family == AF_INET)
return ap->s_in.sin_port;
#ifdef AF_INET6
if (ap->sa.sa_family == AF_INET6)
return ap->s_in6.sin6_port;
#endif
return 0;
}
/*-
* addr_strings - helper function to get host and service names
* @ap: the BIO_ADDR that has the input info
* @numeric: 0 if actual names should be returned, 1 if the numeric
* representation should be returned.
* @hostname: a pointer to a pointer to a memory area to store the
* host name or numeric representation. Unused if NULL.
* @service: a pointer to a pointer to a memory area to store the
* service name or numeric representation. Unused if NULL.
*
* The return value is 0 on failure, with the error code in the error
* stack, and 1 on success.
*/
static int addr_strings(const BIO_ADDR *ap, int numeric,
char **hostname, char **service)
{
if (BIO_sock_init() != 1)
return 0;
if (1) {
#ifdef AI_PASSIVE
int ret = 0;
char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
int flags = 0;
if (numeric)
flags |= NI_NUMERICHOST | NI_NUMERICSERV;
if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
BIO_ADDR_sockaddr_size(ap),
host, sizeof(host), serv, sizeof(serv),
flags)) != 0) {
# ifdef EAI_SYSTEM
if (ret == EAI_SYSTEM) {
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling getnameinfo()");
} else
# endif
{
ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, gai_strerror(ret));
}
return 0;
}
/* VMS getnameinfo() has a bug, it doesn't fill in serv, which
* leaves it with whatever garbage that happens to be there.
* However, we initialise serv with the empty string (serv[0]
* is therefore NUL), so it gets real easy to detect when things
* didn't go the way one might expect.
*/
if (serv[0] == '\0') {
BIO_snprintf(serv, sizeof(serv), "%d",
ntohs(BIO_ADDR_rawport(ap)));
}
if (hostname != NULL)
*hostname = OPENSSL_strdup(host);
if (service != NULL)
*service = OPENSSL_strdup(serv);
} else {
#endif
if (hostname != NULL)
*hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr));
if (service != NULL) {
char serv[6]; /* port is 16 bits => max 5 decimal digits */
BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port));
*service = OPENSSL_strdup(serv);
}
}
if ((hostname != NULL && *hostname == NULL)
|| (service != NULL && *service == NULL)) {
if (hostname != NULL) {
OPENSSL_free(*hostname);
*hostname = NULL;
}
if (service != NULL) {
OPENSSL_free(*service);
*service = NULL;
}
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric)
{
char *hostname = NULL;
if (addr_strings(ap, numeric, &hostname, NULL))
return hostname;
return NULL;
}
char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric)
{
char *service = NULL;
if (addr_strings(ap, numeric, NULL, &service))
return service;
return NULL;
}
char *BIO_ADDR_path_string(const BIO_ADDR *ap)
{
#ifdef AF_UNIX
if (ap->sa.sa_family == AF_UNIX)
return OPENSSL_strdup(ap->s_un.sun_path);
#endif
return NULL;
}
/*
* BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr
* for a given BIO_ADDR. In reality, this is simply a type safe cast.
* The returned struct sockaddr is const, so it can't be tampered with.
*/
const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap)
{
return &(ap->sa);
}
/*
* BIO_ADDR_sockaddr_noconst - non-public function that does the same
* as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as
* it allows you to tamper with the data (and thereby the contents
* of the input BIO_ADDR).
*/
struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap)
{
return &(ap->sa);
}
/*
* BIO_ADDR_sockaddr_size - non-public function that returns the size
* of the struct sockaddr the BIO_ADDR is using. If the protocol family
* isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX,
* the size of the BIO_ADDR type is returned.
*/
socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap)
{
if (ap->sa.sa_family == AF_INET)
return sizeof(ap->s_in);
#ifdef AF_INET6
if (ap->sa.sa_family == AF_INET6)
return sizeof(ap->s_in6);
#endif
#ifdef AF_UNIX
if (ap->sa.sa_family == AF_UNIX)
return sizeof(ap->s_un);
#endif
return sizeof(*ap);
}
/**********************************************************************
*
* Address info database
*
*/
const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_next;
return NULL;
}
int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_family;
return 0;
}
int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_socktype;
return 0;
}
int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai)
{
if (bai != NULL) {
if (bai->bai_protocol != 0)
return bai->bai_protocol;
#ifdef AF_UNIX
if (bai->bai_family == AF_UNIX)
return 0;
#endif
switch (bai->bai_socktype) {
case SOCK_STREAM:
return IPPROTO_TCP;
case SOCK_DGRAM:
return IPPROTO_UDP;
default:
break;
}
}
return 0;
}
/*
* BIO_ADDRINFO_sockaddr_size - non-public function that returns the size
* of the struct sockaddr inside the BIO_ADDRINFO.
*/
socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_addrlen;
return 0;
}
/*
* BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr
* as the struct sockaddr it is.
*/
const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_addr;
return NULL;
}
const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return (BIO_ADDR *)bai->bai_addr;
return NULL;
}
void BIO_ADDRINFO_free(BIO_ADDRINFO *bai)
{
if (bai == NULL)
return;
#ifdef AI_PASSIVE
# ifdef AF_UNIX
# define _cond bai->bai_family != AF_UNIX
# else
# define _cond 1
# endif
if (_cond) {
freeaddrinfo(bai);
return;
}
#endif
/* Free manually when we know that addrinfo_wrap() was used.
* See further comment above addrinfo_wrap()
*/
while (bai != NULL) {
BIO_ADDRINFO *next = bai->bai_next;
OPENSSL_free(bai->bai_addr);
OPENSSL_free(bai);
bai = next;
}
}
/**********************************************************************
*
* Service functions
*
*/
/*-
* The specs in hostserv can take these forms:
*
* host:service => *host = "host", *service = "service"
* host:* => *host = "host", *service = NULL
* host: => *host = "host", *service = NULL
* :service => *host = NULL, *service = "service"
* *:service => *host = NULL, *service = "service"
*
* in case no : is present in the string, the result depends on
* hostserv_prio, as follows:
*
* when hostserv_prio == BIO_PARSE_PRIO_HOST
* host => *host = "host", *service untouched
*
* when hostserv_prio == BIO_PARSE_PRIO_SERV
* service => *host untouched, *service = "service"
*
*/
int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
enum BIO_hostserv_priorities hostserv_prio)
{
const char *h = NULL; size_t hl = 0;
const char *p = NULL; size_t pl = 0;
if (*hostserv == '[') {
if ((p = strchr(hostserv, ']')) == NULL)
goto spec_err;
h = hostserv + 1;
hl = p - h;
p++;
if (*p == '\0')
p = NULL;
else if (*p != ':')
goto spec_err;
else {
p++;
pl = strlen(p);
}
} else {
const char *p2 = strrchr(hostserv, ':');
p = strchr(hostserv, ':');
/*-
* Check for more than one colon. There are three possible
* interpretations:
* 1. IPv6 address with port number, last colon being separator.
* 2. IPv6 address only.
* 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST,
* IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV
* Because of this ambiguity, we currently choose to make it an
* error.
*/
if (p != p2)
goto amb_err;
if (p != NULL) {
h = hostserv;
hl = p - h;
p++;
pl = strlen(p);
} else if (hostserv_prio == BIO_PARSE_PRIO_HOST) {
h = hostserv;
hl = strlen(h);
} else {
p = hostserv;
pl = strlen(p);
}
}
if (p != NULL && strchr(p, ':'))
goto spec_err;
if (h != NULL && host != NULL) {
if (hl == 0
|| (hl == 1 && h[0] == '*')) {
*host = NULL;
} else {
*host = OPENSSL_strndup(h, hl);
if (*host == NULL)
goto memerr;
}
}
if (p != NULL && service != NULL) {
if (pl == 0
|| (pl == 1 && p[0] == '*')) {
*service = NULL;
} else {
*service = OPENSSL_strndup(p, pl);
- if (*service == NULL)
+ if (*service == NULL) {
+ if (h != NULL && host != NULL) {
+ OPENSSL_free(*host);
+ *host = NULL;
+ }
goto memerr;
+ }
}
}
return 1;
amb_err:
ERR_raise(ERR_LIB_BIO, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
return 0;
spec_err:
ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE);
return 0;
memerr:
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
/* addrinfo_wrap is used to build our own addrinfo "chain".
* (it has only one entry, so calling it a chain may be a stretch)
* It should ONLY be called when getaddrinfo() and friends
* aren't available, OR when dealing with a non IP protocol
* family, such as AF_UNIX
*
* the return value is 1 on success, or 0 on failure, which
* only happens if a memory allocation error occurred.
*/
static int addrinfo_wrap(int family, int socktype,
const void *where, size_t wherelen,
unsigned short port,
BIO_ADDRINFO **bai)
{
if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
(*bai)->bai_family = family;
(*bai)->bai_socktype = socktype;
if (socktype == SOCK_STREAM)
(*bai)->bai_protocol = IPPROTO_TCP;
if (socktype == SOCK_DGRAM)
(*bai)->bai_protocol = IPPROTO_UDP;
#ifdef AF_UNIX
if (family == AF_UNIX)
(*bai)->bai_protocol = 0;
#endif
{
/* Magic: We know that BIO_ADDR_sockaddr_noconst is really
just an advanced cast of BIO_ADDR* to struct sockaddr *
by the power of union, so while it may seem that we're
creating a memory leak here, we are not. It will be
all right. */
BIO_ADDR *addr = BIO_ADDR_new();
if (addr != NULL) {
BIO_ADDR_rawmake(addr, family, where, wherelen, port);
(*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr);
}
}
(*bai)->bai_next = NULL;
if ((*bai)->bai_addr == NULL) {
BIO_ADDRINFO_free(*bai);
*bai = NULL;
return 0;
}
return 1;
}
DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init)
{
bio_lookup_lock = CRYPTO_THREAD_lock_new();
return bio_lookup_lock != NULL;
}
int BIO_lookup(const char *host, const char *service,
enum BIO_lookup_type lookup_type,
int family, int socktype, BIO_ADDRINFO **res)
{
return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res);
}
/*-
* BIO_lookup_ex - look up the host and service you want to connect to.
* @host: the host (or node, in case family == AF_UNIX) you want to connect to.
* @service: the service you want to connect to.
* @lookup_type: declare intent with the result, client or server.
* @family: the address family you want to use. Use AF_UNSPEC for any, or
* AF_INET, AF_INET6 or AF_UNIX.
* @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM
* or 0 for all.
* @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all.
* Note that some platforms may not return IPPROTO_SCTP without
* explicitly requesting it (i.e. IPPROTO_SCTP may not be returned
* with 0 for the protocol)
* @res: Storage place for the resulting list of returned addresses
*
* This will do a lookup of the host and service that you want to connect to.
* It returns a linked list of different addresses you can try to connect to.
*
* When no longer needed you should call BIO_ADDRINFO_free() to free the result.
*
* The return value is 1 on success or 0 in case of error.
*/
int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
int family, int socktype, int protocol, BIO_ADDRINFO **res)
{
int ret = 0; /* Assume failure */
switch(family) {
case AF_INET:
#ifdef AF_INET6
case AF_INET6:
#endif
#ifdef AF_UNIX
case AF_UNIX:
#endif
#ifdef AF_UNSPEC
case AF_UNSPEC:
#endif
break;
default:
ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
return 0;
}
#ifdef AF_UNIX
if (family == AF_UNIX) {
if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
return 1;
else
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
#endif
if (BIO_sock_init() != 1)
return 0;
if (1) {
#ifdef AI_PASSIVE
int gai_ret = 0, old_ret = 0;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = protocol;
# ifdef AI_ADDRCONFIG
# ifdef AF_UNSPEC
if (host != NULL && family == AF_UNSPEC)
# endif
hints.ai_flags |= AI_ADDRCONFIG;
# endif
if (lookup_type == BIO_LOOKUP_SERVER)
hints.ai_flags |= AI_PASSIVE;
/* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
* macro magic in bio_local.h
*/
# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST)
retry:
# endif
switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
# ifdef EAI_SYSTEM
case EAI_SYSTEM:
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling getaddrinfo()");
ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
break;
# endif
# ifdef EAI_MEMORY
case EAI_MEMORY:
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
break;
# endif
case 0:
ret = 1; /* Success */
break;
default:
# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST)
if (hints.ai_flags & AI_ADDRCONFIG) {
hints.ai_flags &= ~AI_ADDRCONFIG;
hints.ai_flags |= AI_NUMERICHOST;
old_ret = gai_ret;
goto retry;
}
# endif
ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB,
gai_strerror(old_ret ? old_ret : gai_ret));
break;
}
} else {
#endif
const struct hostent *he;
/*
* Because struct hostent is defined for 32-bit pointers only with
* VMS C, we need to make sure that '&he_fallback_address' and
* '&he_fallback_addresses' are 32-bit pointers
*/
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
/* Windows doesn't seem to have in_addr_t */
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
static uint32_t he_fallback_address;
static const char *he_fallback_addresses[] =
{ (char *)&he_fallback_address, NULL };
#else
static in_addr_t he_fallback_address;
static const char *he_fallback_addresses[] =
{ (char *)&he_fallback_address, NULL };
#endif
static const struct hostent he_fallback =
{ NULL, NULL, AF_INET, sizeof(he_fallback_address),
(char **)&he_fallback_addresses };
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif
struct servent *se;
/* Apparently, on WIN64, s_proto and s_port have traded places... */
#ifdef _WIN64
struct servent se_fallback = { NULL, NULL, NULL, 0 };
#else
struct servent se_fallback = { NULL, NULL, 0, NULL };
#endif
if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) {
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CRYPTO_THREAD_write_lock(bio_lookup_lock))
return 0;
he_fallback_address = INADDR_ANY;
if (host == NULL) {
he = &he_fallback;
switch(lookup_type) {
case BIO_LOOKUP_CLIENT:
he_fallback_address = INADDR_LOOPBACK;
break;
case BIO_LOOKUP_SERVER:
he_fallback_address = INADDR_ANY;
break;
default:
/* We forgot to handle a lookup type! */
assert("We forgot to handle a lookup type!" == NULL);
ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR);
ret = 0;
goto err;
}
} else {
he = gethostbyname(host);
if (he == NULL) {
#ifndef OPENSSL_SYS_WINDOWS
/*
* This might be misleading, because h_errno is used as if
* it was errno. To minimize mixup add 1000. Underlying
* reason for this is that hstrerror is declared obsolete,
* not to mention that a) h_errno is not always guaranteed
* to be meaningless; b) hstrerror can reside in yet another
* library, linking for sake of hstrerror is an overkill;
* c) this path is not executed on contemporary systems
* anyway [above getaddrinfo/gai_strerror is]. We just let
* system administrator figure this out...
*/
# if defined(OPENSSL_SYS_VXWORKS)
/* h_errno doesn't exist on VxWorks */
ERR_raise_data(ERR_LIB_SYS, 1000,
"calling gethostbyname()");
# else
ERR_raise_data(ERR_LIB_SYS, 1000 + h_errno,
"calling gethostbyname()");
# endif
#else
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling gethostbyname()");
#endif
ret = 0;
goto err;
}
}
if (service == NULL) {
se_fallback.s_port = 0;
se_fallback.s_proto = NULL;
se = &se_fallback;
} else {
char *endp = NULL;
long portnum = strtol(service, &endp, 10);
/*
* Because struct servent is defined for 32-bit pointers only with
* VMS C, we need to make sure that 'proto' is a 32-bit pointer.
*/
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
char *proto = NULL;
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif
switch (socktype) {
case SOCK_STREAM:
proto = "tcp";
break;
case SOCK_DGRAM:
proto = "udp";
break;
}
if (endp != service && *endp == '\0'
&& portnum > 0 && portnum < 65536) {
se_fallback.s_port = htons((unsigned short)portnum);
se_fallback.s_proto = proto;
se = &se_fallback;
} else if (endp == service) {
se = getservbyname(service, proto);
if (se == NULL) {
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling getservbyname()");
goto err;
}
} else {
ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE);
goto err;
}
}
*res = NULL;
{
/*
* Because hostent::h_addr_list is an array of 32-bit pointers with VMS C,
* we must make sure our iterator designates the same element type, hence
* the pointer size dance.
*/
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
char **addrlistp;
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif
size_t addresses;
BIO_ADDRINFO *tmp_bai = NULL;
/* The easiest way to create a linked list from an
array is to start from the back */
for(addrlistp = he->h_addr_list; *addrlistp != NULL;
addrlistp++)
;
for(addresses = addrlistp - he->h_addr_list;
addrlistp--, addresses-- > 0; ) {
if (!addrinfo_wrap(he->h_addrtype, socktype,
*addrlistp, he->h_length,
se->s_port, &tmp_bai))
goto addrinfo_malloc_err;
tmp_bai->bai_next = *res;
*res = tmp_bai;
continue;
addrinfo_malloc_err:
BIO_ADDRINFO_free(*res);
*res = NULL;
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
ret = 0;
goto err;
}
ret = 1;
}
err:
CRYPTO_THREAD_unlock(bio_lookup_lock);
}
return ret;
}
#endif /* OPENSSL_NO_SOCK */
diff --git a/crypto/openssl/crypto/bio/bio_sock.c b/crypto/openssl/crypto/bio/bio_sock.c
index 12e6a68e3a25..84496de6f6bd 100644
--- a/crypto/openssl/crypto/bio/bio_sock.c
+++ b/crypto/openssl/crypto/bio/bio_sock.c
@@ -1,419 +1,419 @@
/*
- * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 "bio_local.h"
#ifndef OPENSSL_NO_SOCK
# define SOCKET_PROTOCOL IPPROTO_TCP
# ifdef SO_MAXCONN
# define MAX_LISTEN SO_MAXCONN
# elif defined(SOMAXCONN)
# define MAX_LISTEN SOMAXCONN
# else
# define MAX_LISTEN 32
# endif
# if defined(OPENSSL_SYS_WINDOWS)
static int wsa_init_done = 0;
# endif
# if defined __TANDEM
# include <unistd.h>
# include <sys/time.h> /* select */
# if defined(OPENSSL_TANDEM_FLOSS)
# include <floss.h(floss_select)>
# endif
# elif defined _WIN32
# include <winsock.h> /* for type fd_set */
# else
# include <unistd.h>
# if defined __VMS
# include <sys/socket.h>
# elif defined _HPUX_SOURCE
# include <sys/time.h>
# else
# include <sys/select.h>
# endif
# endif
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
int BIO_get_host_ip(const char *str, unsigned char *ip)
{
BIO_ADDRINFO *res = NULL;
int ret = 0;
if (BIO_sock_init() != 1)
return 0; /* don't generate another error code here */
if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
size_t l;
if (BIO_ADDRINFO_family(res) != AF_INET) {
ERR_raise(ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
} else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) {
/*
* Because only AF_INET addresses will reach this far, we can assert
* that l should be 4
*/
if (ossl_assert(l == 4))
ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l);
}
BIO_ADDRINFO_free(res);
} else {
ERR_add_error_data(2, "host=", str);
}
return ret;
}
int BIO_get_port(const char *str, unsigned short *port_ptr)
{
BIO_ADDRINFO *res = NULL;
int ret = 0;
if (str == NULL) {
ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED);
return 0;
}
if (BIO_sock_init() != 1)
return 0; /* don't generate another error code here */
if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
if (BIO_ADDRINFO_family(res) != AF_INET) {
ERR_raise(ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET);
} else {
*port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res)));
ret = 1;
}
BIO_ADDRINFO_free(res);
} else {
ERR_add_error_data(2, "host=", str);
}
return ret;
}
# endif
int BIO_sock_error(int sock)
{
int j = 0, i;
socklen_t size = sizeof(j);
/*
* Note: under Windows the third parameter is of type (char *) 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
* (char *) or (void *).
*/
i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size);
if (i < 0)
return get_last_socket_error();
else
return j;
}
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
struct hostent *BIO_gethostbyname(const char *name)
{
/*
* Caching gethostbyname() results forever is wrong, so we have to let
* the true gethostbyname() worry about this
*/
return gethostbyname(name);
}
# endif
int BIO_sock_init(void)
{
# ifdef OPENSSL_SYS_WINDOWS
static struct WSAData wsa_state;
if (!wsa_init_done) {
wsa_init_done = 1;
memset(&wsa_state, 0, sizeof(wsa_state));
/*
* Not making wsa_state available to the rest of the code is formally
* wrong. But the structures we use are [believed to be] invariable
* among Winsock DLLs, while API availability is [expected to be]
* probed at run-time with DSO_global_lookup.
*/
if (WSAStartup(0x0202, &wsa_state) != 0) {
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling wsastartup()");
ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP);
return -1;
}
}
# endif /* OPENSSL_SYS_WINDOWS */
# ifdef WATT32
extern int _watt_do_exit;
_watt_do_exit = 0; /* don't make sock_init() call exit() */
if (sock_init())
return -1;
# endif
return 1;
}
void bio_sock_cleanup_int(void)
{
# ifdef OPENSSL_SYS_WINDOWS
if (wsa_init_done) {
wsa_init_done = 0;
WSACleanup();
}
# endif
}
int BIO_socket_ioctl(int fd, long type, void *arg)
{
int i;
# ifdef __DJGPP__
i = ioctlsocket(fd, type, (char *)arg);
# else
# if defined(OPENSSL_SYS_VMS)
/*-
* 2011-02-18 SMS.
* VMS ioctl() can't tolerate a 64-bit "void *arg", but we
* observe that all the consumers pass in an "unsigned long *",
* so we arrange a local copy with a short pointer, and use
* that, instead.
*/
# if __INITIAL_POINTER_SIZE == 64
# define ARG arg_32p
# pragma pointer_size save
# pragma pointer_size 32
unsigned long arg_32;
unsigned long *arg_32p;
# pragma pointer_size restore
arg_32p = &arg_32;
arg_32 = *((unsigned long *)arg);
# else /* __INITIAL_POINTER_SIZE == 64 */
# define ARG arg
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
# else /* defined(OPENSSL_SYS_VMS) */
# define ARG arg
# endif /* defined(OPENSSL_SYS_VMS) [else] */
i = ioctlsocket(fd, type, ARG);
# endif /* __DJGPP__ */
if (i < 0)
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling ioctlsocket()");
return i;
}
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
int BIO_get_accept_socket(char *host, int bind_mode)
{
int s = INVALID_SOCKET;
char *h = NULL, *p = NULL;
BIO_ADDRINFO *res = NULL;
if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
return INVALID_SOCKET;
if (BIO_sock_init() != 1)
- return INVALID_SOCKET;
+ goto err;
if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
goto err;
if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
s = INVALID_SOCKET;
goto err;
}
if (!BIO_listen(s, BIO_ADDRINFO_address(res),
bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
BIO_closesocket(s);
s = INVALID_SOCKET;
}
err:
BIO_ADDRINFO_free(res);
OPENSSL_free(h);
OPENSSL_free(p);
return s;
}
int BIO_accept(int sock, char **ip_port)
{
BIO_ADDR res;
int ret = -1;
ret = BIO_accept_ex(sock, &res, 0);
if (ret == (int)INVALID_SOCKET) {
if (BIO_sock_should_retry(ret)) {
ret = -2;
goto end;
}
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling accept()");
ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
goto end;
}
if (ip_port != NULL) {
char *host = BIO_ADDR_hostname_string(&res, 1);
char *port = BIO_ADDR_service_string(&res, 1);
if (host != NULL && port != NULL)
*ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
else
*ip_port = NULL;
if (*ip_port == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
BIO_closesocket(ret);
ret = (int)INVALID_SOCKET;
} else {
strcpy(*ip_port, host);
strcat(*ip_port, ":");
strcat(*ip_port, port);
}
OPENSSL_free(host);
OPENSSL_free(port);
}
end:
return ret;
}
# endif
int BIO_set_tcp_ndelay(int s, int on)
{
int ret = 0;
# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
int opt;
# ifdef SOL_TCP
opt = SOL_TCP;
# else
# ifdef IPPROTO_TCP
opt = IPPROTO_TCP;
# endif
# endif
ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
# endif
return (ret == 0);
}
int BIO_socket_nbio(int s, int mode)
{
int ret = -1;
int l;
l = mode;
# ifdef FIONBIO
l = mode;
ret = BIO_socket_ioctl(s, FIONBIO, &l);
# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
/* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
l = fcntl(s, F_GETFL, 0);
if (l == -1) {
ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
"calling fcntl()");
ret = -1;
} else {
# if defined(O_NONBLOCK)
l &= ~O_NONBLOCK;
# else
l &= ~FNDELAY; /* BSD4.x */
# endif
if (mode) {
# if defined(O_NONBLOCK)
l |= O_NONBLOCK;
# else
l |= FNDELAY; /* BSD4.x */
# endif
}
ret = fcntl(s, F_SETFL, l);
if (ret < 0) {
ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
"calling fcntl()");
}
}
# else
/* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT);
# endif
return (ret == 0);
}
int BIO_sock_info(int sock,
enum BIO_sock_info_type type, union BIO_sock_info_u *info)
{
switch (type) {
case BIO_SOCK_INFO_ADDRESS:
{
socklen_t addr_len;
int ret = 0;
addr_len = sizeof(*info->addr);
ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
&addr_len);
if (ret == -1) {
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling getsockname()");
ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR);
return 0;
}
if ((size_t)addr_len > sizeof(*info->addr)) {
ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
return 0;
}
}
break;
default:
ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE);
return 0;
}
return 1;
}
/*
* Wait on fd at most until max_time; succeed immediately if max_time == 0.
* If for_read == 0 then assume to wait for writing, else wait for reading.
* Returns -1 on error, 0 on timeout, and 1 on success.
*/
int BIO_socket_wait(int fd, int for_read, time_t max_time)
{
fd_set confds;
struct timeval tv;
time_t now;
#ifdef _WIN32
if ((SOCKET)fd == INVALID_SOCKET)
#else
if (fd < 0 || fd >= FD_SETSIZE)
#endif
return -1;
if (max_time == 0)
return 1;
now = time(NULL);
if (max_time < now)
return 0;
FD_ZERO(&confds);
openssl_fdset(fd, &confds);
tv.tv_usec = 0;
tv.tv_sec = (long)(max_time - now); /* might overflow */
return select(fd + 1, for_read ? &confds : NULL,
for_read ? NULL : &confds, NULL, &tv);
}
#endif /* !defined(OPENSSL_NO_SOCK) */
diff --git a/crypto/openssl/crypto/bio/bss_log.c b/crypto/openssl/crypto/bio/bss_log.c
index 82abfd5cec63..63b30e300fec 100644
--- a/crypto/openssl/crypto/bio/bss_log.c
+++ b/crypto/openssl/crypto/bio/bss_log.c
@@ -1,417 +1,417 @@
/*
* Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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_local.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",
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 (inl < 0)
return 0;
if ((buf = OPENSSL_malloc(inl + 1)) == NULL) {
ERR_raise(ERR_LIB_BIO, 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());
+ BIO_snprintf(pidbuf, sizeof(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/openssl/crypto/bn/asm/armv8-mont.pl b/crypto/openssl/crypto/bn/asm/armv8-mont.pl
index 21ab12bdf07e..1641a9880c97 100755
--- a/crypto/openssl/crypto/bn/asm/armv8-mont.pl
+++ b/crypto/openssl/crypto/bn/asm/armv8-mont.pl
@@ -1,1907 +1,1909 @@
#! /usr/bin/env perl
-# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
# ====================================================================
# March 2015
#
# "Teaser" Montgomery multiplication module for ARMv8. Needs more
# work. While it does improve RSA sign performance by 20-30% (less for
# longer keys) on most processors, for some reason RSA2048 is not
# faster and RSA4096 goes 15-20% slower on Cortex-A57. Multiplication
# instruction issue rate is limited on processor in question, meaning
# that dedicated squaring procedure is a must. Well, actually all
# contemporary AArch64 processors seem to have limited multiplication
# issue rate, i.e. they can't issue multiplication every cycle, which
# explains moderate improvement coefficients in comparison to
# compiler-generated code. Recall that compiler is instructed to use
# umulh and therefore uses same amount of multiplication instructions
# to do the job. Assembly's edge is to minimize number of "collateral"
# instructions and of course instruction scheduling.
#
# April 2015
#
# Squaring procedure that handles lengths divisible by 8 improves
# RSA/DSA performance by 25-40-60% depending on processor and key
# length. Overall improvement coefficients are always positive in
# comparison to compiler-generated code. On Cortex-A57 improvement
# is still modest on longest key lengths, while others exhibit e.g.
# 50-70% improvement for RSA4096 sign. RSA2048 sign is ~25% faster
# on Cortex-A57 and ~60-100% faster on others.
# $output is the last argument if it looks like a file (it has an extension)
# $flavour is the first argument if it doesn't look like a file
my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
open OUT,"| \"$^X\" $xlate $flavour \"$output\""
or die "can't call $xlate: $1";
*STDOUT=*OUT;
($lo0,$hi0,$aj,$m0,$alo,$ahi,
$lo1,$hi1,$nj,$m1,$nlo,$nhi,
$ovf, $i,$j,$tp,$tj) = map("x$_",6..17,19..24);
# int bn_mul_mont(
$rp="x0"; # BN_ULONG *rp,
$ap="x1"; # const BN_ULONG *ap,
$bp="x2"; # const BN_ULONG *bp,
$np="x3"; # const BN_ULONG *np,
$n0="x4"; # const BN_ULONG *n0,
$num="x5"; # int num);
$code.=<<___;
#include "arm_arch.h"
#ifndef __KERNEL__
.extern OPENSSL_armv8_rsa_neonized
.hidden OPENSSL_armv8_rsa_neonized
#endif
.text
.globl bn_mul_mont
.type bn_mul_mont,%function
.align 5
bn_mul_mont:
AARCH64_SIGN_LINK_REGISTER
.Lbn_mul_mont:
tst $num,#3
b.ne .Lmul_mont
cmp $num,#32
b.le .Lscalar_impl
#ifndef __KERNEL__
+#ifndef __AARCH64EB__
adrp x17,OPENSSL_armv8_rsa_neonized
ldr w17,[x17,#:lo12:OPENSSL_armv8_rsa_neonized]
cbnz w17, bn_mul8x_mont_neon
#endif
+#endif
.Lscalar_impl:
tst $num,#7
b.eq __bn_sqr8x_mont
tst $num,#3
b.eq __bn_mul4x_mont
.Lmul_mont:
stp x29,x30,[sp,#-64]!
add x29,sp,#0
stp x19,x20,[sp,#16]
stp x21,x22,[sp,#32]
stp x23,x24,[sp,#48]
ldr $m0,[$bp],#8 // bp[0]
sub $tp,sp,$num,lsl#3
ldp $hi0,$aj,[$ap],#16 // ap[0..1]
lsl $num,$num,#3
ldr $n0,[$n0] // *n0
and $tp,$tp,#-16 // ABI says so
ldp $hi1,$nj,[$np],#16 // np[0..1]
mul $lo0,$hi0,$m0 // ap[0]*bp[0]
sub $j,$num,#16 // j=num-2
umulh $hi0,$hi0,$m0
mul $alo,$aj,$m0 // ap[1]*bp[0]
umulh $ahi,$aj,$m0
mul $m1,$lo0,$n0 // "tp[0]"*n0
mov sp,$tp // alloca
// (*) mul $lo1,$hi1,$m1 // np[0]*m1
umulh $hi1,$hi1,$m1
mul $nlo,$nj,$m1 // np[1]*m1
// (*) adds $lo1,$lo1,$lo0 // discarded
// (*) As for removal of first multiplication and addition
// instructions. The outcome of first addition is
// guaranteed to be zero, which leaves two computationally
// significant outcomes: it either carries or not. Then
// question is when does it carry? Is there alternative
// way to deduce it? If you follow operations, you can
// observe that condition for carry is quite simple:
// $lo0 being non-zero. So that carry can be calculated
// by adding -1 to $lo0. That's what next instruction does.
subs xzr,$lo0,#1 // (*)
umulh $nhi,$nj,$m1
adc $hi1,$hi1,xzr
cbz $j,.L1st_skip
.L1st:
ldr $aj,[$ap],#8
adds $lo0,$alo,$hi0
sub $j,$j,#8 // j--
adc $hi0,$ahi,xzr
ldr $nj,[$np],#8
adds $lo1,$nlo,$hi1
mul $alo,$aj,$m0 // ap[j]*bp[0]
adc $hi1,$nhi,xzr
umulh $ahi,$aj,$m0
adds $lo1,$lo1,$lo0
mul $nlo,$nj,$m1 // np[j]*m1
adc $hi1,$hi1,xzr
umulh $nhi,$nj,$m1
str $lo1,[$tp],#8 // tp[j-1]
cbnz $j,.L1st
.L1st_skip:
adds $lo0,$alo,$hi0
sub $ap,$ap,$num // rewind $ap
adc $hi0,$ahi,xzr
adds $lo1,$nlo,$hi1
sub $np,$np,$num // rewind $np
adc $hi1,$nhi,xzr
adds $lo1,$lo1,$lo0
sub $i,$num,#8 // i=num-1
adcs $hi1,$hi1,$hi0
adc $ovf,xzr,xzr // upmost overflow bit
stp $lo1,$hi1,[$tp]
.Louter:
ldr $m0,[$bp],#8 // bp[i]
ldp $hi0,$aj,[$ap],#16
ldr $tj,[sp] // tp[0]
add $tp,sp,#8
mul $lo0,$hi0,$m0 // ap[0]*bp[i]
sub $j,$num,#16 // j=num-2
umulh $hi0,$hi0,$m0
ldp $hi1,$nj,[$np],#16
mul $alo,$aj,$m0 // ap[1]*bp[i]
adds $lo0,$lo0,$tj
umulh $ahi,$aj,$m0
adc $hi0,$hi0,xzr
mul $m1,$lo0,$n0
sub $i,$i,#8 // i--
// (*) mul $lo1,$hi1,$m1 // np[0]*m1
umulh $hi1,$hi1,$m1
mul $nlo,$nj,$m1 // np[1]*m1
// (*) adds $lo1,$lo1,$lo0
subs xzr,$lo0,#1 // (*)
umulh $nhi,$nj,$m1
cbz $j,.Linner_skip
.Linner:
ldr $aj,[$ap],#8
adc $hi1,$hi1,xzr
ldr $tj,[$tp],#8 // tp[j]
adds $lo0,$alo,$hi0
sub $j,$j,#8 // j--
adc $hi0,$ahi,xzr
adds $lo1,$nlo,$hi1
ldr $nj,[$np],#8
adc $hi1,$nhi,xzr
mul $alo,$aj,$m0 // ap[j]*bp[i]
adds $lo0,$lo0,$tj
umulh $ahi,$aj,$m0
adc $hi0,$hi0,xzr
mul $nlo,$nj,$m1 // np[j]*m1
adds $lo1,$lo1,$lo0
umulh $nhi,$nj,$m1
stur $lo1,[$tp,#-16] // tp[j-1]
cbnz $j,.Linner
.Linner_skip:
ldr $tj,[$tp],#8 // tp[j]
adc $hi1,$hi1,xzr
adds $lo0,$alo,$hi0
sub $ap,$ap,$num // rewind $ap
adc $hi0,$ahi,xzr
adds $lo1,$nlo,$hi1
sub $np,$np,$num // rewind $np
adcs $hi1,$nhi,$ovf
adc $ovf,xzr,xzr
adds $lo0,$lo0,$tj
adc $hi0,$hi0,xzr
adds $lo1,$lo1,$lo0
adcs $hi1,$hi1,$hi0
adc $ovf,$ovf,xzr // upmost overflow bit
stp $lo1,$hi1,[$tp,#-16]
cbnz $i,.Louter
// Final step. We see if result is larger than modulus, and
// if it is, subtract the modulus. But comparison implies
// subtraction. So we subtract modulus, see if it borrowed,
// and conditionally copy original value.
ldr $tj,[sp] // tp[0]
add $tp,sp,#8
ldr $nj,[$np],#8 // np[0]
subs $j,$num,#8 // j=num-1 and clear borrow
mov $ap,$rp
.Lsub:
sbcs $aj,$tj,$nj // tp[j]-np[j]
ldr $tj,[$tp],#8
sub $j,$j,#8 // j--
ldr $nj,[$np],#8
str $aj,[$ap],#8 // rp[j]=tp[j]-np[j]
cbnz $j,.Lsub
sbcs $aj,$tj,$nj
sbcs $ovf,$ovf,xzr // did it borrow?
str $aj,[$ap],#8 // rp[num-1]
ldr $tj,[sp] // tp[0]
add $tp,sp,#8
ldr $aj,[$rp],#8 // rp[0]
sub $num,$num,#8 // num--
nop
.Lcond_copy:
sub $num,$num,#8 // num--
csel $nj,$tj,$aj,lo // did it borrow?
ldr $tj,[$tp],#8
ldr $aj,[$rp],#8
stur xzr,[$tp,#-16] // wipe tp
stur $nj,[$rp,#-16]
cbnz $num,.Lcond_copy
csel $nj,$tj,$aj,lo
stur xzr,[$tp,#-8] // wipe tp
stur $nj,[$rp,#-8]
ldp x19,x20,[x29,#16]
mov sp,x29
ldp x21,x22,[x29,#32]
mov x0,#1
ldp x23,x24,[x29,#48]
ldr x29,[sp],#64
AARCH64_VALIDATE_LINK_REGISTER
ret
.size bn_mul_mont,.-bn_mul_mont
___
{
my ($A0,$A1,$N0,$N1)=map("v$_",(0..3));
my ($Z,$Temp)=("v4.16b","v5");
my @ACC=map("v$_",(6..13));
my ($Bi,$Ni,$M0)=map("v$_",(28..30));
my $sBi="s28";
my $sM0="s30";
my $zero="v14";
my $temp="v15";
my $ACCTemp="v16";
my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("x$_",(0..5));
my ($tinptr,$toutptr,$inner,$outer,$bnptr)=map("x$_",(6..11));
$code.=<<___;
.type bn_mul8x_mont_neon,%function
.align 5
bn_mul8x_mont_neon:
// Not adding AARCH64_SIGN_LINK_REGISTER here because bn_mul8x_mont_neon is jumped to
// only from bn_mul_mont which has already signed the return address.
stp x29,x30,[sp,#-80]!
mov x16,sp
stp d8,d9,[sp,#16]
stp d10,d11,[sp,#32]
stp d12,d13,[sp,#48]
stp d14,d15,[sp,#64]
lsl $num,$num,#1
eor $zero.16b,$zero.16b,$zero.16b
.align 4
.LNEON_8n:
eor @ACC[0].16b,@ACC[0].16b,@ACC[0].16b
sub $toutptr,sp,#128
eor @ACC[1].16b,@ACC[1].16b,@ACC[1].16b
sub $toutptr,$toutptr,$num,lsl#4
eor @ACC[2].16b,@ACC[2].16b,@ACC[2].16b
and $toutptr,$toutptr,#-64
eor @ACC[3].16b,@ACC[3].16b,@ACC[3].16b
mov sp,$toutptr // alloca
eor @ACC[4].16b,@ACC[4].16b,@ACC[4].16b
add $toutptr,$toutptr,#256
eor @ACC[5].16b,@ACC[5].16b,@ACC[5].16b
sub $inner,$num,#8
eor @ACC[6].16b,@ACC[6].16b,@ACC[6].16b
eor @ACC[7].16b,@ACC[7].16b,@ACC[7].16b
.LNEON_8n_init:
st1 {@ACC[0].2d,@ACC[1].2d},[$toutptr],#32
subs $inner,$inner,#8
st1 {@ACC[2].2d,@ACC[3].2d},[$toutptr],#32
st1 {@ACC[4].2d,@ACC[5].2d},[$toutptr],#32
st1 {@ACC[6].2d,@ACC[7].2d},[$toutptr],#32
bne .LNEON_8n_init
add $tinptr,sp,#256
ld1 {$A0.4s,$A1.4s},[$aptr],#32
add $bnptr,sp,#8
ldr $sM0,[$n0],#4
mov $outer,$num
b .LNEON_8n_outer
.align 4
.LNEON_8n_outer:
ldr $sBi,[$bptr],#4 // *b++
uxtl $Bi.4s,$Bi.4h
add $toutptr,sp,#128
ld1 {$N0.4s,$N1.4s},[$nptr],#32
umlal @ACC[0].2d,$Bi.2s,$A0.s[0]
umlal @ACC[1].2d,$Bi.2s,$A0.s[1]
umlal @ACC[2].2d,$Bi.2s,$A0.s[2]
shl $Ni.2d,@ACC[0].2d,#16
ext $Ni.16b,$Ni.16b,$Ni.16b,#8
umlal @ACC[3].2d,$Bi.2s,$A0.s[3]
add $Ni.2d,$Ni.2d,@ACC[0].2d
umlal @ACC[4].2d,$Bi.2s,$A1.s[0]
mul $Ni.2s,$Ni.2s,$M0.2s
umlal @ACC[5].2d,$Bi.2s,$A1.s[1]
st1 {$Bi.2s},[sp] // put aside smashed b[8*i+0]
umlal @ACC[6].2d,$Bi.2s,$A1.s[2]
uxtl $Ni.4s,$Ni.4h
umlal @ACC[7].2d,$Bi.2s,$A1.s[3]
___
for ($i=0; $i<7;) {
$code.=<<___;
ldr $sBi,[$bptr],#4 // *b++
umlal @ACC[0].2d,$Ni.2s,$N0.s[0]
umlal @ACC[1].2d,$Ni.2s,$N0.s[1]
uxtl $Bi.4s,$Bi.4h
umlal @ACC[2].2d,$Ni.2s,$N0.s[2]
ushr $temp.2d,@ACC[0].2d,#16
umlal @ACC[3].2d,$Ni.2s,$N0.s[3]
umlal @ACC[4].2d,$Ni.2s,$N1.s[0]
ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8
add @ACC[0].2d,@ACC[0].2d,$temp.2d
umlal @ACC[5].2d,$Ni.2s,$N1.s[1]
ushr @ACC[0].2d,@ACC[0].2d,#16
umlal @ACC[6].2d,$Ni.2s,$N1.s[2]
umlal @ACC[7].2d,$Ni.2s,$N1.s[3]
add $ACCTemp.2d,@ACC[1].2d,@ACC[0].2d
ins @ACC[1].d[0],$ACCTemp.d[0]
st1 {$Ni.2s},[$bnptr],#8 // put aside smashed m[8*i+$i]
___
push(@ACC,shift(@ACC)); $i++;
$code.=<<___;
umlal @ACC[0].2d,$Bi.2s,$A0.s[0]
ld1 {@ACC[7].2d},[$tinptr],#16
umlal @ACC[1].2d,$Bi.2s,$A0.s[1]
umlal @ACC[2].2d,$Bi.2s,$A0.s[2]
shl $Ni.2d,@ACC[0].2d,#16
ext $Ni.16b,$Ni.16b,$Ni.16b,#8
umlal @ACC[3].2d,$Bi.2s,$A0.s[3]
add $Ni.2d,$Ni.2d,@ACC[0].2d
umlal @ACC[4].2d,$Bi.2s,$A1.s[0]
mul $Ni.2s,$Ni.2s,$M0.2s
umlal @ACC[5].2d,$Bi.2s,$A1.s[1]
st1 {$Bi.2s},[$bnptr],#8 // put aside smashed b[8*i+$i]
umlal @ACC[6].2d,$Bi.2s,$A1.s[2]
uxtl $Ni.4s,$Ni.4h
umlal @ACC[7].2d,$Bi.2s,$A1.s[3]
___
}
$code.=<<___;
ld1 {$Bi.2s},[sp] // pull smashed b[8*i+0]
umlal @ACC[0].2d,$Ni.2s,$N0.s[0]
ld1 {$A0.4s,$A1.4s},[$aptr],#32
umlal @ACC[1].2d,$Ni.2s,$N0.s[1]
umlal @ACC[2].2d,$Ni.2s,$N0.s[2]
mov $Temp.16b,@ACC[0].16b
ushr $Temp.2d,$Temp.2d,#16
ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8
umlal @ACC[3].2d,$Ni.2s,$N0.s[3]
umlal @ACC[4].2d,$Ni.2s,$N1.s[0]
add @ACC[0].2d,@ACC[0].2d,$Temp.2d
umlal @ACC[5].2d,$Ni.2s,$N1.s[1]
ushr @ACC[0].2d,@ACC[0].2d,#16
eor $temp.16b,$temp.16b,$temp.16b
ins @ACC[0].d[1],$temp.d[0]
umlal @ACC[6].2d,$Ni.2s,$N1.s[2]
umlal @ACC[7].2d,$Ni.2s,$N1.s[3]
add @ACC[1].2d,@ACC[1].2d,@ACC[0].2d
st1 {$Ni.2s},[$bnptr],#8 // put aside smashed m[8*i+$i]
add $bnptr,sp,#8 // rewind
___
push(@ACC,shift(@ACC));
$code.=<<___;
sub $inner,$num,#8
b .LNEON_8n_inner
.align 4
.LNEON_8n_inner:
subs $inner,$inner,#8
umlal @ACC[0].2d,$Bi.2s,$A0.s[0]
ld1 {@ACC[7].2d},[$tinptr]
umlal @ACC[1].2d,$Bi.2s,$A0.s[1]
ld1 {$Ni.2s},[$bnptr],#8 // pull smashed m[8*i+0]
umlal @ACC[2].2d,$Bi.2s,$A0.s[2]
ld1 {$N0.4s,$N1.4s},[$nptr],#32
umlal @ACC[3].2d,$Bi.2s,$A0.s[3]
b.eq .LInner_jump
add $tinptr,$tinptr,#16 // don't advance in last iteration
.LInner_jump:
umlal @ACC[4].2d,$Bi.2s,$A1.s[0]
umlal @ACC[5].2d,$Bi.2s,$A1.s[1]
umlal @ACC[6].2d,$Bi.2s,$A1.s[2]
umlal @ACC[7].2d,$Bi.2s,$A1.s[3]
___
for ($i=1; $i<8; $i++) {
$code.=<<___;
ld1 {$Bi.2s},[$bnptr],#8 // pull smashed b[8*i+$i]
umlal @ACC[0].2d,$Ni.2s,$N0.s[0]
umlal @ACC[1].2d,$Ni.2s,$N0.s[1]
umlal @ACC[2].2d,$Ni.2s,$N0.s[2]
umlal @ACC[3].2d,$Ni.2s,$N0.s[3]
umlal @ACC[4].2d,$Ni.2s,$N1.s[0]
umlal @ACC[5].2d,$Ni.2s,$N1.s[1]
umlal @ACC[6].2d,$Ni.2s,$N1.s[2]
umlal @ACC[7].2d,$Ni.2s,$N1.s[3]
st1 {@ACC[0].2d},[$toutptr],#16
___
push(@ACC,shift(@ACC));
$code.=<<___;
umlal @ACC[0].2d,$Bi.2s,$A0.s[0]
ld1 {@ACC[7].2d},[$tinptr]
umlal @ACC[1].2d,$Bi.2s,$A0.s[1]
ld1 {$Ni.2s},[$bnptr],#8 // pull smashed m[8*i+$i]
umlal @ACC[2].2d,$Bi.2s,$A0.s[2]
b.eq .LInner_jump$i
add $tinptr,$tinptr,#16 // don't advance in last iteration
.LInner_jump$i:
umlal @ACC[3].2d,$Bi.2s,$A0.s[3]
umlal @ACC[4].2d,$Bi.2s,$A1.s[0]
umlal @ACC[5].2d,$Bi.2s,$A1.s[1]
umlal @ACC[6].2d,$Bi.2s,$A1.s[2]
umlal @ACC[7].2d,$Bi.2s,$A1.s[3]
___
}
$code.=<<___;
b.ne .LInner_after_rewind$i
sub $aptr,$aptr,$num,lsl#2 // rewind
.LInner_after_rewind$i:
umlal @ACC[0].2d,$Ni.2s,$N0.s[0]
ld1 {$Bi.2s},[sp] // pull smashed b[8*i+0]
umlal @ACC[1].2d,$Ni.2s,$N0.s[1]
ld1 {$A0.4s,$A1.4s},[$aptr],#32
umlal @ACC[2].2d,$Ni.2s,$N0.s[2]
add $bnptr,sp,#8 // rewind
umlal @ACC[3].2d,$Ni.2s,$N0.s[3]
umlal @ACC[4].2d,$Ni.2s,$N1.s[0]
umlal @ACC[5].2d,$Ni.2s,$N1.s[1]
umlal @ACC[6].2d,$Ni.2s,$N1.s[2]
st1 {@ACC[0].2d},[$toutptr],#16
umlal @ACC[7].2d,$Ni.2s,$N1.s[3]
bne .LNEON_8n_inner
___
push(@ACC,shift(@ACC));
$code.=<<___;
add $tinptr,sp,#128
st1 {@ACC[0].2d,@ACC[1].2d},[$toutptr],#32
eor $N0.16b,$N0.16b,$N0.16b // $N0
st1 {@ACC[2].2d,@ACC[3].2d},[$toutptr],#32
eor $N1.16b,$N1.16b,$N1.16b // $N1
st1 {@ACC[4].2d,@ACC[5].2d},[$toutptr],#32
st1 {@ACC[6].2d},[$toutptr]
subs $outer,$outer,#8
ld1 {@ACC[0].2d,@ACC[1].2d},[$tinptr],#32
ld1 {@ACC[2].2d,@ACC[3].2d},[$tinptr],#32
ld1 {@ACC[4].2d,@ACC[5].2d},[$tinptr],#32
ld1 {@ACC[6].2d,@ACC[7].2d},[$tinptr],#32
b.eq .LInner_8n_jump_2steps
sub $nptr,$nptr,$num,lsl#2 // rewind
b .LNEON_8n_outer
.LInner_8n_jump_2steps:
add $toutptr,sp,#128
st1 {$N0.2d,$N1.2d}, [sp],#32 // start wiping stack frame
mov $Temp.16b,@ACC[0].16b
ushr $temp.2d,@ACC[0].2d,#16
ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8
st1 {$N0.2d,$N1.2d}, [sp],#32
add @ACC[0].2d,@ACC[0].2d,$temp.2d
st1 {$N0.2d,$N1.2d}, [sp],#32
ushr $temp.2d,@ACC[0].2d,#16
st1 {$N0.2d,$N1.2d}, [sp],#32
zip1 @ACC[0].4h,$Temp.4h,@ACC[0].4h
ins $temp.d[1],$zero.d[0]
mov $inner,$num
b .LNEON_tail_entry
.align 4
.LNEON_tail:
add @ACC[0].2d,@ACC[0].2d,$temp.2d
mov $Temp.16b,@ACC[0].16b
ushr $temp.2d,@ACC[0].2d,#16
ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8
ld1 {@ACC[2].2d,@ACC[3].2d}, [$tinptr],#32
add @ACC[0].2d,@ACC[0].2d,$temp.2d
ld1 {@ACC[4].2d,@ACC[5].2d}, [$tinptr],#32
ushr $temp.2d,@ACC[0].2d,#16
ld1 {@ACC[6].2d,@ACC[7].2d}, [$tinptr],#32
zip1 @ACC[0].4h,$Temp.4h,@ACC[0].4h
ins $temp.d[1],$zero.d[0]
.LNEON_tail_entry:
___
for ($i=1; $i<8; $i++) {
$code.=<<___;
add @ACC[1].2d,@ACC[1].2d,$temp.2d
st1 {@ACC[0].s}[0], [$toutptr],#4
ushr $temp.2d,@ACC[1].2d,#16
mov $Temp.16b,@ACC[1].16b
ext @ACC[1].16b,@ACC[1].16b,@ACC[1].16b,#8
add @ACC[1].2d,@ACC[1].2d,$temp.2d
ushr $temp.2d,@ACC[1].2d,#16
zip1 @ACC[1].4h,$Temp.4h,@ACC[1].4h
ins $temp.d[1],$zero.d[0]
___
push(@ACC,shift(@ACC));
}
push(@ACC,shift(@ACC));
$code.=<<___;
ld1 {@ACC[0].2d,@ACC[1].2d}, [$tinptr],#32
subs $inner,$inner,#8
st1 {@ACC[7].s}[0], [$toutptr],#4
bne .LNEON_tail
st1 {$temp.s}[0], [$toutptr],#4 // top-most bit
sub $nptr,$nptr,$num,lsl#2 // rewind $nptr
subs $aptr,sp,#0 // clear carry flag
add $bptr,sp,$num,lsl#2
.LNEON_sub:
ldp w4,w5,[$aptr],#8
ldp w6,w7,[$aptr],#8
ldp w8,w9,[$nptr],#8
ldp w10,w11,[$nptr],#8
sbcs w8,w4,w8
sbcs w9,w5,w9
sbcs w10,w6,w10
sbcs w11,w7,w11
sub x17,$bptr,$aptr
stp w8,w9,[$rptr],#8
stp w10,w11,[$rptr],#8
cbnz x17,.LNEON_sub
ldr w10, [$aptr] // load top-most bit
mov x11,sp
eor v0.16b,v0.16b,v0.16b
sub x11,$bptr,x11 // this is num*4
eor v1.16b,v1.16b,v1.16b
mov $aptr,sp
sub $rptr,$rptr,x11 // rewind $rptr
mov $nptr,$bptr // second 3/4th of frame
sbcs w10,w10,wzr // result is carry flag
.LNEON_copy_n_zap:
ldp w4,w5,[$aptr],#8
ldp w6,w7,[$aptr],#8
ldp w8,w9,[$rptr],#8
ldp w10,w11,[$rptr]
sub $rptr,$rptr,#8
b.cs .LCopy_1
mov w8,w4
mov w9,w5
mov w10,w6
mov w11,w7
.LCopy_1:
st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe
st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe
ldp w4,w5,[$aptr],#8
ldp w6,w7,[$aptr],#8
stp w8,w9,[$rptr],#8
stp w10,w11,[$rptr],#8
sub $aptr,$aptr,#32
ldp w8,w9,[$rptr],#8
ldp w10,w11,[$rptr]
sub $rptr,$rptr,#8
b.cs .LCopy_2
mov w8, w4
mov w9, w5
mov w10, w6
mov w11, w7
.LCopy_2:
st1 {v0.2d,v1.2d}, [$aptr],#32 // wipe
st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe
sub x17,$bptr,$aptr // preserves carry
stp w8,w9,[$rptr],#8
stp w10,w11,[$rptr],#8
cbnz x17,.LNEON_copy_n_zap
mov sp,x16
ldp d14,d15,[sp,#64]
ldp d12,d13,[sp,#48]
ldp d10,d11,[sp,#32]
ldp d8,d9,[sp,#16]
ldr x29,[sp],#80
AARCH64_VALIDATE_LINK_REGISTER
ret // bx lr
.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
___
}
{
########################################################################
# Following is ARMv8 adaptation of sqrx8x_mont from x86_64-mont5 module.
my ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("x$_",(6..13));
my ($t0,$t1,$t2,$t3)=map("x$_",(14..17));
my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("x$_",(19..26));
my ($cnt,$carry,$topmost)=("x27","x28","x30");
my ($tp,$ap_end,$na0)=($bp,$np,$carry);
$code.=<<___;
.type __bn_sqr8x_mont,%function
.align 5
__bn_sqr8x_mont:
cmp $ap,$bp
b.ne __bn_mul4x_mont
.Lsqr8x_mont:
// Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to
// only from bn_mul_mont which has already signed the return address.
stp x29,x30,[sp,#-128]!
add x29,sp,#0
stp x19,x20,[sp,#16]
stp x21,x22,[sp,#32]
stp x23,x24,[sp,#48]
stp x25,x26,[sp,#64]
stp x27,x28,[sp,#80]
stp $rp,$np,[sp,#96] // offload rp and np
ldp $a0,$a1,[$ap,#8*0]
ldp $a2,$a3,[$ap,#8*2]
ldp $a4,$a5,[$ap,#8*4]
ldp $a6,$a7,[$ap,#8*6]
sub $tp,sp,$num,lsl#4
lsl $num,$num,#3
ldr $n0,[$n0] // *n0
mov sp,$tp // alloca
sub $cnt,$num,#8*8
b .Lsqr8x_zero_start
.Lsqr8x_zero:
sub $cnt,$cnt,#8*8
stp xzr,xzr,[$tp,#8*0]
stp xzr,xzr,[$tp,#8*2]
stp xzr,xzr,[$tp,#8*4]
stp xzr,xzr,[$tp,#8*6]
.Lsqr8x_zero_start:
stp xzr,xzr,[$tp,#8*8]
stp xzr,xzr,[$tp,#8*10]
stp xzr,xzr,[$tp,#8*12]
stp xzr,xzr,[$tp,#8*14]
add $tp,$tp,#8*16
cbnz $cnt,.Lsqr8x_zero
add $ap_end,$ap,$num
add $ap,$ap,#8*8
mov $acc0,xzr
mov $acc1,xzr
mov $acc2,xzr
mov $acc3,xzr
mov $acc4,xzr
mov $acc5,xzr
mov $acc6,xzr
mov $acc7,xzr
mov $tp,sp
str $n0,[x29,#112] // offload n0
// Multiply everything but a[i]*a[i]
.align 4
.Lsqr8x_outer_loop:
// a[1]a[0] (i)
// a[2]a[0]
// a[3]a[0]
// a[4]a[0]
// a[5]a[0]
// a[6]a[0]
// a[7]a[0]
// a[2]a[1] (ii)
// a[3]a[1]
// a[4]a[1]
// a[5]a[1]
// a[6]a[1]
// a[7]a[1]
// a[3]a[2] (iii)
// a[4]a[2]
// a[5]a[2]
// a[6]a[2]
// a[7]a[2]
// a[4]a[3] (iv)
// a[5]a[3]
// a[6]a[3]
// a[7]a[3]
// a[5]a[4] (v)
// a[6]a[4]
// a[7]a[4]
// a[6]a[5] (vi)
// a[7]a[5]
// a[7]a[6] (vii)
mul $t0,$a1,$a0 // lo(a[1..7]*a[0]) (i)
mul $t1,$a2,$a0
mul $t2,$a3,$a0
mul $t3,$a4,$a0
adds $acc1,$acc1,$t0 // t[1]+lo(a[1]*a[0])
mul $t0,$a5,$a0
adcs $acc2,$acc2,$t1
mul $t1,$a6,$a0
adcs $acc3,$acc3,$t2
mul $t2,$a7,$a0
adcs $acc4,$acc4,$t3
umulh $t3,$a1,$a0 // hi(a[1..7]*a[0])
adcs $acc5,$acc5,$t0
umulh $t0,$a2,$a0
adcs $acc6,$acc6,$t1
umulh $t1,$a3,$a0
adcs $acc7,$acc7,$t2
umulh $t2,$a4,$a0
stp $acc0,$acc1,[$tp],#8*2 // t[0..1]
adc $acc0,xzr,xzr // t[8]
adds $acc2,$acc2,$t3 // t[2]+lo(a[1]*a[0])
umulh $t3,$a5,$a0
adcs $acc3,$acc3,$t0
umulh $t0,$a6,$a0
adcs $acc4,$acc4,$t1
umulh $t1,$a7,$a0
adcs $acc5,$acc5,$t2
mul $t2,$a2,$a1 // lo(a[2..7]*a[1]) (ii)
adcs $acc6,$acc6,$t3
mul $t3,$a3,$a1
adcs $acc7,$acc7,$t0
mul $t0,$a4,$a1
adc $acc0,$acc0,$t1
mul $t1,$a5,$a1
adds $acc3,$acc3,$t2
mul $t2,$a6,$a1
adcs $acc4,$acc4,$t3
mul $t3,$a7,$a1
adcs $acc5,$acc5,$t0
umulh $t0,$a2,$a1 // hi(a[2..7]*a[1])
adcs $acc6,$acc6,$t1
umulh $t1,$a3,$a1
adcs $acc7,$acc7,$t2
umulh $t2,$a4,$a1
adcs $acc0,$acc0,$t3
umulh $t3,$a5,$a1
stp $acc2,$acc3,[$tp],#8*2 // t[2..3]
adc $acc1,xzr,xzr // t[9]
adds $acc4,$acc4,$t0
umulh $t0,$a6,$a1
adcs $acc5,$acc5,$t1
umulh $t1,$a7,$a1
adcs $acc6,$acc6,$t2
mul $t2,$a3,$a2 // lo(a[3..7]*a[2]) (iii)
adcs $acc7,$acc7,$t3
mul $t3,$a4,$a2
adcs $acc0,$acc0,$t0
mul $t0,$a5,$a2
adc $acc1,$acc1,$t1
mul $t1,$a6,$a2
adds $acc5,$acc5,$t2
mul $t2,$a7,$a2
adcs $acc6,$acc6,$t3
umulh $t3,$a3,$a2 // hi(a[3..7]*a[2])
adcs $acc7,$acc7,$t0
umulh $t0,$a4,$a2
adcs $acc0,$acc0,$t1
umulh $t1,$a5,$a2
adcs $acc1,$acc1,$t2
umulh $t2,$a6,$a2
stp $acc4,$acc5,[$tp],#8*2 // t[4..5]
adc $acc2,xzr,xzr // t[10]
adds $acc6,$acc6,$t3
umulh $t3,$a7,$a2
adcs $acc7,$acc7,$t0
mul $t0,$a4,$a3 // lo(a[4..7]*a[3]) (iv)
adcs $acc0,$acc0,$t1
mul $t1,$a5,$a3
adcs $acc1,$acc1,$t2
mul $t2,$a6,$a3
adc $acc2,$acc2,$t3
mul $t3,$a7,$a3
adds $acc7,$acc7,$t0
umulh $t0,$a4,$a3 // hi(a[4..7]*a[3])
adcs $acc0,$acc0,$t1
umulh $t1,$a5,$a3
adcs $acc1,$acc1,$t2
umulh $t2,$a6,$a3
adcs $acc2,$acc2,$t3
umulh $t3,$a7,$a3
stp $acc6,$acc7,[$tp],#8*2 // t[6..7]
adc $acc3,xzr,xzr // t[11]
adds $acc0,$acc0,$t0
mul $t0,$a5,$a4 // lo(a[5..7]*a[4]) (v)
adcs $acc1,$acc1,$t1
mul $t1,$a6,$a4
adcs $acc2,$acc2,$t2
mul $t2,$a7,$a4
adc $acc3,$acc3,$t3
umulh $t3,$a5,$a4 // hi(a[5..7]*a[4])
adds $acc1,$acc1,$t0
umulh $t0,$a6,$a4
adcs $acc2,$acc2,$t1
umulh $t1,$a7,$a4
adcs $acc3,$acc3,$t2
mul $t2,$a6,$a5 // lo(a[6..7]*a[5]) (vi)
adc $acc4,xzr,xzr // t[12]
adds $acc2,$acc2,$t3
mul $t3,$a7,$a5
adcs $acc3,$acc3,$t0
umulh $t0,$a6,$a5 // hi(a[6..7]*a[5])
adc $acc4,$acc4,$t1
umulh $t1,$a7,$a5
adds $acc3,$acc3,$t2
mul $t2,$a7,$a6 // lo(a[7]*a[6]) (vii)
adcs $acc4,$acc4,$t3
umulh $t3,$a7,$a6 // hi(a[7]*a[6])
adc $acc5,xzr,xzr // t[13]
adds $acc4,$acc4,$t0
sub $cnt,$ap_end,$ap // done yet?
adc $acc5,$acc5,$t1
adds $acc5,$acc5,$t2
sub $t0,$ap_end,$num // rewinded ap
adc $acc6,xzr,xzr // t[14]
add $acc6,$acc6,$t3
cbz $cnt,.Lsqr8x_outer_break
mov $n0,$a0
ldp $a0,$a1,[$tp,#8*0]
ldp $a2,$a3,[$tp,#8*2]
ldp $a4,$a5,[$tp,#8*4]
ldp $a6,$a7,[$tp,#8*6]
adds $acc0,$acc0,$a0
adcs $acc1,$acc1,$a1
ldp $a0,$a1,[$ap,#8*0]
adcs $acc2,$acc2,$a2
adcs $acc3,$acc3,$a3
ldp $a2,$a3,[$ap,#8*2]
adcs $acc4,$acc4,$a4
adcs $acc5,$acc5,$a5
ldp $a4,$a5,[$ap,#8*4]
adcs $acc6,$acc6,$a6
mov $rp,$ap
adcs $acc7,xzr,$a7
ldp $a6,$a7,[$ap,#8*6]
add $ap,$ap,#8*8
//adc $carry,xzr,xzr // moved below
mov $cnt,#-8*8
// a[8]a[0]
// a[9]a[0]
// a[a]a[0]
// a[b]a[0]
// a[c]a[0]
// a[d]a[0]
// a[e]a[0]
// a[f]a[0]
// a[8]a[1]
// a[f]a[1]........................
// a[8]a[2]
// a[f]a[2]........................
// a[8]a[3]
// a[f]a[3]........................
// a[8]a[4]
// a[f]a[4]........................
// a[8]a[5]
// a[f]a[5]........................
// a[8]a[6]
// a[f]a[6]........................
// a[8]a[7]
// a[f]a[7]........................
.Lsqr8x_mul:
mul $t0,$a0,$n0
adc $carry,xzr,xzr // carry bit, modulo-scheduled
mul $t1,$a1,$n0
add $cnt,$cnt,#8
mul $t2,$a2,$n0
mul $t3,$a3,$n0
adds $acc0,$acc0,$t0
mul $t0,$a4,$n0
adcs $acc1,$acc1,$t1
mul $t1,$a5,$n0
adcs $acc2,$acc2,$t2
mul $t2,$a6,$n0
adcs $acc3,$acc3,$t3
mul $t3,$a7,$n0
adcs $acc4,$acc4,$t0
umulh $t0,$a0,$n0
adcs $acc5,$acc5,$t1
umulh $t1,$a1,$n0
adcs $acc6,$acc6,$t2
umulh $t2,$a2,$n0
adcs $acc7,$acc7,$t3
umulh $t3,$a3,$n0
adc $carry,$carry,xzr
str $acc0,[$tp],#8
adds $acc0,$acc1,$t0
umulh $t0,$a4,$n0
adcs $acc1,$acc2,$t1
umulh $t1,$a5,$n0
adcs $acc2,$acc3,$t2
umulh $t2,$a6,$n0
adcs $acc3,$acc4,$t3
umulh $t3,$a7,$n0
ldr $n0,[$rp,$cnt]
adcs $acc4,$acc5,$t0
adcs $acc5,$acc6,$t1
adcs $acc6,$acc7,$t2
adcs $acc7,$carry,$t3
//adc $carry,xzr,xzr // moved above
cbnz $cnt,.Lsqr8x_mul
// note that carry flag is guaranteed
// to be zero at this point
cmp $ap,$ap_end // done yet?
b.eq .Lsqr8x_break
ldp $a0,$a1,[$tp,#8*0]
ldp $a2,$a3,[$tp,#8*2]
ldp $a4,$a5,[$tp,#8*4]
ldp $a6,$a7,[$tp,#8*6]
adds $acc0,$acc0,$a0
ldur $n0,[$rp,#-8*8]
adcs $acc1,$acc1,$a1
ldp $a0,$a1,[$ap,#8*0]
adcs $acc2,$acc2,$a2
adcs $acc3,$acc3,$a3
ldp $a2,$a3,[$ap,#8*2]
adcs $acc4,$acc4,$a4
adcs $acc5,$acc5,$a5
ldp $a4,$a5,[$ap,#8*4]
adcs $acc6,$acc6,$a6
mov $cnt,#-8*8
adcs $acc7,$acc7,$a7
ldp $a6,$a7,[$ap,#8*6]
add $ap,$ap,#8*8
//adc $carry,xzr,xzr // moved above
b .Lsqr8x_mul
.align 4
.Lsqr8x_break:
ldp $a0,$a1,[$rp,#8*0]
add $ap,$rp,#8*8
ldp $a2,$a3,[$rp,#8*2]
sub $t0,$ap_end,$ap // is it last iteration?
ldp $a4,$a5,[$rp,#8*4]
sub $t1,$tp,$t0
ldp $a6,$a7,[$rp,#8*6]
cbz $t0,.Lsqr8x_outer_loop
stp $acc0,$acc1,[$tp,#8*0]
ldp $acc0,$acc1,[$t1,#8*0]
stp $acc2,$acc3,[$tp,#8*2]
ldp $acc2,$acc3,[$t1,#8*2]
stp $acc4,$acc5,[$tp,#8*4]
ldp $acc4,$acc5,[$t1,#8*4]
stp $acc6,$acc7,[$tp,#8*6]
mov $tp,$t1
ldp $acc6,$acc7,[$t1,#8*6]
b .Lsqr8x_outer_loop
.align 4
.Lsqr8x_outer_break:
// Now multiply above result by 2 and add a[n-1]*a[n-1]|...|a[0]*a[0]
ldp $a1,$a3,[$t0,#8*0] // recall that $t0 is &a[0]
ldp $t1,$t2,[sp,#8*1]
ldp $a5,$a7,[$t0,#8*2]
add $ap,$t0,#8*4
ldp $t3,$t0,[sp,#8*3]
stp $acc0,$acc1,[$tp,#8*0]
mul $acc0,$a1,$a1
stp $acc2,$acc3,[$tp,#8*2]
umulh $a1,$a1,$a1
stp $acc4,$acc5,[$tp,#8*4]
mul $a2,$a3,$a3
stp $acc6,$acc7,[$tp,#8*6]
mov $tp,sp
umulh $a3,$a3,$a3
adds $acc1,$a1,$t1,lsl#1
extr $t1,$t2,$t1,#63
sub $cnt,$num,#8*4
.Lsqr4x_shift_n_add:
adcs $acc2,$a2,$t1
extr $t2,$t3,$t2,#63
sub $cnt,$cnt,#8*4
adcs $acc3,$a3,$t2
ldp $t1,$t2,[$tp,#8*5]
mul $a4,$a5,$a5
ldp $a1,$a3,[$ap],#8*2
umulh $a5,$a5,$a5
mul $a6,$a7,$a7
umulh $a7,$a7,$a7
extr $t3,$t0,$t3,#63
stp $acc0,$acc1,[$tp,#8*0]
adcs $acc4,$a4,$t3
extr $t0,$t1,$t0,#63
stp $acc2,$acc3,[$tp,#8*2]
adcs $acc5,$a5,$t0
ldp $t3,$t0,[$tp,#8*7]
extr $t1,$t2,$t1,#63
adcs $acc6,$a6,$t1
extr $t2,$t3,$t2,#63
adcs $acc7,$a7,$t2
ldp $t1,$t2,[$tp,#8*9]
mul $a0,$a1,$a1
ldp $a5,$a7,[$ap],#8*2
umulh $a1,$a1,$a1
mul $a2,$a3,$a3
umulh $a3,$a3,$a3
stp $acc4,$acc5,[$tp,#8*4]
extr $t3,$t0,$t3,#63
stp $acc6,$acc7,[$tp,#8*6]
add $tp,$tp,#8*8
adcs $acc0,$a0,$t3
extr $t0,$t1,$t0,#63
adcs $acc1,$a1,$t0
ldp $t3,$t0,[$tp,#8*3]
extr $t1,$t2,$t1,#63
cbnz $cnt,.Lsqr4x_shift_n_add
___
my ($np,$np_end)=($ap,$ap_end);
$code.=<<___;
ldp $np,$n0,[x29,#104] // pull np and n0
adcs $acc2,$a2,$t1
extr $t2,$t3,$t2,#63
adcs $acc3,$a3,$t2
ldp $t1,$t2,[$tp,#8*5]
mul $a4,$a5,$a5
umulh $a5,$a5,$a5
stp $acc0,$acc1,[$tp,#8*0]
mul $a6,$a7,$a7
umulh $a7,$a7,$a7
stp $acc2,$acc3,[$tp,#8*2]
extr $t3,$t0,$t3,#63
adcs $acc4,$a4,$t3
extr $t0,$t1,$t0,#63
ldp $acc0,$acc1,[sp,#8*0]
adcs $acc5,$a5,$t0
extr $t1,$t2,$t1,#63
ldp $a0,$a1,[$np,#8*0]
adcs $acc6,$a6,$t1
extr $t2,xzr,$t2,#63
ldp $a2,$a3,[$np,#8*2]
adc $acc7,$a7,$t2
ldp $a4,$a5,[$np,#8*4]
// Reduce by 512 bits per iteration
mul $na0,$n0,$acc0 // t[0]*n0
ldp $a6,$a7,[$np,#8*6]
add $np_end,$np,$num
ldp $acc2,$acc3,[sp,#8*2]
stp $acc4,$acc5,[$tp,#8*4]
ldp $acc4,$acc5,[sp,#8*4]
stp $acc6,$acc7,[$tp,#8*6]
ldp $acc6,$acc7,[sp,#8*6]
add $np,$np,#8*8
mov $topmost,xzr // initial top-most carry
mov $tp,sp
mov $cnt,#8
.Lsqr8x_reduction:
// (*) mul $t0,$a0,$na0 // lo(n[0-7])*lo(t[0]*n0)
mul $t1,$a1,$na0
sub $cnt,$cnt,#1
mul $t2,$a2,$na0
str $na0,[$tp],#8 // put aside t[0]*n0 for tail processing
mul $t3,$a3,$na0
// (*) adds xzr,$acc0,$t0
subs xzr,$acc0,#1 // (*)
mul $t0,$a4,$na0
adcs $acc0,$acc1,$t1
mul $t1,$a5,$na0
adcs $acc1,$acc2,$t2
mul $t2,$a6,$na0
adcs $acc2,$acc3,$t3
mul $t3,$a7,$na0
adcs $acc3,$acc4,$t0
umulh $t0,$a0,$na0 // hi(n[0-7])*lo(t[0]*n0)
adcs $acc4,$acc5,$t1
umulh $t1,$a1,$na0
adcs $acc5,$acc6,$t2
umulh $t2,$a2,$na0
adcs $acc6,$acc7,$t3
umulh $t3,$a3,$na0
adc $acc7,xzr,xzr
adds $acc0,$acc0,$t0
umulh $t0,$a4,$na0
adcs $acc1,$acc1,$t1
umulh $t1,$a5,$na0
adcs $acc2,$acc2,$t2
umulh $t2,$a6,$na0
adcs $acc3,$acc3,$t3
umulh $t3,$a7,$na0
mul $na0,$n0,$acc0 // next t[0]*n0
adcs $acc4,$acc4,$t0
adcs $acc5,$acc5,$t1
adcs $acc6,$acc6,$t2
adc $acc7,$acc7,$t3
cbnz $cnt,.Lsqr8x_reduction
ldp $t0,$t1,[$tp,#8*0]
ldp $t2,$t3,[$tp,#8*2]
mov $rp,$tp
sub $cnt,$np_end,$np // done yet?
adds $acc0,$acc0,$t0
adcs $acc1,$acc1,$t1
ldp $t0,$t1,[$tp,#8*4]
adcs $acc2,$acc2,$t2
adcs $acc3,$acc3,$t3
ldp $t2,$t3,[$tp,#8*6]
adcs $acc4,$acc4,$t0
adcs $acc5,$acc5,$t1
adcs $acc6,$acc6,$t2
adcs $acc7,$acc7,$t3
//adc $carry,xzr,xzr // moved below
cbz $cnt,.Lsqr8x8_post_condition
ldur $n0,[$tp,#-8*8]
ldp $a0,$a1,[$np,#8*0]
ldp $a2,$a3,[$np,#8*2]
ldp $a4,$a5,[$np,#8*4]
mov $cnt,#-8*8
ldp $a6,$a7,[$np,#8*6]
add $np,$np,#8*8
.Lsqr8x_tail:
mul $t0,$a0,$n0
adc $carry,xzr,xzr // carry bit, modulo-scheduled
mul $t1,$a1,$n0
add $cnt,$cnt,#8
mul $t2,$a2,$n0
mul $t3,$a3,$n0
adds $acc0,$acc0,$t0
mul $t0,$a4,$n0
adcs $acc1,$acc1,$t1
mul $t1,$a5,$n0
adcs $acc2,$acc2,$t2
mul $t2,$a6,$n0
adcs $acc3,$acc3,$t3
mul $t3,$a7,$n0
adcs $acc4,$acc4,$t0
umulh $t0,$a0,$n0
adcs $acc5,$acc5,$t1
umulh $t1,$a1,$n0
adcs $acc6,$acc6,$t2
umulh $t2,$a2,$n0
adcs $acc7,$acc7,$t3
umulh $t3,$a3,$n0
adc $carry,$carry,xzr
str $acc0,[$tp],#8
adds $acc0,$acc1,$t0
umulh $t0,$a4,$n0
adcs $acc1,$acc2,$t1
umulh $t1,$a5,$n0
adcs $acc2,$acc3,$t2
umulh $t2,$a6,$n0
adcs $acc3,$acc4,$t3
umulh $t3,$a7,$n0
ldr $n0,[$rp,$cnt]
adcs $acc4,$acc5,$t0
adcs $acc5,$acc6,$t1
adcs $acc6,$acc7,$t2
adcs $acc7,$carry,$t3
//adc $carry,xzr,xzr // moved above
cbnz $cnt,.Lsqr8x_tail
// note that carry flag is guaranteed
// to be zero at this point
ldp $a0,$a1,[$tp,#8*0]
sub $cnt,$np_end,$np // done yet?
sub $t2,$np_end,$num // rewinded np
ldp $a2,$a3,[$tp,#8*2]
ldp $a4,$a5,[$tp,#8*4]
ldp $a6,$a7,[$tp,#8*6]
cbz $cnt,.Lsqr8x_tail_break
ldur $n0,[$rp,#-8*8]
adds $acc0,$acc0,$a0
adcs $acc1,$acc1,$a1
ldp $a0,$a1,[$np,#8*0]
adcs $acc2,$acc2,$a2
adcs $acc3,$acc3,$a3
ldp $a2,$a3,[$np,#8*2]
adcs $acc4,$acc4,$a4
adcs $acc5,$acc5,$a5
ldp $a4,$a5,[$np,#8*4]
adcs $acc6,$acc6,$a6
mov $cnt,#-8*8
adcs $acc7,$acc7,$a7
ldp $a6,$a7,[$np,#8*6]
add $np,$np,#8*8
//adc $carry,xzr,xzr // moved above
b .Lsqr8x_tail
.align 4
.Lsqr8x_tail_break:
ldr $n0,[x29,#112] // pull n0
add $cnt,$tp,#8*8 // end of current t[num] window
subs xzr,$topmost,#1 // "move" top-most carry to carry bit
adcs $t0,$acc0,$a0
adcs $t1,$acc1,$a1
ldp $acc0,$acc1,[$rp,#8*0]
adcs $acc2,$acc2,$a2
ldp $a0,$a1,[$t2,#8*0] // recall that $t2 is &n[0]
adcs $acc3,$acc3,$a3
ldp $a2,$a3,[$t2,#8*2]
adcs $acc4,$acc4,$a4
adcs $acc5,$acc5,$a5
ldp $a4,$a5,[$t2,#8*4]
adcs $acc6,$acc6,$a6
adcs $acc7,$acc7,$a7
ldp $a6,$a7,[$t2,#8*6]
add $np,$t2,#8*8
adc $topmost,xzr,xzr // top-most carry
mul $na0,$n0,$acc0
stp $t0,$t1,[$tp,#8*0]
stp $acc2,$acc3,[$tp,#8*2]
ldp $acc2,$acc3,[$rp,#8*2]
stp $acc4,$acc5,[$tp,#8*4]
ldp $acc4,$acc5,[$rp,#8*4]
cmp $cnt,x29 // did we hit the bottom?
stp $acc6,$acc7,[$tp,#8*6]
mov $tp,$rp // slide the window
ldp $acc6,$acc7,[$rp,#8*6]
mov $cnt,#8
b.ne .Lsqr8x_reduction
// Final step. We see if result is larger than modulus, and
// if it is, subtract the modulus. But comparison implies
// subtraction. So we subtract modulus, see if it borrowed,
// and conditionally copy original value.
ldr $rp,[x29,#96] // pull rp
add $tp,$tp,#8*8
subs $t0,$acc0,$a0
sbcs $t1,$acc1,$a1
sub $cnt,$num,#8*8
mov $ap_end,$rp // $rp copy
.Lsqr8x_sub:
sbcs $t2,$acc2,$a2
ldp $a0,$a1,[$np,#8*0]
sbcs $t3,$acc3,$a3
stp $t0,$t1,[$rp,#8*0]
sbcs $t0,$acc4,$a4
ldp $a2,$a3,[$np,#8*2]
sbcs $t1,$acc5,$a5
stp $t2,$t3,[$rp,#8*2]
sbcs $t2,$acc6,$a6
ldp $a4,$a5,[$np,#8*4]
sbcs $t3,$acc7,$a7
ldp $a6,$a7,[$np,#8*6]
add $np,$np,#8*8
ldp $acc0,$acc1,[$tp,#8*0]
sub $cnt,$cnt,#8*8
ldp $acc2,$acc3,[$tp,#8*2]
ldp $acc4,$acc5,[$tp,#8*4]
ldp $acc6,$acc7,[$tp,#8*6]
add $tp,$tp,#8*8
stp $t0,$t1,[$rp,#8*4]
sbcs $t0,$acc0,$a0
stp $t2,$t3,[$rp,#8*6]
add $rp,$rp,#8*8
sbcs $t1,$acc1,$a1
cbnz $cnt,.Lsqr8x_sub
sbcs $t2,$acc2,$a2
mov $tp,sp
add $ap,sp,$num
ldp $a0,$a1,[$ap_end,#8*0]
sbcs $t3,$acc3,$a3
stp $t0,$t1,[$rp,#8*0]
sbcs $t0,$acc4,$a4
ldp $a2,$a3,[$ap_end,#8*2]
sbcs $t1,$acc5,$a5
stp $t2,$t3,[$rp,#8*2]
sbcs $t2,$acc6,$a6
ldp $acc0,$acc1,[$ap,#8*0]
sbcs $t3,$acc7,$a7
ldp $acc2,$acc3,[$ap,#8*2]
sbcs xzr,$topmost,xzr // did it borrow?
ldr x30,[x29,#8] // pull return address
stp $t0,$t1,[$rp,#8*4]
stp $t2,$t3,[$rp,#8*6]
sub $cnt,$num,#8*4
.Lsqr4x_cond_copy:
sub $cnt,$cnt,#8*4
csel $t0,$acc0,$a0,lo
stp xzr,xzr,[$tp,#8*0]
csel $t1,$acc1,$a1,lo
ldp $a0,$a1,[$ap_end,#8*4]
ldp $acc0,$acc1,[$ap,#8*4]
csel $t2,$acc2,$a2,lo
stp xzr,xzr,[$tp,#8*2]
add $tp,$tp,#8*4
csel $t3,$acc3,$a3,lo
ldp $a2,$a3,[$ap_end,#8*6]
ldp $acc2,$acc3,[$ap,#8*6]
add $ap,$ap,#8*4
stp $t0,$t1,[$ap_end,#8*0]
stp $t2,$t3,[$ap_end,#8*2]
add $ap_end,$ap_end,#8*4
stp xzr,xzr,[$ap,#8*0]
stp xzr,xzr,[$ap,#8*2]
cbnz $cnt,.Lsqr4x_cond_copy
csel $t0,$acc0,$a0,lo
stp xzr,xzr,[$tp,#8*0]
csel $t1,$acc1,$a1,lo
stp xzr,xzr,[$tp,#8*2]
csel $t2,$acc2,$a2,lo
csel $t3,$acc3,$a3,lo
stp $t0,$t1,[$ap_end,#8*0]
stp $t2,$t3,[$ap_end,#8*2]
b .Lsqr8x_done
.align 4
.Lsqr8x8_post_condition:
adc $carry,xzr,xzr
ldr x30,[x29,#8] // pull return address
// $acc0-7,$carry hold result, $a0-7 hold modulus
subs $a0,$acc0,$a0
ldr $ap,[x29,#96] // pull rp
sbcs $a1,$acc1,$a1
stp xzr,xzr,[sp,#8*0]
sbcs $a2,$acc2,$a2
stp xzr,xzr,[sp,#8*2]
sbcs $a3,$acc3,$a3
stp xzr,xzr,[sp,#8*4]
sbcs $a4,$acc4,$a4
stp xzr,xzr,[sp,#8*6]
sbcs $a5,$acc5,$a5
stp xzr,xzr,[sp,#8*8]
sbcs $a6,$acc6,$a6
stp xzr,xzr,[sp,#8*10]
sbcs $a7,$acc7,$a7
stp xzr,xzr,[sp,#8*12]
sbcs $carry,$carry,xzr // did it borrow?
stp xzr,xzr,[sp,#8*14]
// $a0-7 hold result-modulus
csel $a0,$acc0,$a0,lo
csel $a1,$acc1,$a1,lo
csel $a2,$acc2,$a2,lo
csel $a3,$acc3,$a3,lo
stp $a0,$a1,[$ap,#8*0]
csel $a4,$acc4,$a4,lo
csel $a5,$acc5,$a5,lo
stp $a2,$a3,[$ap,#8*2]
csel $a6,$acc6,$a6,lo
csel $a7,$acc7,$a7,lo
stp $a4,$a5,[$ap,#8*4]
stp $a6,$a7,[$ap,#8*6]
.Lsqr8x_done:
ldp x19,x20,[x29,#16]
mov sp,x29
ldp x21,x22,[x29,#32]
mov x0,#1
ldp x23,x24,[x29,#48]
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldr x29,[sp],#128
// x30 is loaded earlier
AARCH64_VALIDATE_LINK_REGISTER
ret
.size __bn_sqr8x_mont,.-__bn_sqr8x_mont
___
}
{
########################################################################
# Even though this might look as ARMv8 adaptation of mulx4x_mont from
# x86_64-mont5 module, it's different in sense that it performs
# reduction 256 bits at a time.
my ($a0,$a1,$a2,$a3,
$t0,$t1,$t2,$t3,
$m0,$m1,$m2,$m3,
$acc0,$acc1,$acc2,$acc3,$acc4,
$bi,$mi,$tp,$ap_end,$cnt) = map("x$_",(6..17,19..28));
my $bp_end=$rp;
my ($carry,$topmost) = ($rp,"x30");
$code.=<<___;
.type __bn_mul4x_mont,%function
.align 5
__bn_mul4x_mont:
// Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to
// only from bn_mul_mont (or __bn_sqr8x_mont from bn_mul_mont) which has already signed the return address.
stp x29,x30,[sp,#-128]!
add x29,sp,#0
stp x19,x20,[sp,#16]
stp x21,x22,[sp,#32]
stp x23,x24,[sp,#48]
stp x25,x26,[sp,#64]
stp x27,x28,[sp,#80]
sub $tp,sp,$num,lsl#3
lsl $num,$num,#3
ldr $n0,[$n0] // *n0
sub sp,$tp,#8*4 // alloca
add $t0,$bp,$num
add $ap_end,$ap,$num
stp $rp,$t0,[x29,#96] // offload rp and &b[num]
ldr $bi,[$bp,#8*0] // b[0]
ldp $a0,$a1,[$ap,#8*0] // a[0..3]
ldp $a2,$a3,[$ap,#8*2]
add $ap,$ap,#8*4
mov $acc0,xzr
mov $acc1,xzr
mov $acc2,xzr
mov $acc3,xzr
ldp $m0,$m1,[$np,#8*0] // n[0..3]
ldp $m2,$m3,[$np,#8*2]
adds $np,$np,#8*4 // clear carry bit
mov $carry,xzr
mov $cnt,#0
mov $tp,sp
.Loop_mul4x_1st_reduction:
mul $t0,$a0,$bi // lo(a[0..3]*b[0])
adc $carry,$carry,xzr // modulo-scheduled
mul $t1,$a1,$bi
add $cnt,$cnt,#8
mul $t2,$a2,$bi
and $cnt,$cnt,#31
mul $t3,$a3,$bi
adds $acc0,$acc0,$t0
umulh $t0,$a0,$bi // hi(a[0..3]*b[0])
adcs $acc1,$acc1,$t1
mul $mi,$acc0,$n0 // t[0]*n0
adcs $acc2,$acc2,$t2
umulh $t1,$a1,$bi
adcs $acc3,$acc3,$t3
umulh $t2,$a2,$bi
adc $acc4,xzr,xzr
umulh $t3,$a3,$bi
ldr $bi,[$bp,$cnt] // next b[i] (or b[0])
adds $acc1,$acc1,$t0
// (*) mul $t0,$m0,$mi // lo(n[0..3]*t[0]*n0)
str $mi,[$tp],#8 // put aside t[0]*n0 for tail processing
adcs $acc2,$acc2,$t1
mul $t1,$m1,$mi
adcs $acc3,$acc3,$t2
mul $t2,$m2,$mi
adc $acc4,$acc4,$t3 // can't overflow
mul $t3,$m3,$mi
// (*) adds xzr,$acc0,$t0
subs xzr,$acc0,#1 // (*)
umulh $t0,$m0,$mi // hi(n[0..3]*t[0]*n0)
adcs $acc0,$acc1,$t1
umulh $t1,$m1,$mi
adcs $acc1,$acc2,$t2
umulh $t2,$m2,$mi
adcs $acc2,$acc3,$t3
umulh $t3,$m3,$mi
adcs $acc3,$acc4,$carry
adc $carry,xzr,xzr
adds $acc0,$acc0,$t0
sub $t0,$ap_end,$ap
adcs $acc1,$acc1,$t1
adcs $acc2,$acc2,$t2
adcs $acc3,$acc3,$t3
//adc $carry,$carry,xzr
cbnz $cnt,.Loop_mul4x_1st_reduction
cbz $t0,.Lmul4x4_post_condition
ldp $a0,$a1,[$ap,#8*0] // a[4..7]
ldp $a2,$a3,[$ap,#8*2]
add $ap,$ap,#8*4
ldr $mi,[sp] // a[0]*n0
ldp $m0,$m1,[$np,#8*0] // n[4..7]
ldp $m2,$m3,[$np,#8*2]
add $np,$np,#8*4
.Loop_mul4x_1st_tail:
mul $t0,$a0,$bi // lo(a[4..7]*b[i])
adc $carry,$carry,xzr // modulo-scheduled
mul $t1,$a1,$bi
add $cnt,$cnt,#8
mul $t2,$a2,$bi
and $cnt,$cnt,#31
mul $t3,$a3,$bi
adds $acc0,$acc0,$t0
umulh $t0,$a0,$bi // hi(a[4..7]*b[i])
adcs $acc1,$acc1,$t1
umulh $t1,$a1,$bi
adcs $acc2,$acc2,$t2
umulh $t2,$a2,$bi
adcs $acc3,$acc3,$t3
umulh $t3,$a3,$bi
adc $acc4,xzr,xzr
ldr $bi,[$bp,$cnt] // next b[i] (or b[0])
adds $acc1,$acc1,$t0
mul $t0,$m0,$mi // lo(n[4..7]*a[0]*n0)
adcs $acc2,$acc2,$t1
mul $t1,$m1,$mi
adcs $acc3,$acc3,$t2
mul $t2,$m2,$mi
adc $acc4,$acc4,$t3 // can't overflow
mul $t3,$m3,$mi
adds $acc0,$acc0,$t0
umulh $t0,$m0,$mi // hi(n[4..7]*a[0]*n0)
adcs $acc1,$acc1,$t1
umulh $t1,$m1,$mi
adcs $acc2,$acc2,$t2
umulh $t2,$m2,$mi
adcs $acc3,$acc3,$t3
adcs $acc4,$acc4,$carry
umulh $t3,$m3,$mi
adc $carry,xzr,xzr
ldr $mi,[sp,$cnt] // next t[0]*n0
str $acc0,[$tp],#8 // result!!!
adds $acc0,$acc1,$t0
sub $t0,$ap_end,$ap // done yet?
adcs $acc1,$acc2,$t1
adcs $acc2,$acc3,$t2
adcs $acc3,$acc4,$t3
//adc $carry,$carry,xzr
cbnz $cnt,.Loop_mul4x_1st_tail
sub $t1,$ap_end,$num // rewinded $ap
cbz $t0,.Lmul4x_proceed
ldp $a0,$a1,[$ap,#8*0]
ldp $a2,$a3,[$ap,#8*2]
add $ap,$ap,#8*4
ldp $m0,$m1,[$np,#8*0]
ldp $m2,$m3,[$np,#8*2]
add $np,$np,#8*4
b .Loop_mul4x_1st_tail
.align 5
.Lmul4x_proceed:
ldr $bi,[$bp,#8*4]! // *++b
adc $topmost,$carry,xzr
ldp $a0,$a1,[$t1,#8*0] // a[0..3]
sub $np,$np,$num // rewind np
ldp $a2,$a3,[$t1,#8*2]
add $ap,$t1,#8*4
stp $acc0,$acc1,[$tp,#8*0] // result!!!
ldp $acc0,$acc1,[sp,#8*4] // t[0..3]
stp $acc2,$acc3,[$tp,#8*2] // result!!!
ldp $acc2,$acc3,[sp,#8*6]
ldp $m0,$m1,[$np,#8*0] // n[0..3]
mov $tp,sp
ldp $m2,$m3,[$np,#8*2]
adds $np,$np,#8*4 // clear carry bit
mov $carry,xzr
.align 4
.Loop_mul4x_reduction:
mul $t0,$a0,$bi // lo(a[0..3]*b[4])
adc $carry,$carry,xzr // modulo-scheduled
mul $t1,$a1,$bi
add $cnt,$cnt,#8
mul $t2,$a2,$bi
and $cnt,$cnt,#31
mul $t3,$a3,$bi
adds $acc0,$acc0,$t0
umulh $t0,$a0,$bi // hi(a[0..3]*b[4])
adcs $acc1,$acc1,$t1
mul $mi,$acc0,$n0 // t[0]*n0
adcs $acc2,$acc2,$t2
umulh $t1,$a1,$bi
adcs $acc3,$acc3,$t3
umulh $t2,$a2,$bi
adc $acc4,xzr,xzr
umulh $t3,$a3,$bi
ldr $bi,[$bp,$cnt] // next b[i]
adds $acc1,$acc1,$t0
// (*) mul $t0,$m0,$mi
str $mi,[$tp],#8 // put aside t[0]*n0 for tail processing
adcs $acc2,$acc2,$t1
mul $t1,$m1,$mi // lo(n[0..3]*t[0]*n0
adcs $acc3,$acc3,$t2
mul $t2,$m2,$mi
adc $acc4,$acc4,$t3 // can't overflow
mul $t3,$m3,$mi
// (*) adds xzr,$acc0,$t0
subs xzr,$acc0,#1 // (*)
umulh $t0,$m0,$mi // hi(n[0..3]*t[0]*n0
adcs $acc0,$acc1,$t1
umulh $t1,$m1,$mi
adcs $acc1,$acc2,$t2
umulh $t2,$m2,$mi
adcs $acc2,$acc3,$t3
umulh $t3,$m3,$mi
adcs $acc3,$acc4,$carry
adc $carry,xzr,xzr
adds $acc0,$acc0,$t0
adcs $acc1,$acc1,$t1
adcs $acc2,$acc2,$t2
adcs $acc3,$acc3,$t3
//adc $carry,$carry,xzr
cbnz $cnt,.Loop_mul4x_reduction
adc $carry,$carry,xzr
ldp $t0,$t1,[$tp,#8*4] // t[4..7]
ldp $t2,$t3,[$tp,#8*6]
ldp $a0,$a1,[$ap,#8*0] // a[4..7]
ldp $a2,$a3,[$ap,#8*2]
add $ap,$ap,#8*4
adds $acc0,$acc0,$t0
adcs $acc1,$acc1,$t1
adcs $acc2,$acc2,$t2
adcs $acc3,$acc3,$t3
//adc $carry,$carry,xzr
ldr $mi,[sp] // t[0]*n0
ldp $m0,$m1,[$np,#8*0] // n[4..7]
ldp $m2,$m3,[$np,#8*2]
add $np,$np,#8*4
.align 4
.Loop_mul4x_tail:
mul $t0,$a0,$bi // lo(a[4..7]*b[4])
adc $carry,$carry,xzr // modulo-scheduled
mul $t1,$a1,$bi
add $cnt,$cnt,#8
mul $t2,$a2,$bi
and $cnt,$cnt,#31
mul $t3,$a3,$bi
adds $acc0,$acc0,$t0
umulh $t0,$a0,$bi // hi(a[4..7]*b[4])
adcs $acc1,$acc1,$t1
umulh $t1,$a1,$bi
adcs $acc2,$acc2,$t2
umulh $t2,$a2,$bi
adcs $acc3,$acc3,$t3
umulh $t3,$a3,$bi
adc $acc4,xzr,xzr
ldr $bi,[$bp,$cnt] // next b[i]
adds $acc1,$acc1,$t0
mul $t0,$m0,$mi // lo(n[4..7]*t[0]*n0)
adcs $acc2,$acc2,$t1
mul $t1,$m1,$mi
adcs $acc3,$acc3,$t2
mul $t2,$m2,$mi
adc $acc4,$acc4,$t3 // can't overflow
mul $t3,$m3,$mi
adds $acc0,$acc0,$t0
umulh $t0,$m0,$mi // hi(n[4..7]*t[0]*n0)
adcs $acc1,$acc1,$t1
umulh $t1,$m1,$mi
adcs $acc2,$acc2,$t2
umulh $t2,$m2,$mi
adcs $acc3,$acc3,$t3
umulh $t3,$m3,$mi
adcs $acc4,$acc4,$carry
ldr $mi,[sp,$cnt] // next a[0]*n0
adc $carry,xzr,xzr
str $acc0,[$tp],#8 // result!!!
adds $acc0,$acc1,$t0
sub $t0,$ap_end,$ap // done yet?
adcs $acc1,$acc2,$t1
adcs $acc2,$acc3,$t2
adcs $acc3,$acc4,$t3
//adc $carry,$carry,xzr
cbnz $cnt,.Loop_mul4x_tail
sub $t1,$np,$num // rewinded np?
adc $carry,$carry,xzr
cbz $t0,.Loop_mul4x_break
ldp $t0,$t1,[$tp,#8*4]
ldp $t2,$t3,[$tp,#8*6]
ldp $a0,$a1,[$ap,#8*0]
ldp $a2,$a3,[$ap,#8*2]
add $ap,$ap,#8*4
adds $acc0,$acc0,$t0
adcs $acc1,$acc1,$t1
adcs $acc2,$acc2,$t2
adcs $acc3,$acc3,$t3
//adc $carry,$carry,xzr
ldp $m0,$m1,[$np,#8*0]
ldp $m2,$m3,[$np,#8*2]
add $np,$np,#8*4
b .Loop_mul4x_tail
.align 4
.Loop_mul4x_break:
ldp $t2,$t3,[x29,#96] // pull rp and &b[num]
adds $acc0,$acc0,$topmost
add $bp,$bp,#8*4 // bp++
adcs $acc1,$acc1,xzr
sub $ap,$ap,$num // rewind ap
adcs $acc2,$acc2,xzr
stp $acc0,$acc1,[$tp,#8*0] // result!!!
adcs $acc3,$acc3,xzr
ldp $acc0,$acc1,[sp,#8*4] // t[0..3]
adc $topmost,$carry,xzr
stp $acc2,$acc3,[$tp,#8*2] // result!!!
cmp $bp,$t3 // done yet?
ldp $acc2,$acc3,[sp,#8*6]
ldp $m0,$m1,[$t1,#8*0] // n[0..3]
ldp $m2,$m3,[$t1,#8*2]
add $np,$t1,#8*4
b.eq .Lmul4x_post
ldr $bi,[$bp]
ldp $a0,$a1,[$ap,#8*0] // a[0..3]
ldp $a2,$a3,[$ap,#8*2]
adds $ap,$ap,#8*4 // clear carry bit
mov $carry,xzr
mov $tp,sp
b .Loop_mul4x_reduction
.align 4
.Lmul4x_post:
// Final step. We see if result is larger than modulus, and
// if it is, subtract the modulus. But comparison implies
// subtraction. So we subtract modulus, see if it borrowed,
// and conditionally copy original value.
mov $rp,$t2
mov $ap_end,$t2 // $rp copy
subs $t0,$acc0,$m0
add $tp,sp,#8*8
sbcs $t1,$acc1,$m1
sub $cnt,$num,#8*4
.Lmul4x_sub:
sbcs $t2,$acc2,$m2
ldp $m0,$m1,[$np,#8*0]
sub $cnt,$cnt,#8*4
ldp $acc0,$acc1,[$tp,#8*0]
sbcs $t3,$acc3,$m3
ldp $m2,$m3,[$np,#8*2]
add $np,$np,#8*4
ldp $acc2,$acc3,[$tp,#8*2]
add $tp,$tp,#8*4
stp $t0,$t1,[$rp,#8*0]
sbcs $t0,$acc0,$m0
stp $t2,$t3,[$rp,#8*2]
add $rp,$rp,#8*4
sbcs $t1,$acc1,$m1
cbnz $cnt,.Lmul4x_sub
sbcs $t2,$acc2,$m2
mov $tp,sp
add $ap,sp,#8*4
ldp $a0,$a1,[$ap_end,#8*0]
sbcs $t3,$acc3,$m3
stp $t0,$t1,[$rp,#8*0]
ldp $a2,$a3,[$ap_end,#8*2]
stp $t2,$t3,[$rp,#8*2]
ldp $acc0,$acc1,[$ap,#8*0]
ldp $acc2,$acc3,[$ap,#8*2]
sbcs xzr,$topmost,xzr // did it borrow?
ldr x30,[x29,#8] // pull return address
sub $cnt,$num,#8*4
.Lmul4x_cond_copy:
sub $cnt,$cnt,#8*4
csel $t0,$acc0,$a0,lo
stp xzr,xzr,[$tp,#8*0]
csel $t1,$acc1,$a1,lo
ldp $a0,$a1,[$ap_end,#8*4]
ldp $acc0,$acc1,[$ap,#8*4]
csel $t2,$acc2,$a2,lo
stp xzr,xzr,[$tp,#8*2]
add $tp,$tp,#8*4
csel $t3,$acc3,$a3,lo
ldp $a2,$a3,[$ap_end,#8*6]
ldp $acc2,$acc3,[$ap,#8*6]
add $ap,$ap,#8*4
stp $t0,$t1,[$ap_end,#8*0]
stp $t2,$t3,[$ap_end,#8*2]
add $ap_end,$ap_end,#8*4
cbnz $cnt,.Lmul4x_cond_copy
csel $t0,$acc0,$a0,lo
stp xzr,xzr,[$tp,#8*0]
csel $t1,$acc1,$a1,lo
stp xzr,xzr,[$tp,#8*2]
csel $t2,$acc2,$a2,lo
stp xzr,xzr,[$tp,#8*3]
csel $t3,$acc3,$a3,lo
stp xzr,xzr,[$tp,#8*4]
stp $t0,$t1,[$ap_end,#8*0]
stp $t2,$t3,[$ap_end,#8*2]
b .Lmul4x_done
.align 4
.Lmul4x4_post_condition:
adc $carry,$carry,xzr
ldr $ap,[x29,#96] // pull rp
// $acc0-3,$carry hold result, $m0-7 hold modulus
subs $a0,$acc0,$m0
ldr x30,[x29,#8] // pull return address
sbcs $a1,$acc1,$m1
stp xzr,xzr,[sp,#8*0]
sbcs $a2,$acc2,$m2
stp xzr,xzr,[sp,#8*2]
sbcs $a3,$acc3,$m3
stp xzr,xzr,[sp,#8*4]
sbcs xzr,$carry,xzr // did it borrow?
stp xzr,xzr,[sp,#8*6]
// $a0-3 hold result-modulus
csel $a0,$acc0,$a0,lo
csel $a1,$acc1,$a1,lo
csel $a2,$acc2,$a2,lo
csel $a3,$acc3,$a3,lo
stp $a0,$a1,[$ap,#8*0]
stp $a2,$a3,[$ap,#8*2]
.Lmul4x_done:
ldp x19,x20,[x29,#16]
mov sp,x29
ldp x21,x22,[x29,#32]
mov x0,#1
ldp x23,x24,[x29,#48]
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldr x29,[sp],#128
// x30 loaded earlier
AARCH64_VALIDATE_LINK_REGISTER
ret
.size __bn_mul4x_mont,.-__bn_mul4x_mont
___
}
$code.=<<___;
.asciz "Montgomery Multiplication for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 4
___
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/openssl/crypto/bn/bn_exp.c b/crypto/openssl/crypto/bn/bn_exp.c
index 598a592ca139..0e563ad823c7 100644
--- a/crypto/openssl/crypto/bn/bn_exp.c
+++ b/crypto/openssl/crypto/bn/bn_exp.c
@@ -1,1523 +1,1532 @@
/*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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.h"
#include "bn_local.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 "crypto/sparc_arch.h"
# define SPARC_T4_MONT
#endif
/* maximum precomputation table size for *variable* sliding windows */
#define TABLE_SIZE 32
/*
* Beyond this limit the constant time code is disabled due to
* the possible overflow in the computation of powerbufLen in
* BN_mod_exp_mont_consttime.
* When this limit is exceeded, the computation will be done using
* non-constant time code, but it will take very long.
*/
#define BN_CONSTTIME_SIZE_LIMIT (INT_MAX / BN_BYTES / 256)
/* 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() */
ERR_raise(ERR_LIB_BN, 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() */
ERR_raise(ERR_LIB_BN, 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_RECP_CTX_init(&recp);
BN_CTX_start(ctx);
aa = BN_CTX_get(ctx);
val[0] = BN_CTX_get(ctx);
if (val[0] == NULL)
goto err;
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 (r == p) {
BIGNUM *p_dup = BN_CTX_get(ctx);
if (p_dup == NULL || BN_copy(p_dup, p) == NULL)
goto err;
p = p_dup;
}
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
*/
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;
bn_check_top(a);
bn_check_top(p);
bn_check_top(m);
if (!BN_is_odd(m)) {
ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
if (m->top <= BN_CONSTTIME_SIZE_LIMIT
&& (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);
}
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
*/
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,
+int bn_mod_exp_mont_fixed_top(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)) {
ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
top = m->top;
if (top > BN_CONSTTIME_SIZE_LIMIT) {
/* Prevent overflowing the powerbufLen computation below */
return BN_mod_exp_mont(rr, a, p, m, ctx, in_mont);
}
/*
* 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;
}
if (a->neg || BN_ucmp(a, m) >= 0) {
BIGNUM *reduced = BN_CTX_get(ctx);
if (reduced == NULL
|| !BN_nnmod(reduced, a, m, ctx)) {
goto err;
}
a = reduced;
}
#ifdef RSAZ_ENABLED
/*
* 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 && top <= BN_SOFT_LIMIT) {
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 (!bn_to_mont_fixed_top(&am, a, mont, ctx))
goto err;
if (top > BN_SOFT_LIMIT)
goto fallback;
#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 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 https://eprint.iacr.org/2011/239,
* specifically optimization of cache-timing attack countermeasures,
* pre-computation optimization, and Almost Montgomery Multiplication.
*
* The paper discusses a 4-bit window to optimize 512-bit modular
* exponentiation, used in RSA-1024 with CRT, but RSA-1024 is no longer
* important.
*
* |bn_mul_mont_gather5| and |bn_power5| implement the "almost"
* reduction variant, so the values here may not be fully reduced.
* They are bounded by R (i.e. they fit in |top| words), not |m|.
* Additionally, we pass these "almost" reduced inputs into
* |bn_mul_mont|, which implements the normal reduction variant.
* Given those inputs, |bn_mul_mont| may not give reduced
* output, but it will still produce "almost" reduced output.
*/
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);
BN_ULONG *n0 = mont->n0, *np;
/*
* BN_to_montgomery can contaminate words above .top [in
* BN_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));
}
}
tmp.top = top;
/*
* The result is now in |tmp| in Montgomery form, but it may not be
* fully reduced. This is within bounds for |BN_from_montgomery|
* (tmp < R <= m*R) so it will, when converting from Montgomery form,
* produce a fully reduced result.
*
* This differs from Figure 2 of the paper, which uses AMM(h, 1) to
* convert from Montgomery form with unreduced output, followed by an
* extra reduction step. In the paper's terminology, we replace
* steps 9 and 10 with MM(h, 1).
*/
} else
#endif
{
fallback:
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,
* 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))
+ if (!bn_from_mont_fixed_top(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_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *in_mont)
+{
+ bn_check_top(a);
+ bn_check_top(p);
+ bn_check_top(m);
+ if (!bn_mod_exp_mont_fixed_top(rr, a, p, m, ctx, in_mont))
+ return 0;
+ bn_correct_top(rr);
+ return 1;
+}
+
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() */
ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
bn_check_top(p);
bn_check_top(m);
if (!BN_is_odd(m)) {
ERR_raise(ERR_LIB_BN, 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() */
ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (r == m) {
ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
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 (r == p) {
BIGNUM *p_dup = BN_CTX_get(ctx);
if (p_dup == NULL || BN_copy(p_dup, p) == NULL)
goto err;
p = p_dup;
}
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
*/
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;
}
/*
* This is a variant of modular exponentiation optimization that does
* parallel 2-primes exponentiation using 256-bit (AVX512VL) AVX512_IFMA ISA
* in 52-bit binary redundant representation.
* If such instructions are not available, or input data size is not supported,
* it falls back to two BN_mod_exp_mont_consttime() calls.
*/
int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1,
const BIGNUM *m1, BN_MONT_CTX *in_mont1,
BIGNUM *rr2, const BIGNUM *a2, const BIGNUM *p2,
const BIGNUM *m2, BN_MONT_CTX *in_mont2,
BN_CTX *ctx)
{
int ret = 0;
#ifdef RSAZ_ENABLED
BN_MONT_CTX *mont1 = NULL;
BN_MONT_CTX *mont2 = NULL;
if (ossl_rsaz_avx512ifma_eligible() &&
((a1->top == 16) && (p1->top == 16) && (BN_num_bits(m1) == 1024) &&
(a2->top == 16) && (p2->top == 16) && (BN_num_bits(m2) == 1024))) {
if (bn_wexpand(rr1, 16) == NULL)
goto err;
if (bn_wexpand(rr2, 16) == NULL)
goto err;
/* Ensure that montgomery contexts are initialized */
if (in_mont1 != NULL) {
mont1 = in_mont1;
} else {
if ((mont1 = BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(mont1, m1, ctx))
goto err;
}
if (in_mont2 != NULL) {
mont2 = in_mont2;
} else {
if ((mont2 = BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(mont2, m2, ctx))
goto err;
}
ret = ossl_rsaz_mod_exp_avx512_x2(rr1->d, a1->d, p1->d, m1->d,
mont1->RR.d, mont1->n0[0],
rr2->d, a2->d, p2->d, m2->d,
mont2->RR.d, mont2->n0[0],
1024 /* factor bit size */);
rr1->top = 16;
rr1->neg = 0;
bn_correct_top(rr1);
bn_check_top(rr1);
rr2->top = 16;
rr2->neg = 0;
bn_correct_top(rr2);
bn_check_top(rr2);
goto err;
}
#endif
/* rr1 = a1^p1 mod m1 */
ret = BN_mod_exp_mont_consttime(rr1, a1, p1, m1, ctx, in_mont1);
/* rr2 = a2^p2 mod m2 */
ret &= BN_mod_exp_mont_consttime(rr2, a2, p2, m2, ctx, in_mont2);
#ifdef RSAZ_ENABLED
err:
if (in_mont2 == NULL)
BN_MONT_CTX_free(mont2);
if (in_mont1 == NULL)
BN_MONT_CTX_free(mont1);
#endif
return ret;
}
diff --git a/crypto/openssl/crypto/bn/bn_gf2m.c b/crypto/openssl/crypto/bn/bn_gf2m.c
index c811ae82d6b1..bcc66613cc14 100644
--- a/crypto/openssl/crypto/bn/bn_gf2m.c
+++ b/crypto/openssl/crypto/bn/bn_gf2m.c
@@ -1,1197 +1,1209 @@
/*
* Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <stdio.h>
#include "internal/cryptlib.h"
#include "bn_local.h"
#ifndef OPENSSL_NO_EC2M
+# include <openssl/ec.h>
/*
* Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should
* fail.
*/
# define MAX_ITERATIONS 50
# define SQR_nibble(w) ((((w) & 8) << 3) \
| (((w) & 4) << 2) \
| (((w) & 2) << 1) \
| ((w) & 1))
/* Platform-specific macros to accelerate squaring. */
# if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
# define SQR1(w) \
SQR_nibble((w) >> 60) << 56 | SQR_nibble((w) >> 56) << 48 | \
SQR_nibble((w) >> 52) << 40 | SQR_nibble((w) >> 48) << 32 | \
SQR_nibble((w) >> 44) << 24 | SQR_nibble((w) >> 40) << 16 | \
SQR_nibble((w) >> 36) << 8 | SQR_nibble((w) >> 32)
# define SQR0(w) \
SQR_nibble((w) >> 28) << 56 | SQR_nibble((w) >> 24) << 48 | \
SQR_nibble((w) >> 20) << 40 | SQR_nibble((w) >> 16) << 32 | \
SQR_nibble((w) >> 12) << 24 | SQR_nibble((w) >> 8) << 16 | \
SQR_nibble((w) >> 4) << 8 | SQR_nibble((w) )
# endif
# ifdef THIRTY_TWO_BIT
# define SQR1(w) \
SQR_nibble((w) >> 28) << 24 | SQR_nibble((w) >> 24) << 16 | \
SQR_nibble((w) >> 20) << 8 | SQR_nibble((w) >> 16)
# define SQR0(w) \
SQR_nibble((w) >> 12) << 24 | SQR_nibble((w) >> 8) << 16 | \
SQR_nibble((w) >> 4) << 8 | SQR_nibble((w) )
# endif
# if !defined(OPENSSL_BN_ASM_GF2m)
/*
* Product of two polynomials a, b each with degree < BN_BITS2 - 1, result is
* a polynomial r with degree < 2 * BN_BITS - 1 The caller MUST ensure that
* the variables have the right amount of space allocated.
*/
# ifdef THIRTY_TWO_BIT
static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a,
const BN_ULONG b)
{
register BN_ULONG h, l, s;
BN_ULONG tab[8], top2b = a >> 30;
register BN_ULONG a1, a2, a4;
a1 = a & (0x3FFFFFFF);
a2 = a1 << 1;
a4 = a2 << 1;
tab[0] = 0;
tab[1] = a1;
tab[2] = a2;
tab[3] = a1 ^ a2;
tab[4] = a4;
tab[5] = a1 ^ a4;
tab[6] = a2 ^ a4;
tab[7] = a1 ^ a2 ^ a4;
s = tab[b & 0x7];
l = s;
s = tab[b >> 3 & 0x7];
l ^= s << 3;
h = s >> 29;
s = tab[b >> 6 & 0x7];
l ^= s << 6;
h ^= s >> 26;
s = tab[b >> 9 & 0x7];
l ^= s << 9;
h ^= s >> 23;
s = tab[b >> 12 & 0x7];
l ^= s << 12;
h ^= s >> 20;
s = tab[b >> 15 & 0x7];
l ^= s << 15;
h ^= s >> 17;
s = tab[b >> 18 & 0x7];
l ^= s << 18;
h ^= s >> 14;
s = tab[b >> 21 & 0x7];
l ^= s << 21;
h ^= s >> 11;
s = tab[b >> 24 & 0x7];
l ^= s << 24;
h ^= s >> 8;
s = tab[b >> 27 & 0x7];
l ^= s << 27;
h ^= s >> 5;
s = tab[b >> 30];
l ^= s << 30;
h ^= s >> 2;
/* compensate for the top two bits of a */
if (top2b & 01) {
l ^= b << 30;
h ^= b >> 2;
}
if (top2b & 02) {
l ^= b << 31;
h ^= b >> 1;
}
*r1 = h;
*r0 = l;
}
# endif
# if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a,
const BN_ULONG b)
{
register BN_ULONG h, l, s;
BN_ULONG tab[16], top3b = a >> 61;
register BN_ULONG a1, a2, a4, a8;
a1 = a & (0x1FFFFFFFFFFFFFFFULL);
a2 = a1 << 1;
a4 = a2 << 1;
a8 = a4 << 1;
tab[0] = 0;
tab[1] = a1;
tab[2] = a2;
tab[3] = a1 ^ a2;
tab[4] = a4;
tab[5] = a1 ^ a4;
tab[6] = a2 ^ a4;
tab[7] = a1 ^ a2 ^ a4;
tab[8] = a8;
tab[9] = a1 ^ a8;
tab[10] = a2 ^ a8;
tab[11] = a1 ^ a2 ^ a8;
tab[12] = a4 ^ a8;
tab[13] = a1 ^ a4 ^ a8;
tab[14] = a2 ^ a4 ^ a8;
tab[15] = a1 ^ a2 ^ a4 ^ a8;
s = tab[b & 0xF];
l = s;
s = tab[b >> 4 & 0xF];
l ^= s << 4;
h = s >> 60;
s = tab[b >> 8 & 0xF];
l ^= s << 8;
h ^= s >> 56;
s = tab[b >> 12 & 0xF];
l ^= s << 12;
h ^= s >> 52;
s = tab[b >> 16 & 0xF];
l ^= s << 16;
h ^= s >> 48;
s = tab[b >> 20 & 0xF];
l ^= s << 20;
h ^= s >> 44;
s = tab[b >> 24 & 0xF];
l ^= s << 24;
h ^= s >> 40;
s = tab[b >> 28 & 0xF];
l ^= s << 28;
h ^= s >> 36;
s = tab[b >> 32 & 0xF];
l ^= s << 32;
h ^= s >> 32;
s = tab[b >> 36 & 0xF];
l ^= s << 36;
h ^= s >> 28;
s = tab[b >> 40 & 0xF];
l ^= s << 40;
h ^= s >> 24;
s = tab[b >> 44 & 0xF];
l ^= s << 44;
h ^= s >> 20;
s = tab[b >> 48 & 0xF];
l ^= s << 48;
h ^= s >> 16;
s = tab[b >> 52 & 0xF];
l ^= s << 52;
h ^= s >> 12;
s = tab[b >> 56 & 0xF];
l ^= s << 56;
h ^= s >> 8;
s = tab[b >> 60];
l ^= s << 60;
h ^= s >> 4;
/* compensate for the top three bits of a */
if (top3b & 01) {
l ^= b << 61;
h ^= b >> 3;
}
if (top3b & 02) {
l ^= b << 62;
h ^= b >> 2;
}
if (top3b & 04) {
l ^= b << 63;
h ^= b >> 1;
}
*r1 = h;
*r0 = l;
}
# endif
/*
* Product of two polynomials a, b each with degree < 2 * BN_BITS2 - 1,
* result is a polynomial r with degree < 4 * BN_BITS2 - 1 The caller MUST
* ensure that the variables have the right amount of space allocated.
*/
static void bn_GF2m_mul_2x2(BN_ULONG *r, const BN_ULONG a1, const BN_ULONG a0,
const BN_ULONG b1, const BN_ULONG b0)
{
BN_ULONG m1, m0;
/* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
bn_GF2m_mul_1x1(r + 3, r + 2, a1, b1);
bn_GF2m_mul_1x1(r + 1, r, a0, b0);
bn_GF2m_mul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
/* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */
r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */
}
# else
void bn_GF2m_mul_2x2(BN_ULONG *r, BN_ULONG a1, BN_ULONG a0, BN_ULONG b1,
BN_ULONG b0);
# endif
/*
* Add polynomials a and b and store result in r; r could be a or b, a and b
* could be equal; r is the bitwise XOR of a and b.
*/
int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
int i;
const BIGNUM *at, *bt;
bn_check_top(a);
bn_check_top(b);
if (a->top < b->top) {
at = b;
bt = a;
} else {
at = a;
bt = b;
}
if (bn_wexpand(r, at->top) == NULL)
return 0;
for (i = 0; i < bt->top; i++) {
r->d[i] = at->d[i] ^ bt->d[i];
}
for (; i < at->top; i++) {
r->d[i] = at->d[i];
}
r->top = at->top;
bn_correct_top(r);
return 1;
}
/*-
* Some functions allow for representation of the irreducible polynomials
* as an int[], say p. The irreducible f(t) is then of the form:
* t^p[0] + t^p[1] + ... + t^p[k]
* where m = p[0] > p[1] > ... > p[k] = 0.
*/
/* Performs modular reduction of a and store result in r. r could be a. */
int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[])
{
int j, k;
int n, dN, d0, d1;
BN_ULONG zz, *z;
bn_check_top(a);
if (p[0] == 0) {
/* reduction mod 1 => return 0 */
BN_zero(r);
return 1;
}
/*
* Since the algorithm does reduction in the r value, if a != r, copy the
* contents of a into r so we can do reduction in r.
*/
if (a != r) {
if (!bn_wexpand(r, a->top))
return 0;
for (j = 0; j < a->top; j++) {
r->d[j] = a->d[j];
}
r->top = a->top;
}
z = r->d;
/* start reduction */
dN = p[0] / BN_BITS2;
for (j = r->top - 1; j > dN;) {
zz = z[j];
if (z[j] == 0) {
j--;
continue;
}
z[j] = 0;
for (k = 1; p[k] != 0; k++) {
/* reducing component t^p[k] */
n = p[0] - p[k];
d0 = n % BN_BITS2;
d1 = BN_BITS2 - d0;
n /= BN_BITS2;
z[j - n] ^= (zz >> d0);
if (d0)
z[j - n - 1] ^= (zz << d1);
}
/* reducing component t^0 */
n = dN;
d0 = p[0] % BN_BITS2;
d1 = BN_BITS2 - d0;
z[j - n] ^= (zz >> d0);
if (d0)
z[j - n - 1] ^= (zz << d1);
}
/* final round of reduction */
while (j == dN) {
d0 = p[0] % BN_BITS2;
zz = z[dN] >> d0;
if (zz == 0)
break;
d1 = BN_BITS2 - d0;
/* clear up the top d1 bits */
if (d0)
z[dN] = (z[dN] << d1) >> d1;
else
z[dN] = 0;
z[0] ^= zz; /* reduction t^0 component */
for (k = 1; p[k] != 0; k++) {
BN_ULONG tmp_ulong;
/* reducing component t^p[k] */
n = p[k] / BN_BITS2;
d0 = p[k] % BN_BITS2;
d1 = BN_BITS2 - d0;
z[n] ^= (zz << d0);
if (d0 && (tmp_ulong = zz >> d1))
z[n + 1] ^= tmp_ulong;
}
}
bn_correct_top(r);
return 1;
}
/*
* Performs modular reduction of a by p and store result in r. r could be a.
* This function calls down to the BN_GF2m_mod_arr implementation; this wrapper
* function is only provided for convenience; for best performance, use the
* BN_GF2m_mod_arr function.
*/
int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p)
{
int ret = 0;
int arr[6];
bn_check_top(a);
bn_check_top(p);
ret = BN_GF2m_poly2arr(p, arr, OSSL_NELEM(arr));
if (!ret || ret > (int)OSSL_NELEM(arr)) {
ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
return 0;
}
ret = BN_GF2m_mod_arr(r, a, arr);
bn_check_top(r);
return ret;
}
/*
* Compute the product of two polynomials a and b, reduce modulo p, and store
* the result in r. r could be a or b; a could be b.
*/
int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const int p[], BN_CTX *ctx)
{
int zlen, i, j, k, ret = 0;
BIGNUM *s;
BN_ULONG x1, x0, y1, y0, zz[4];
bn_check_top(a);
bn_check_top(b);
if (a == b) {
return BN_GF2m_mod_sqr_arr(r, a, p, ctx);
}
BN_CTX_start(ctx);
if ((s = BN_CTX_get(ctx)) == NULL)
goto err;
zlen = a->top + b->top + 4;
if (!bn_wexpand(s, zlen))
goto err;
s->top = zlen;
for (i = 0; i < zlen; i++)
s->d[i] = 0;
for (j = 0; j < b->top; j += 2) {
y0 = b->d[j];
y1 = ((j + 1) == b->top) ? 0 : b->d[j + 1];
for (i = 0; i < a->top; i += 2) {
x0 = a->d[i];
x1 = ((i + 1) == a->top) ? 0 : a->d[i + 1];
bn_GF2m_mul_2x2(zz, x1, x0, y1, y0);
for (k = 0; k < 4; k++)
s->d[i + j + k] ^= zz[k];
}
}
bn_correct_top(s);
if (BN_GF2m_mod_arr(r, s, p))
ret = 1;
bn_check_top(r);
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Compute the product of two polynomials a and b, reduce modulo p, and store
* the result in r. r could be a or b; a could equal b. This function calls
* down to the BN_GF2m_mod_mul_arr implementation; this wrapper function is
* only provided for convenience; for best performance, use the
* BN_GF2m_mod_mul_arr function.
*/
int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
int *arr;
bn_check_top(a);
bn_check_top(b);
bn_check_top(p);
arr = OPENSSL_malloc(sizeof(*arr) * max);
if (arr == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return 0;
}
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx);
bn_check_top(r);
err:
OPENSSL_free(arr);
return ret;
}
/* Square a, reduce the result mod p, and store it in a. r could be a. */
int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[],
BN_CTX *ctx)
{
int i, ret = 0;
BIGNUM *s;
bn_check_top(a);
BN_CTX_start(ctx);
if ((s = BN_CTX_get(ctx)) == NULL)
goto err;
if (!bn_wexpand(s, 2 * a->top))
goto err;
for (i = a->top - 1; i >= 0; i--) {
s->d[2 * i + 1] = SQR1(a->d[i]);
s->d[2 * i] = SQR0(a->d[i]);
}
s->top = 2 * a->top;
bn_correct_top(s);
if (!BN_GF2m_mod_arr(r, s, p))
goto err;
bn_check_top(r);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Square a, reduce the result mod p, and store it in a. r could be a. This
* function calls down to the BN_GF2m_mod_sqr_arr implementation; this
* wrapper function is only provided for convenience; for best performance,
* use the BN_GF2m_mod_sqr_arr function.
*/
int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
int *arr;
bn_check_top(a);
bn_check_top(p);
arr = OPENSSL_malloc(sizeof(*arr) * max);
if (arr == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return 0;
}
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx);
bn_check_top(r);
err:
OPENSSL_free(arr);
return ret;
}
/*
* Invert a, reduce modulo p, and store the result in r. r could be a. Uses
* Modified Almost Inverse Algorithm (Algorithm 10) from Hankerson, D.,
* Hernandez, J.L., and Menezes, A. "Software Implementation of Elliptic
* Curve Cryptography Over Binary Fields".
*/
static int BN_GF2m_mod_inv_vartime(BIGNUM *r, const BIGNUM *a,
const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *b, *c = NULL, *u = NULL, *v = NULL, *tmp;
int ret = 0;
bn_check_top(a);
bn_check_top(p);
BN_CTX_start(ctx);
b = BN_CTX_get(ctx);
c = BN_CTX_get(ctx);
u = BN_CTX_get(ctx);
v = BN_CTX_get(ctx);
if (v == NULL)
goto err;
if (!BN_GF2m_mod(u, a, p))
goto err;
if (BN_is_zero(u))
goto err;
if (!BN_copy(v, p))
goto err;
# if 0
if (!BN_one(b))
goto err;
while (1) {
while (!BN_is_odd(u)) {
if (BN_is_zero(u))
goto err;
if (!BN_rshift1(u, u))
goto err;
if (BN_is_odd(b)) {
if (!BN_GF2m_add(b, b, p))
goto err;
}
if (!BN_rshift1(b, b))
goto err;
}
if (BN_abs_is_word(u, 1))
break;
if (BN_num_bits(u) < BN_num_bits(v)) {
tmp = u;
u = v;
v = tmp;
tmp = b;
b = c;
c = tmp;
}
if (!BN_GF2m_add(u, u, v))
goto err;
if (!BN_GF2m_add(b, b, c))
goto err;
}
# else
{
int i;
int ubits = BN_num_bits(u);
int vbits = BN_num_bits(v); /* v is copy of p */
int top = p->top;
BN_ULONG *udp, *bdp, *vdp, *cdp;
if (!bn_wexpand(u, top))
goto err;
udp = u->d;
for (i = u->top; i < top; i++)
udp[i] = 0;
u->top = top;
if (!bn_wexpand(b, top))
goto err;
bdp = b->d;
bdp[0] = 1;
for (i = 1; i < top; i++)
bdp[i] = 0;
b->top = top;
if (!bn_wexpand(c, top))
goto err;
cdp = c->d;
for (i = 0; i < top; i++)
cdp[i] = 0;
c->top = top;
vdp = v->d; /* It pays off to "cache" *->d pointers,
* because it allows optimizer to be more
* aggressive. But we don't have to "cache"
* p->d, because *p is declared 'const'... */
while (1) {
while (ubits && !(udp[0] & 1)) {
BN_ULONG u0, u1, b0, b1, mask;
u0 = udp[0];
b0 = bdp[0];
mask = (BN_ULONG)0 - (b0 & 1);
b0 ^= p->d[0] & mask;
for (i = 0; i < top - 1; i++) {
u1 = udp[i + 1];
udp[i] = ((u0 >> 1) | (u1 << (BN_BITS2 - 1))) & BN_MASK2;
u0 = u1;
b1 = bdp[i + 1] ^ (p->d[i + 1] & mask);
bdp[i] = ((b0 >> 1) | (b1 << (BN_BITS2 - 1))) & BN_MASK2;
b0 = b1;
}
udp[i] = u0 >> 1;
bdp[i] = b0 >> 1;
ubits--;
}
if (ubits <= BN_BITS2) {
if (udp[0] == 0) /* poly was reducible */
goto err;
if (udp[0] == 1)
break;
}
if (ubits < vbits) {
i = ubits;
ubits = vbits;
vbits = i;
tmp = u;
u = v;
v = tmp;
tmp = b;
b = c;
c = tmp;
udp = vdp;
vdp = v->d;
bdp = cdp;
cdp = c->d;
}
for (i = 0; i < top; i++) {
udp[i] ^= vdp[i];
bdp[i] ^= cdp[i];
}
if (ubits == vbits) {
BN_ULONG ul;
int utop = (ubits - 1) / BN_BITS2;
while ((ul = udp[utop]) == 0 && utop)
utop--;
ubits = utop * BN_BITS2 + BN_num_bits_word(ul);
}
}
bn_correct_top(b);
}
# endif
if (!BN_copy(r, b))
goto err;
bn_check_top(r);
ret = 1;
err:
# ifdef BN_DEBUG
/* BN_CTX_end would complain about the expanded form */
bn_correct_top(c);
bn_correct_top(u);
bn_correct_top(v);
# endif
BN_CTX_end(ctx);
return ret;
}
/*-
* Wrapper for BN_GF2m_mod_inv_vartime that blinds the input before calling.
* This is not constant time.
* But it does eliminate first order deduction on the input.
*/
int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *b = NULL;
int ret = 0;
int numbits;
BN_CTX_start(ctx);
if ((b = BN_CTX_get(ctx)) == NULL)
goto err;
/* Fail on a non-sensical input p value */
numbits = BN_num_bits(p);
if (numbits <= 1)
goto err;
/* generate blinding value */
do {
if (!BN_priv_rand_ex(b, numbits - 1,
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx))
goto err;
} while (BN_is_zero(b));
/* r := a * b */
if (!BN_GF2m_mod_mul(r, a, b, p, ctx))
goto err;
/* r := 1/(a * b) */
if (!BN_GF2m_mod_inv_vartime(r, r, p, ctx))
goto err;
/* r := b/(a * b) = 1/a */
if (!BN_GF2m_mod_mul(r, r, b, p, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Invert xx, reduce modulo p, and store the result in r. r could be xx.
* This function calls down to the BN_GF2m_mod_inv implementation; this
* wrapper function is only provided for convenience; for best performance,
* use the BN_GF2m_mod_inv function.
*/
int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *xx, const int p[],
BN_CTX *ctx)
{
BIGNUM *field;
int ret = 0;
bn_check_top(xx);
BN_CTX_start(ctx);
if ((field = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_GF2m_arr2poly(p, field))
goto err;
ret = BN_GF2m_mod_inv(r, xx, field, ctx);
bn_check_top(r);
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Divide y by x, reduce modulo p, and store the result in r. r could be x
* or y, x could equal y.
*/
int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x,
const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *xinv = NULL;
int ret = 0;
bn_check_top(y);
bn_check_top(x);
bn_check_top(p);
BN_CTX_start(ctx);
xinv = BN_CTX_get(ctx);
if (xinv == NULL)
goto err;
if (!BN_GF2m_mod_inv(xinv, x, p, ctx))
goto err;
if (!BN_GF2m_mod_mul(r, y, xinv, p, ctx))
goto err;
bn_check_top(r);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Divide yy by xx, reduce modulo p, and store the result in r. r could be xx
* * or yy, xx could equal yy. This function calls down to the
* BN_GF2m_mod_div implementation; this wrapper function is only provided for
* convenience; for best performance, use the BN_GF2m_mod_div function.
*/
int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx,
const int p[], BN_CTX *ctx)
{
BIGNUM *field;
int ret = 0;
bn_check_top(yy);
bn_check_top(xx);
BN_CTX_start(ctx);
if ((field = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_GF2m_arr2poly(p, field))
goto err;
ret = BN_GF2m_mod_div(r, yy, xx, field, ctx);
bn_check_top(r);
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Compute the bth power of a, reduce modulo p, and store the result in r. r
* could be a. Uses simple square-and-multiply algorithm A.5.1 from IEEE
* P1363.
*/
int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const int p[], BN_CTX *ctx)
{
int ret = 0, i, n;
BIGNUM *u;
bn_check_top(a);
bn_check_top(b);
if (BN_is_zero(b))
return BN_one(r);
if (BN_abs_is_word(b, 1))
return (BN_copy(r, a) != NULL);
BN_CTX_start(ctx);
if ((u = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_GF2m_mod_arr(u, a, p))
goto err;
n = BN_num_bits(b) - 1;
for (i = n - 1; i >= 0; i--) {
if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx))
goto err;
if (BN_is_bit_set(b, i)) {
if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx))
goto err;
}
}
if (!BN_copy(r, u))
goto err;
bn_check_top(r);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Compute the bth power of a, reduce modulo p, and store the result in r. r
* could be a. This function calls down to the BN_GF2m_mod_exp_arr
* implementation; this wrapper function is only provided for convenience;
* for best performance, use the BN_GF2m_mod_exp_arr function.
*/
int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
int *arr;
bn_check_top(a);
bn_check_top(b);
bn_check_top(p);
arr = OPENSSL_malloc(sizeof(*arr) * max);
if (arr == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return 0;
}
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx);
bn_check_top(r);
err:
OPENSSL_free(arr);
return ret;
}
/*
* Compute the square root of a, reduce modulo p, and store the result in r.
* r could be a. Uses exponentiation as in algorithm A.4.1 from IEEE P1363.
*/
int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[],
BN_CTX *ctx)
{
int ret = 0;
BIGNUM *u;
bn_check_top(a);
if (p[0] == 0) {
/* reduction mod 1 => return 0 */
BN_zero(r);
return 1;
}
BN_CTX_start(ctx);
if ((u = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_set_bit(u, p[0] - 1))
goto err;
ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx);
bn_check_top(r);
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Compute the square root of a, reduce modulo p, and store the result in r.
* r could be a. This function calls down to the BN_GF2m_mod_sqrt_arr
* implementation; this wrapper function is only provided for convenience;
* for best performance, use the BN_GF2m_mod_sqrt_arr function.
*/
int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
int *arr;
bn_check_top(a);
bn_check_top(p);
arr = OPENSSL_malloc(sizeof(*arr) * max);
if (arr == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return 0;
}
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx);
bn_check_top(r);
err:
OPENSSL_free(arr);
return ret;
}
/*
* Find r such that r^2 + r = a mod p. r could be a. If no r exists returns
* 0. Uses algorithms A.4.7 and A.4.6 from IEEE P1363.
*/
int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[],
BN_CTX *ctx)
{
int ret = 0, count = 0, j;
BIGNUM *a, *z, *rho, *w, *w2, *tmp;
bn_check_top(a_);
if (p[0] == 0) {
/* reduction mod 1 => return 0 */
BN_zero(r);
return 1;
}
BN_CTX_start(ctx);
a = BN_CTX_get(ctx);
z = BN_CTX_get(ctx);
w = BN_CTX_get(ctx);
if (w == NULL)
goto err;
if (!BN_GF2m_mod_arr(a, a_, p))
goto err;
if (BN_is_zero(a)) {
BN_zero(r);
ret = 1;
goto err;
}
if (p[0] & 0x1) { /* m is odd */
/* compute half-trace of a */
if (!BN_copy(z, a))
goto err;
for (j = 1; j <= (p[0] - 1) / 2; j++) {
if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx))
goto err;
if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx))
goto err;
if (!BN_GF2m_add(z, z, a))
goto err;
}
} else { /* m is even */
rho = BN_CTX_get(ctx);
w2 = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL)
goto err;
do {
if (!BN_priv_rand_ex(rho, p[0], BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY,
0, ctx))
goto err;
if (!BN_GF2m_mod_arr(rho, rho, p))
goto err;
BN_zero(z);
if (!BN_copy(w, rho))
goto err;
for (j = 1; j <= p[0] - 1; j++) {
if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx))
goto err;
if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx))
goto err;
if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx))
goto err;
if (!BN_GF2m_add(z, z, tmp))
goto err;
if (!BN_GF2m_add(w, w2, rho))
goto err;
}
count++;
} while (BN_is_zero(w) && (count < MAX_ITERATIONS));
if (BN_is_zero(w)) {
ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
goto err;
}
}
if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx))
goto err;
if (!BN_GF2m_add(w, z, w))
goto err;
if (BN_GF2m_cmp(w, a)) {
ERR_raise(ERR_LIB_BN, BN_R_NO_SOLUTION);
goto err;
}
if (!BN_copy(r, z))
goto err;
bn_check_top(r);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Find r such that r^2 + r = a mod p. r could be a. If no r exists returns
* 0. This function calls down to the BN_GF2m_mod_solve_quad_arr
* implementation; this wrapper function is only provided for convenience;
* for best performance, use the BN_GF2m_mod_solve_quad_arr function.
*/
int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx)
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
int *arr;
bn_check_top(a);
bn_check_top(p);
arr = OPENSSL_malloc(sizeof(*arr) * max);
if (arr == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
goto err;
}
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx);
bn_check_top(r);
err:
OPENSSL_free(arr);
return ret;
}
/*
* Convert the bit-string representation of a polynomial ( \sum_{i=0}^n a_i *
* x^i) into an array of integers corresponding to the bits with non-zero
- * coefficient. Array is terminated with -1. Up to max elements of the array
- * will be filled. Return value is total number of array elements that would
- * be filled if array was large enough.
+ * coefficient. The array is intended to be suitable for use with
+ * `BN_GF2m_mod_arr()`, and so the constant term of the polynomial must not be
+ * zero. This translates to a requirement that the input BIGNUM `a` is odd.
+ *
+ * Given sufficient room, the array is terminated with -1. Up to max elements
+ * of the array will be filled.
+ *
+ * The return value is total number of array elements that would be filled if
+ * array was large enough, including the terminating `-1`. It is `0` when `a`
+ * is not odd or the constant term is zero contrary to requirement.
+ *
+ * The return value is also `0` when the leading exponent exceeds
+ * `OPENSSL_ECC_MAX_FIELD_BITS`, this guards against CPU exhaustion attacks,
*/
int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
{
int i, j, k = 0;
BN_ULONG mask;
- if (BN_is_zero(a))
+ if (!BN_is_odd(a))
return 0;
for (i = a->top - 1; i >= 0; i--) {
if (!a->d[i])
/* skip word if a->d[i] == 0 */
continue;
mask = BN_TBIT;
for (j = BN_BITS2 - 1; j >= 0; j--) {
if (a->d[i] & mask) {
if (k < max)
p[k] = BN_BITS2 * i + j;
k++;
}
mask >>= 1;
}
}
- if (k < max) {
+ if (k > 0 && p[0] > OPENSSL_ECC_MAX_FIELD_BITS)
+ return 0;
+
+ if (k < max)
p[k] = -1;
- k++;
- }
- return k;
+ return k + 1;
}
/*
* Convert the coefficient array representation of a polynomial to a
* bit-string. The array must be terminated by -1.
*/
int BN_GF2m_arr2poly(const int p[], BIGNUM *a)
{
int i;
bn_check_top(a);
BN_zero(a);
for (i = 0; p[i] != -1; i++) {
if (BN_set_bit(a, p[i]) == 0)
return 0;
}
bn_check_top(a);
return 1;
}
#endif
diff --git a/crypto/openssl/crypto/bn/rsaz_exp_x2.c b/crypto/openssl/crypto/bn/rsaz_exp_x2.c
index b19050dfee8c..4a2a6752f672 100644
--- a/crypto/openssl/crypto/bn/rsaz_exp_x2.c
+++ b/crypto/openssl/crypto/bn/rsaz_exp_x2.c
@@ -1,575 +1,571 @@
/*
- * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2020, Intel Corporation. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
*
* Originally written by Ilya Albrekht, Sergey Kirillov and Andrey Matyukov
* Intel Corporation
*
*/
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
#include "rsaz_exp.h"
#ifndef RSAZ_ENABLED
NON_EMPTY_TRANSLATION_UNIT
#else
# include <assert.h>
# include <string.h>
# if defined(__GNUC__)
# define ALIGN64 __attribute__((aligned(64)))
# elif defined(_MSC_VER)
# define ALIGN64 __declspec(align(64))
# else
# define ALIGN64
# endif
# define ALIGN_OF(ptr, boundary) \
((unsigned char *)(ptr) + (boundary - (((size_t)(ptr)) & (boundary - 1))))
/* Internal radix */
# define DIGIT_SIZE (52)
/* 52-bit mask */
# define DIGIT_MASK ((uint64_t)0xFFFFFFFFFFFFF)
# define BITS2WORD8_SIZE(x) (((x) + 7) >> 3)
# define BITS2WORD64_SIZE(x) (((x) + 63) >> 6)
static ossl_inline uint64_t get_digit52(const uint8_t *in, int in_len);
static ossl_inline void put_digit52(uint8_t *out, int out_len, uint64_t digit);
static void to_words52(BN_ULONG *out, int out_len, const BN_ULONG *in,
int in_bitsize);
static void from_words52(BN_ULONG *bn_out, int out_bitsize, const BN_ULONG *in);
static ossl_inline void set_bit(BN_ULONG *a, int idx);
/* Number of |digit_size|-bit digits in |bitsize|-bit value */
static ossl_inline int number_of_digits(int bitsize, int digit_size)
{
return (bitsize + digit_size - 1) / digit_size;
}
typedef void (*AMM52)(BN_ULONG *res, const BN_ULONG *base,
const BN_ULONG *exp, const BN_ULONG *m, BN_ULONG k0);
typedef void (*EXP52_x2)(BN_ULONG *res, const BN_ULONG *base,
const BN_ULONG *exp[2], const BN_ULONG *m,
const BN_ULONG *rr, const BN_ULONG k0[2]);
/*
* For details of the methods declared below please refer to
* crypto/bn/asm/rsaz-avx512.pl
*
* Naming notes:
* amm = Almost Montgomery Multiplication
* ams = Almost Montgomery Squaring
* 52x20 - data represented as array of 20 digits in 52-bit radix
* _x1_/_x2_ - 1 or 2 independent inputs/outputs
* _256 suffix - uses 256-bit (AVX512VL) registers
*/
/*AMM = Almost Montgomery Multiplication. */
void ossl_rsaz_amm52x20_x1_256(BN_ULONG *res, const BN_ULONG *base,
const BN_ULONG *exp, const BN_ULONG *m,
BN_ULONG k0);
static void RSAZ_exp52x20_x2_256(BN_ULONG *res, const BN_ULONG *base,
const BN_ULONG *exp[2], const BN_ULONG *m,
const BN_ULONG *rr, const BN_ULONG k0[2]);
void ossl_rsaz_amm52x20_x2_256(BN_ULONG *out, const BN_ULONG *a,
const BN_ULONG *b, const BN_ULONG *m,
const BN_ULONG k0[2]);
void ossl_extract_multiplier_2x20_win5(BN_ULONG *red_Y,
const BN_ULONG *red_table,
int red_table_idx, int tbl_idx);
/*
* Dual Montgomery modular exponentiation using prime moduli of the
* same bit size, optimized with AVX512 ISA.
*
* Input and output parameters for each exponentiation are independent and
* denoted here by index |i|, i = 1..2.
*
* Input and output are all in regular 2^64 radix.
*
* Each moduli shall be |factor_size| bit size.
*
* NOTE: currently only 2x1024 case is supported.
*
* [out] res|i| - result of modular exponentiation: array of qword values
* in regular (2^64) radix. Size of array shall be enough
* to hold |factor_size| bits.
* [in] base|i| - base
* [in] exp|i| - exponent
* [in] m|i| - moduli
* [in] rr|i| - Montgomery parameter RR = R^2 mod m|i|
* [in] k0_|i| - Montgomery parameter k0 = -1/m|i| mod 2^64
* [in] factor_size - moduli bit size
*
* \return 0 in case of failure,
* 1 in case of success.
*/
int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1,
const BN_ULONG *base1,
const BN_ULONG *exp1,
const BN_ULONG *m1,
const BN_ULONG *rr1,
BN_ULONG k0_1,
BN_ULONG *res2,
const BN_ULONG *base2,
const BN_ULONG *exp2,
const BN_ULONG *m2,
const BN_ULONG *rr2,
BN_ULONG k0_2,
int factor_size)
{
int ret = 0;
/*
* Number of word-size (BN_ULONG) digits to store exponent in redundant
* representation.
*/
int exp_digits = number_of_digits(factor_size + 2, DIGIT_SIZE);
int coeff_pow = 4 * (DIGIT_SIZE * exp_digits - factor_size);
BN_ULONG *base1_red, *m1_red, *rr1_red;
BN_ULONG *base2_red, *m2_red, *rr2_red;
BN_ULONG *coeff_red;
BN_ULONG *storage = NULL;
BN_ULONG *storage_aligned = NULL;
BN_ULONG storage_len_bytes = 7 * exp_digits * sizeof(BN_ULONG);
/* AMM = Almost Montgomery Multiplication */
AMM52 amm = NULL;
/* Dual (2-exps in parallel) exponentiation */
EXP52_x2 exp_x2 = NULL;
const BN_ULONG *exp[2] = {0};
BN_ULONG k0[2] = {0};
/* Only 1024-bit factor size is supported now */
switch (factor_size) {
case 1024:
amm = ossl_rsaz_amm52x20_x1_256;
exp_x2 = RSAZ_exp52x20_x2_256;
break;
default:
goto err;
}
storage = (BN_ULONG *)OPENSSL_malloc(storage_len_bytes + 64);
if (storage == NULL)
goto err;
storage_aligned = (BN_ULONG *)ALIGN_OF(storage, 64);
/* Memory layout for red(undant) representations */
base1_red = storage_aligned;
base2_red = storage_aligned + 1 * exp_digits;
m1_red = storage_aligned + 2 * exp_digits;
m2_red = storage_aligned + 3 * exp_digits;
rr1_red = storage_aligned + 4 * exp_digits;
rr2_red = storage_aligned + 5 * exp_digits;
coeff_red = storage_aligned + 6 * exp_digits;
/* Convert base_i, m_i, rr_i, from regular to 52-bit radix */
to_words52(base1_red, exp_digits, base1, factor_size);
to_words52(base2_red, exp_digits, base2, factor_size);
to_words52(m1_red, exp_digits, m1, factor_size);
to_words52(m2_red, exp_digits, m2, factor_size);
to_words52(rr1_red, exp_digits, rr1, factor_size);
to_words52(rr2_red, exp_digits, rr2, factor_size);
/*
* Compute target domain Montgomery converters RR' for each modulus
* based on precomputed original domain's RR.
*
* RR -> RR' transformation steps:
* (1) coeff = 2^k
* (2) t = AMM(RR,RR) = RR^2 / R' mod m
* (3) RR' = AMM(t, coeff) = RR^2 * 2^k / R'^2 mod m
* where
* k = 4 * (52 * digits52 - modlen)
* R = 2^(64 * ceil(modlen/64)) mod m
* RR = R^2 mod M
* R' = 2^(52 * ceil(modlen/52)) mod m
*
* modlen = 1024: k = 64, RR = 2^2048 mod m, RR' = 2^2080 mod m
*/
memset(coeff_red, 0, exp_digits * sizeof(BN_ULONG));
/* (1) in reduced domain representation */
set_bit(coeff_red, 64 * (int)(coeff_pow / 52) + coeff_pow % 52);
amm(rr1_red, rr1_red, rr1_red, m1_red, k0_1); /* (2) for m1 */
amm(rr1_red, rr1_red, coeff_red, m1_red, k0_1); /* (3) for m1 */
amm(rr2_red, rr2_red, rr2_red, m2_red, k0_2); /* (2) for m2 */
amm(rr2_red, rr2_red, coeff_red, m2_red, k0_2); /* (3) for m2 */
exp[0] = exp1;
exp[1] = exp2;
k0[0] = k0_1;
k0[1] = k0_2;
exp_x2(rr1_red, base1_red, exp, m1_red, rr1_red, k0);
/* Convert rr_i back to regular radix */
from_words52(res1, factor_size, rr1_red);
from_words52(res2, factor_size, rr2_red);
/* bn_reduce_once_in_place expects number of BN_ULONG, not bit size */
factor_size /= sizeof(BN_ULONG) * 8;
bn_reduce_once_in_place(res1, /*carry=*/0, m1, storage, factor_size);
bn_reduce_once_in_place(res2, /*carry=*/0, m2, storage, factor_size);
ret = 1;
err:
if (storage != NULL) {
OPENSSL_cleanse(storage, storage_len_bytes);
OPENSSL_free(storage);
}
return ret;
}
/*
* Dual 1024-bit w-ary modular exponentiation using prime moduli of the same
* bit size using Almost Montgomery Multiplication, optimized with AVX512_IFMA
* ISA.
*
* The parameter w (window size) = 5.
*
* [out] res - result of modular exponentiation: 2x20 qword
* values in 2^52 radix.
* [in] base - base (2x20 qword values in 2^52 radix)
* [in] exp - array of 2 pointers to 16 qword values in 2^64 radix.
* Exponent is not converted to redundant representation.
* [in] m - moduli (2x20 qword values in 2^52 radix)
* [in] rr - Montgomery parameter for 2 moduli: RR = 2^2080 mod m.
* (2x20 qword values in 2^52 radix)
* [in] k0 - Montgomery parameter for 2 moduli: k0 = -1/m mod 2^64
*
* \return (void).
*/
static void RSAZ_exp52x20_x2_256(BN_ULONG *out, /* [2][20] */
const BN_ULONG *base, /* [2][20] */
const BN_ULONG *exp[2], /* 2x16 */
const BN_ULONG *m, /* [2][20] */
const BN_ULONG *rr, /* [2][20] */
const BN_ULONG k0[2])
{
# define BITSIZE_MODULUS (1024)
# define EXP_WIN_SIZE (5)
# define EXP_WIN_MASK ((1U << EXP_WIN_SIZE) - 1)
/*
* Number of digits (64-bit words) in redundant representation to handle
* modulus bits
*/
# define RED_DIGITS (20)
# define EXP_DIGITS (16)
# define DAMM ossl_rsaz_amm52x20_x2_256
/*
* Squaring is done using multiplication now. That can be a subject of
* optimization in future.
*/
# define DAMS(r,a,m,k0) \
ossl_rsaz_amm52x20_x2_256((r),(a),(a),(m),(k0))
/* Allocate stack for red(undant) result Y and multiplier X */
ALIGN64 BN_ULONG red_Y[2][RED_DIGITS];
ALIGN64 BN_ULONG red_X[2][RED_DIGITS];
/* Allocate expanded exponent */
ALIGN64 BN_ULONG expz[2][EXP_DIGITS + 1];
/* Pre-computed table of base powers */
ALIGN64 BN_ULONG red_table[1U << EXP_WIN_SIZE][2][RED_DIGITS];
int idx;
memset(red_Y, 0, sizeof(red_Y));
memset(red_table, 0, sizeof(red_table));
memset(red_X, 0, sizeof(red_X));
/*
* Compute table of powers base^i, i = 0, ..., (2^EXP_WIN_SIZE) - 1
* table[0] = mont(x^0) = mont(1)
* table[1] = mont(x^1) = mont(x)
*/
red_X[0][0] = 1;
red_X[1][0] = 1;
DAMM(red_table[0][0], (const BN_ULONG*)red_X, rr, m, k0);
DAMM(red_table[1][0], base, rr, m, k0);
for (idx = 1; idx < (int)((1U << EXP_WIN_SIZE) / 2); idx++) {
DAMS(red_table[2 * idx + 0][0], red_table[1 * idx][0], m, k0);
DAMM(red_table[2 * idx + 1][0], red_table[2 * idx][0], red_table[1][0], m, k0);
}
/* Copy and expand exponents */
memcpy(expz[0], exp[0], EXP_DIGITS * sizeof(BN_ULONG));
expz[0][EXP_DIGITS] = 0;
memcpy(expz[1], exp[1], EXP_DIGITS * sizeof(BN_ULONG));
expz[1][EXP_DIGITS] = 0;
/* Exponentiation */
{
const int rem = BITSIZE_MODULUS % EXP_WIN_SIZE;
BN_ULONG table_idx_mask = EXP_WIN_MASK;
int exp_bit_no = BITSIZE_MODULUS - rem;
int exp_chunk_no = exp_bit_no / 64;
int exp_chunk_shift = exp_bit_no % 64;
BN_ULONG red_table_idx_0, red_table_idx_1;
/*
* If rem == 0, then
* exp_bit_no = modulus_bitsize - exp_win_size
* However, this isn't possible because rem is { 1024, 1536, 2048 } % 5
* which is { 4, 1, 3 } respectively.
*
* If this assertion ever fails the fix above is easy.
*/
OPENSSL_assert(rem != 0);
/* Process 1-st exp window - just init result */
red_table_idx_0 = expz[0][exp_chunk_no];
red_table_idx_1 = expz[1][exp_chunk_no];
/*
* The function operates with fixed moduli sizes divisible by 64,
* thus table index here is always in supported range [0, EXP_WIN_SIZE).
*/
red_table_idx_0 >>= exp_chunk_shift;
red_table_idx_1 >>= exp_chunk_shift;
ossl_extract_multiplier_2x20_win5(red_Y[0], (const BN_ULONG*)red_table,
(int)red_table_idx_0, 0);
ossl_extract_multiplier_2x20_win5(red_Y[1], (const BN_ULONG*)red_table,
(int)red_table_idx_1, 1);
/* Process other exp windows */
for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) {
/* Extract pre-computed multiplier from the table */
{
BN_ULONG T;
exp_chunk_no = exp_bit_no / 64;
exp_chunk_shift = exp_bit_no % 64;
{
red_table_idx_0 = expz[0][exp_chunk_no];
T = expz[0][exp_chunk_no + 1];
red_table_idx_0 >>= exp_chunk_shift;
/*
* Get additional bits from then next quadword
* when 64-bit boundaries are crossed.
*/
if (exp_chunk_shift > 64 - EXP_WIN_SIZE) {
T <<= (64 - exp_chunk_shift);
red_table_idx_0 ^= T;
}
red_table_idx_0 &= table_idx_mask;
ossl_extract_multiplier_2x20_win5(red_X[0],
(const BN_ULONG*)red_table,
(int)red_table_idx_0, 0);
}
{
red_table_idx_1 = expz[1][exp_chunk_no];
T = expz[1][exp_chunk_no + 1];
red_table_idx_1 >>= exp_chunk_shift;
/*
* Get additional bits from then next quadword
* when 64-bit boundaries are crossed.
*/
if (exp_chunk_shift > 64 - EXP_WIN_SIZE) {
T <<= (64 - exp_chunk_shift);
red_table_idx_1 ^= T;
}
red_table_idx_1 &= table_idx_mask;
ossl_extract_multiplier_2x20_win5(red_X[1],
(const BN_ULONG*)red_table,
(int)red_table_idx_1, 1);
}
}
/* Series of squaring */
DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
DAMM((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, (const BN_ULONG*)red_X, m, k0);
}
}
/*
*
* NB: After the last AMM of exponentiation in Montgomery domain, the result
* may be 1025-bit, but the conversion out of Montgomery domain performs an
* AMM(x,1) which guarantees that the final result is less than |m|, so no
* conditional subtraction is needed here. See "Efficient Software
* Implementations of Modular Exponentiation" (by Shay Gueron) paper for details.
*/
/* Convert result back in regular 2^52 domain */
memset(red_X, 0, sizeof(red_X));
red_X[0][0] = 1;
red_X[1][0] = 1;
DAMM(out, (const BN_ULONG*)red_Y, (const BN_ULONG*)red_X, m, k0);
/* Clear exponents */
OPENSSL_cleanse(expz, sizeof(expz));
OPENSSL_cleanse(red_Y, sizeof(red_Y));
# undef DAMS
# undef DAMM
# undef EXP_DIGITS
# undef RED_DIGITS
# undef EXP_WIN_MASK
# undef EXP_WIN_SIZE
# undef BITSIZE_MODULUS
}
static ossl_inline uint64_t get_digit52(const uint8_t *in, int in_len)
{
uint64_t digit = 0;
assert(in != NULL);
for (; in_len > 0; in_len--) {
digit <<= 8;
digit += (uint64_t)(in[in_len - 1]);
}
return digit;
}
/*
* Convert array of words in regular (base=2^64) representation to array of
* words in redundant (base=2^52) one.
*/
static void to_words52(BN_ULONG *out, int out_len,
const BN_ULONG *in, int in_bitsize)
{
uint8_t *in_str = NULL;
assert(out != NULL);
assert(in != NULL);
/* Check destination buffer capacity */
assert(out_len >= number_of_digits(in_bitsize, DIGIT_SIZE));
in_str = (uint8_t *)in;
for (; in_bitsize >= (2 * DIGIT_SIZE); in_bitsize -= (2 * DIGIT_SIZE), out += 2) {
uint64_t digit;
memcpy(&digit, in_str, sizeof(digit));
out[0] = digit & DIGIT_MASK;
in_str += 6;
memcpy(&digit, in_str, sizeof(digit));
out[1] = (digit >> 4) & DIGIT_MASK;
in_str += 7;
out_len -= 2;
}
if (in_bitsize > DIGIT_SIZE) {
uint64_t digit = get_digit52(in_str, 7);
out[0] = digit & DIGIT_MASK;
in_str += 6;
in_bitsize -= DIGIT_SIZE;
digit = get_digit52(in_str, BITS2WORD8_SIZE(in_bitsize));
out[1] = digit >> 4;
out += 2;
out_len -= 2;
} else if (in_bitsize > 0) {
out[0] = get_digit52(in_str, BITS2WORD8_SIZE(in_bitsize));
out++;
out_len--;
}
- while (out_len > 0) {
- *out = 0;
- out_len--;
- out++;
- }
+ memset(out, 0, out_len * sizeof(BN_ULONG));
}
static ossl_inline void put_digit52(uint8_t *pStr, int strLen, uint64_t digit)
{
assert(pStr != NULL);
for (; strLen > 0; strLen--) {
*pStr++ = (uint8_t)(digit & 0xFF);
digit >>= 8;
}
}
/*
* Convert array of words in redundant (base=2^52) representation to array of
* words in regular (base=2^64) one.
*/
static void from_words52(BN_ULONG *out, int out_bitsize, const BN_ULONG *in)
{
int i;
int out_len = BITS2WORD64_SIZE(out_bitsize);
assert(out != NULL);
assert(in != NULL);
for (i = 0; i < out_len; i++)
out[i] = 0;
{
uint8_t *out_str = (uint8_t *)out;
for (; out_bitsize >= (2 * DIGIT_SIZE);
out_bitsize -= (2 * DIGIT_SIZE), in += 2) {
uint64_t digit;
digit = in[0];
memcpy(out_str, &digit, sizeof(digit));
out_str += 6;
digit = digit >> 48 | in[1] << 4;
memcpy(out_str, &digit, sizeof(digit));
out_str += 7;
}
if (out_bitsize > DIGIT_SIZE) {
put_digit52(out_str, 7, in[0]);
out_str += 6;
out_bitsize -= DIGIT_SIZE;
put_digit52(out_str, BITS2WORD8_SIZE(out_bitsize),
(in[1] << 4 | in[0] >> 48));
} else if (out_bitsize) {
put_digit52(out_str, BITS2WORD8_SIZE(out_bitsize), in[0]);
}
}
}
/*
* Set bit at index |idx| in the words array |a|.
* It does not do any boundaries checks, make sure the index is valid before
* calling the function.
*/
static ossl_inline void set_bit(BN_ULONG *a, int idx)
{
assert(a != NULL);
{
int i, j;
i = idx / BN_BITS2;
j = idx % BN_BITS2;
a[i] |= (((BN_ULONG)1) << j);
}
}
#endif
diff --git a/crypto/openssl/crypto/cmp/cmp_client.c b/crypto/openssl/crypto/cmp/cmp_client.c
index df334cc00198..4c8dbfdcd739 100644
--- a/crypto/openssl/crypto/cmp/cmp_client.c
+++ b/crypto/openssl/crypto/cmp/cmp_client.c
@@ -1,918 +1,921 @@
/*
* Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 "cmp_local.h"
#include "internal/cryptlib.h"
#include "e_os.h" /* ossl_sleep() */
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/bio.h>
#include <openssl/cmp.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include <openssl/cmp_util.h>
#define IS_CREP(t) ((t) == OSSL_CMP_PKIBODY_IP || (t) == OSSL_CMP_PKIBODY_CP \
|| (t) == OSSL_CMP_PKIBODY_KUP)
/*-
* Evaluate whether there's an exception (violating the standard) configured for
* handling negative responses without protection or with invalid protection.
* Returns 1 on acceptance, 0 on rejection, or -1 on (internal) error.
*/
static int unprotected_exception(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *rep,
int invalid_protection,
int expected_type /* ignored here */)
{
int rcvd_type = OSSL_CMP_MSG_get_bodytype(rep /* may be NULL */);
const char *msg_type = NULL;
if (!ossl_assert(ctx != NULL && rep != NULL))
return -1;
if (!ctx->unprotectedErrors)
return 0;
switch (rcvd_type) {
case OSSL_CMP_PKIBODY_ERROR:
msg_type = "error response";
break;
case OSSL_CMP_PKIBODY_RP:
{
OSSL_CMP_PKISI *si =
ossl_cmp_revrepcontent_get_pkisi(rep->body->value.rp,
OSSL_CMP_REVREQSID);
if (si == NULL)
return -1;
if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_rejection)
msg_type = "revocation response message with rejection status";
break;
}
case OSSL_CMP_PKIBODY_PKICONF:
msg_type = "PKI Confirmation message";
break;
default:
if (IS_CREP(rcvd_type)) {
int any_rid = OSSL_CMP_CERTREQID_NONE;
OSSL_CMP_CERTREPMESSAGE *crepmsg = rep->body->value.ip;
OSSL_CMP_CERTRESPONSE *crep =
ossl_cmp_certrepmessage_get0_certresponse(crepmsg, any_rid);
if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1)
return -1;
if (crep == NULL)
return -1;
if (ossl_cmp_pkisi_get_status(crep->status)
== OSSL_CMP_PKISTATUS_rejection)
msg_type = "CertRepMessage with rejection status";
}
}
if (msg_type == NULL)
return 0;
ossl_cmp_log2(WARN, ctx, "ignoring %s protection of %s",
invalid_protection ? "invalid" : "missing", msg_type);
return 1;
}
/* Save error info from PKIStatusInfo field of a certresponse into ctx */
static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
{
int i;
OSSL_CMP_PKIFREETEXT *ss;
if (!ossl_assert(ctx != NULL && si != NULL))
return 0;
ctx->status = ossl_cmp_pkisi_get_status(si);
if (ctx->status < OSSL_CMP_PKISTATUS_accepted)
return 0;
ctx->failInfoCode = ossl_cmp_pkisi_get_pkifailureinfo(si);
if (!ossl_cmp_ctx_set0_statusString(ctx, sk_ASN1_UTF8STRING_new_null())
|| (ctx->statusString == NULL))
return 0;
ss = si->statusString; /* may be NULL */
for (i = 0; i < sk_ASN1_UTF8STRING_num(ss); i++) {
ASN1_UTF8STRING *str = sk_ASN1_UTF8STRING_value(ss, i);
+ ASN1_UTF8STRING *dup = ASN1_STRING_dup(str);
- if (!sk_ASN1_UTF8STRING_push(ctx->statusString, ASN1_STRING_dup(str)))
+ if (dup == NULL || !sk_ASN1_UTF8STRING_push(ctx->statusString, dup)) {
+ ASN1_UTF8STRING_free(dup);
return 0;
+ }
}
return 1;
}
/*-
* Perform the generic aspects of sending a request and receiving a response.
* Returns 1 on success and provides the received PKIMESSAGE in *rep.
* Returns 0 on error.
* Regardless of success, caller is responsible for freeing *rep (unless NULL).
*/
static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
OSSL_CMP_MSG **rep, int expected_type)
{
int begin_transaction =
expected_type != OSSL_CMP_PKIBODY_POLLREP
&& expected_type != OSSL_CMP_PKIBODY_PKICONF;
const char *req_type_str =
ossl_cmp_bodytype_to_string(OSSL_CMP_MSG_get_bodytype(req));
const char *expected_type_str = ossl_cmp_bodytype_to_string(expected_type);
int bak_msg_timeout = ctx->msg_timeout;
int bt;
time_t now = time(NULL);
int time_left;
OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb;
if (transfer_cb == NULL)
transfer_cb = OSSL_CMP_MSG_http_perform;
*rep = NULL;
if (ctx->total_timeout != 0 /* not waiting indefinitely */) {
if (begin_transaction)
ctx->end_time = now + ctx->total_timeout;
if (now >= ctx->end_time) {
ERR_raise(ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT);
return 0;
}
if (!ossl_assert(ctx->end_time - now < INT_MAX)) {
/* actually cannot happen due to assignment in initial_certreq() */
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
return 0;
}
time_left = (int)(ctx->end_time - now);
if (ctx->msg_timeout == 0 || time_left < ctx->msg_timeout)
ctx->msg_timeout = time_left;
}
/* should print error queue since transfer_cb may call ERR_clear_error() */
OSSL_CMP_CTX_print_errors(ctx);
ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
*rep = (*transfer_cb)(ctx, req);
ctx->msg_timeout = bak_msg_timeout;
if (*rep == NULL) {
ERR_raise_data(ERR_LIB_CMP,
ctx->total_timeout != 0 && time(NULL) >= ctx->end_time ?
CMP_R_TOTAL_TIMEOUT : CMP_R_TRANSFER_ERROR,
"request sent: %s, expected response: %s",
req_type_str, expected_type_str);
return 0;
}
bt = OSSL_CMP_MSG_get_bodytype(*rep);
/*
* The body type in the 'bt' variable is not yet verified.
* Still we use this preliminary value already for a progress report because
* the following msg verification may also produce log entries and may fail.
*/
ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt));
/* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */
if (bt != OSSL_CMP_PKIBODY_POLLREP && bt != OSSL_CMP_PKIBODY_PKICONF
&& !ossl_cmp_ctx_set1_extraCertsIn(ctx, (*rep)->extraCerts))
return 0;
if (!ossl_cmp_msg_check_update(ctx, *rep, unprotected_exception,
expected_type))
return 0;
if (bt == expected_type
/* as an answer to polling, there could be IP/CP/KUP: */
|| (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP))
return 1;
/* received message type is not one of the expected ones (e.g., error) */
ERR_raise(ERR_LIB_CMP, bt == OSSL_CMP_PKIBODY_ERROR ? CMP_R_RECEIVED_ERROR :
CMP_R_UNEXPECTED_PKIBODY); /* in next line for mkerr.pl */
if (bt != OSSL_CMP_PKIBODY_ERROR) {
ERR_add_error_data(3, "message type is '",
ossl_cmp_bodytype_to_string(bt), "'");
} else {
OSSL_CMP_ERRORMSGCONTENT *emc = (*rep)->body->value.error;
OSSL_CMP_PKISI *si = emc->pKIStatusInfo;
char buf[OSSL_CMP_PKISI_BUFLEN];
if (save_statusInfo(ctx, si)
&& OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf,
sizeof(buf)) != NULL)
ERR_add_error_data(1, buf);
if (emc->errorCode != NULL
&& BIO_snprintf(buf, sizeof(buf), "; errorCode: %08lX",
ASN1_INTEGER_get(emc->errorCode)) > 0)
ERR_add_error_data(1, buf);
if (emc->errorDetails != NULL) {
char *text = ossl_sk_ASN1_UTF8STRING2text(emc->errorDetails, ", ",
OSSL_CMP_PKISI_BUFLEN - 1);
if (text != NULL && *text != '\0')
ERR_add_error_data(2, "; errorDetails: ", text);
OPENSSL_free(text);
}
if (ctx->status != OSSL_CMP_PKISTATUS_rejection) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS);
if (ctx->status == OSSL_CMP_PKISTATUS_waiting)
ctx->status = OSSL_CMP_PKISTATUS_rejection;
}
}
return 0;
}
/*-
* When a 'waiting' PKIStatus has been received, this function is used to
* poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup.
* On receiving a pollRep, which includes a checkAfter value, it return this
* value if sleep == 0, else it sleeps as long as indicated and retries.
*
* A transaction timeout is enabled if ctx->total_timeout is != 0.
* In this case polling will continue until the timeout is reached and then
* polling is done a last time even if this is before the "checkAfter" time.
*
* Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
* Returns 1 on success and provides the received PKIMESSAGE in *rep.
* In this case the caller is responsible for freeing *rep.
* Returns 0 on error (which includes the case that timeout has been reached).
*/
static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
OSSL_CMP_MSG **rep, int *checkAfter)
{
OSSL_CMP_MSG *preq = NULL;
OSSL_CMP_MSG *prep = NULL;
ossl_cmp_info(ctx,
"received 'waiting' PKIStatus, starting to poll for response");
*rep = NULL;
for (;;) {
if ((preq = ossl_cmp_pollReq_new(ctx, rid)) == NULL)
goto err;
if (!send_receive_check(ctx, preq, &prep, OSSL_CMP_PKIBODY_POLLREP))
goto err;
/* handle potential pollRep */
if (OSSL_CMP_MSG_get_bodytype(prep) == OSSL_CMP_PKIBODY_POLLREP) {
OSSL_CMP_POLLREPCONTENT *prc = prep->body->value.pollRep;
OSSL_CMP_POLLREP *pollRep = NULL;
int64_t check_after;
char str[OSSL_CMP_PKISI_BUFLEN];
int len;
if (sk_OSSL_CMP_POLLREP_num(prc) > 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
goto err;
}
pollRep = ossl_cmp_pollrepcontent_get0_pollrep(prc, rid);
if (pollRep == NULL)
goto err;
if (!ASN1_INTEGER_get_int64(&check_after, pollRep->checkAfter)) {
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_CHECKAFTER_IN_POLLREP);
goto err;
}
if (check_after < 0 || (uint64_t)check_after
> (sleep ? ULONG_MAX / 1000 : INT_MAX)) {
ERR_raise(ERR_LIB_CMP, CMP_R_CHECKAFTER_OUT_OF_RANGE);
if (BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN, "value = %jd",
check_after) >= 0)
ERR_add_error_data(1, str);
goto err;
}
if (pollRep->reason == NULL
|| (len = BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN,
" with reason = '")) < 0) {
*str = '\0';
} else {
char *text = ossl_sk_ASN1_UTF8STRING2text(pollRep->reason, ", ",
sizeof(str) - len - 2);
if (text == NULL
|| BIO_snprintf(str + len, sizeof(str) - len,
"%s'", text) < 0)
*str = '\0';
OPENSSL_free(text);
}
ossl_cmp_log2(INFO, ctx,
"received polling response%s; checkAfter = %ld seconds",
str, check_after);
if (ctx->total_timeout != 0) { /* timeout is not infinite */
const int exp = 5; /* expected max time per msg round trip */
int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL));
if (time_left <= 0) {
ERR_raise(ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT);
goto err;
}
if (time_left < check_after)
check_after = time_left;
/* poll one last time just when timeout was reached */
}
OSSL_CMP_MSG_free(preq);
preq = NULL;
OSSL_CMP_MSG_free(prep);
prep = NULL;
if (sleep) {
ossl_sleep((unsigned long)(1000 * check_after));
} else {
if (checkAfter != NULL)
*checkAfter = (int)check_after;
return -1; /* exits the loop */
}
} else {
ossl_cmp_info(ctx, "received ip/cp/kup after polling");
/* any other body type has been rejected by send_receive_check() */
break;
}
}
if (prep == NULL)
goto err;
OSSL_CMP_MSG_free(preq);
*rep = prep;
return 1;
err:
OSSL_CMP_MSG_free(preq);
OSSL_CMP_MSG_free(prep);
return 0;
}
/*
* Send certConf for IR, CR or KUR sequences and check response,
* not modifying ctx->status during the certConf exchange
*/
int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId,
int fail_info, const char *txt)
{
OSSL_CMP_MSG *certConf;
OSSL_CMP_MSG *PKIconf = NULL;
int res = 0;
/* OSSL_CMP_certConf_new() also checks if all necessary options are set */
certConf = ossl_cmp_certConf_new(ctx, certReqId, fail_info, txt);
if (certConf == NULL)
goto err;
res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
err:
OSSL_CMP_MSG_free(certConf);
OSSL_CMP_MSG_free(PKIconf);
return res;
}
/* Send given error and check response */
int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
const char *txt, int errorCode, const char *details)
{
OSSL_CMP_MSG *error = NULL;
OSSL_CMP_PKISI *si = NULL;
OSSL_CMP_MSG *PKIconf = NULL;
int res = 0;
/* not overwriting ctx->status on error exchange */
if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt)) == NULL)
goto err;
/* ossl_cmp_error_new() also checks if all necessary options are set */
if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL)
goto err;
res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
err:
OSSL_CMP_MSG_free(error);
OSSL_CMP_PKISI_free(si);
OSSL_CMP_MSG_free(PKIconf);
return res;
}
/*-
* Retrieve a copy of the certificate, if any, from the given CertResponse.
* Take into account PKIStatusInfo of CertResponse in ctx, report it on error.
* Returns NULL if not found or on error.
*/
static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype,
OSSL_CMP_CERTRESPONSE *crep)
{
char buf[OSSL_CMP_PKISI_BUFLEN];
X509 *crt = NULL;
if (!ossl_assert(ctx != NULL && crep != NULL))
return NULL;
switch (ossl_cmp_pkisi_get_status(crep->status)) {
case OSSL_CMP_PKISTATUS_waiting:
ossl_cmp_err(ctx,
"received \"waiting\" status for cert when actually aiming to extract cert");
ERR_raise(ERR_LIB_CMP, CMP_R_ENCOUNTERED_WAITING);
goto err;
case OSSL_CMP_PKISTATUS_grantedWithMods:
ossl_cmp_warn(ctx, "received \"grantedWithMods\" for certificate");
break;
case OSSL_CMP_PKISTATUS_accepted:
break;
/* get all information in case of a rejection before going to error */
case OSSL_CMP_PKISTATUS_rejection:
ossl_cmp_err(ctx, "received \"rejection\" status rather than cert");
ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_REJECTED_BY_SERVER);
goto err;
case OSSL_CMP_PKISTATUS_revocationWarning:
ossl_cmp_warn(ctx,
"received \"revocationWarning\" - a revocation of the cert is imminent");
break;
case OSSL_CMP_PKISTATUS_revocationNotification:
ossl_cmp_warn(ctx,
"received \"revocationNotification\" - a revocation of the cert has occurred");
break;
case OSSL_CMP_PKISTATUS_keyUpdateWarning:
if (bodytype != OSSL_CMP_PKIBODY_KUR) {
ERR_raise(ERR_LIB_CMP, CMP_R_ENCOUNTERED_KEYUPDATEWARNING);
goto err;
}
break;
default:
ossl_cmp_log1(ERROR, ctx,
"received unsupported PKIStatus %d for certificate",
ctx->status);
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS);
goto err;
}
crt = ossl_cmp_certresponse_get1_cert(ctx, crep);
if (crt == NULL) /* according to PKIStatus, we can expect a cert */
ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);
return crt;
err:
if (OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
ERR_add_error_data(1, buf);
return NULL;
}
/*-
* Callback fn validating that the new certificate can be verified, using
* ctx->certConf_cb_arg, which has been initialized using opt_out_trusted, and
* ctx->untrusted, which at this point already contains msg->extraCerts.
* Returns 0 on acceptance, else a bit field reflecting PKIFailureInfo.
* Quoting from RFC 4210 section 5.1. Overall PKI Message:
* The extraCerts field can contain certificates that may be useful to
* the recipient. For example, this can be used by a CA or RA to
* present an end entity with certificates that it needs to verify its
* own new certificate (if, for example, the CA that issued the end
* entity's certificate is not a root CA for the end entity). Note that
* this field does not necessarily contain a certification path; the
* recipient may have to sort, select from, or otherwise process the
* extra certificates in order to use them.
* Note: While often handy, there is no hard requirement by CMP that
* an EE must be able to validate the certificates it gets enrolled.
*/
int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
const char **text)
{
X509_STORE *out_trusted = OSSL_CMP_CTX_get_certConf_cb_arg(ctx);
STACK_OF(X509) *chain = NULL;
(void)text; /* make (artificial) use of var to prevent compiler warning */
if (fail_info != 0) /* accept any error flagged by CMP core library */
return fail_info;
if (out_trusted == NULL) {
ossl_cmp_debug(ctx, "trying to build chain for newly enrolled cert");
chain = X509_build_chain(cert, ctx->untrusted, out_trusted,
0, ctx->libctx, ctx->propq);
} else {
X509_STORE_CTX *csc = X509_STORE_CTX_new_ex(ctx->libctx, ctx->propq);
ossl_cmp_debug(ctx, "validating newly enrolled cert");
if (csc == NULL)
goto err;
if (!X509_STORE_CTX_init(csc, out_trusted, cert, ctx->untrusted))
goto err;
/* disable any cert status/revocation checking etc. */
X509_VERIFY_PARAM_clear_flags(X509_STORE_CTX_get0_param(csc),
~(X509_V_FLAG_USE_CHECK_TIME
| X509_V_FLAG_NO_CHECK_TIME
| X509_V_FLAG_PARTIAL_CHAIN
| X509_V_FLAG_POLICY_CHECK));
if (X509_verify_cert(csc) <= 0)
goto err;
if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc),
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
| X509_ADD_FLAG_NO_SS)) {
sk_X509_free(chain);
chain = NULL;
}
err:
X509_STORE_CTX_free(csc);
}
if (sk_X509_num(chain) > 0)
X509_free(sk_X509_shift(chain)); /* remove leaf (EE) cert */
if (out_trusted != NULL) {
if (chain == NULL) {
ossl_cmp_err(ctx, "failed to validate newly enrolled cert");
fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
} else {
ossl_cmp_debug(ctx,
"success validating newly enrolled cert");
}
} else if (chain == NULL) {
ossl_cmp_warn(ctx, "could not build approximate chain for newly enrolled cert, resorting to received extraCerts");
chain = OSSL_CMP_CTX_get1_extraCertsIn(ctx);
} else {
ossl_cmp_debug(ctx,
"success building approximate chain for newly enrolled cert");
}
(void)ossl_cmp_ctx_set1_newChain(ctx, chain);
sk_X509_pop_free(chain, X509_free);
return fail_info;
}
/*-
* Perform the generic handling of certificate responses for IR/CR/KUR/P10CR.
* |rid| must be OSSL_CMP_CERTREQID_NONE if not available, namely for p10cr
* Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
* Returns 1 on success and provides the received PKIMESSAGE in *resp.
* Returns 0 on error (which includes the case that timeout has been reached).
* Regardless of success, caller is responsible for freeing *resp (unless NULL).
*/
static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
OSSL_CMP_MSG **resp, int *checkAfter,
int req_type, int expected_type)
{
EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx);
int fail_info = 0; /* no failure */
const char *txt = NULL;
OSSL_CMP_CERTREPMESSAGE *crepmsg;
OSSL_CMP_CERTRESPONSE *crep;
OSSL_CMP_certConf_cb_t cb;
X509 *cert;
char *subj = NULL;
int ret = 1;
if (!ossl_assert(ctx != NULL))
return 0;
retry:
crepmsg = (*resp)->body->value.ip; /* same for cp and kup */
if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
return 0;
}
crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
if (crep == NULL)
return 0;
if (!save_statusInfo(ctx, crep->status))
return 0;
if (rid == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */
rid = ossl_cmp_asn1_get_int(crep->certReqId);
if (rid < OSSL_CMP_CERTREQID_NONE) {
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
return 0;
}
}
if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) {
OSSL_CMP_MSG_free(*resp);
*resp = NULL;
if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) {
if (ret == -1) /* at this point implies sleep == 0 */
return ret; /* waiting */
goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */
} else {
ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED);
return 0;
}
}
cert = get1_cert_status(ctx, (*resp)->body->type, crep);
if (cert == NULL) {
ERR_add_error_data(1, "; cannot extract certificate from response");
return 0;
}
if (!ossl_cmp_ctx_set0_newCert(ctx, cert))
return 0;
/*
* if the CMP server returned certificates in the caPubs field, copy them
* to the context so that they can be retrieved if necessary
*/
if (crepmsg->caPubs != NULL
&& !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs))
return 0;
subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
if (rkey != NULL
/* X509_check_private_key() also works if rkey is just public key */
&& !(X509_check_private_key(ctx->newCert, rkey))) {
fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
txt = "public key in new certificate does not match our enrollment key";
/*-
* not calling (void)ossl_cmp_exchange_error(ctx,
* OSSL_CMP_PKISTATUS_rejection, fail_info, txt)
* not throwing CMP_R_CERTIFICATE_NOT_ACCEPTED with txt
* not returning 0
* since we better leave this for the certConf_cb to decide
*/
}
/*
* Execute the certification checking callback function,
* which can determine whether to accept a newly enrolled certificate.
* It may overrule the pre-decision reflected in 'fail_info' and '*txt'.
*/
cb = ctx->certConf_cb != NULL ? ctx->certConf_cb : OSSL_CMP_certConf_cb;
if ((fail_info = cb(ctx, ctx->newCert, fail_info, &txt)) != 0
&& txt == NULL)
txt = "CMP client did not accept it";
if (fail_info != 0) /* immediately log error before any certConf exchange */
ossl_cmp_log1(ERROR, ctx,
"rejecting newly enrolled cert with subject: %s", subj);
if (!ctx->disableConfirm
&& !ossl_cmp_hdr_has_implicitConfirm((*resp)->header)) {
if (!ossl_cmp_exchange_certConf(ctx, rid, fail_info, txt))
ret = 0;
}
/* not throwing failure earlier as transfer_cb may call ERR_clear_error() */
if (fail_info != 0) {
ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_ACCEPTED,
"rejecting newly enrolled cert with subject: %s; %s",
subj, txt);
ctx->status = OSSL_CMP_PKISTATUS_rejection;
ret = 0;
}
OPENSSL_free(subj);
return ret;
}
static int initial_certreq(OSSL_CMP_CTX *ctx,
int req_type, const OSSL_CRMF_MSG *crm,
OSSL_CMP_MSG **p_rep, int rep_type)
{
OSSL_CMP_MSG *req;
int res;
ctx->status = OSSL_CMP_PKISTATUS_request;
if (!ossl_cmp_ctx_set0_newCert(ctx, NULL))
return 0;
/* also checks if all necessary options are set */
if ((req = ossl_cmp_certreq_new(ctx, req_type, crm)) == NULL)
return 0;
ctx->status = OSSL_CMP_PKISTATUS_trans;
res = send_receive_check(ctx, req, p_rep, rep_type);
OSSL_CMP_MSG_free(req);
return res;
}
int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
const OSSL_CRMF_MSG *crm, int *checkAfter)
{
OSSL_CMP_MSG *rep = NULL;
int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR;
int rid = is_p10 ? OSSL_CMP_CERTREQID_NONE : OSSL_CMP_CERTREQID;
int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1;
int res = 0;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */
if (!initial_certreq(ctx, req_type, crm, &rep, rep_type))
goto err;
} else {
if (req_type < 0)
return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
0, "polling aborted",
0 /* errorCode */, "by application");
res = poll_for_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter);
if (res <= 0) /* waiting or error */
return res;
}
res = cert_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter,
req_type, rep_type);
err:
OSSL_CMP_MSG_free(rep);
return res;
}
/*-
* Do the full sequence CR/IR/KUR/P10CR, CP/IP/KUP/CP,
* certConf, PKIconf, and polling if required.
* Will sleep as long as indicated by the server (according to checkAfter).
* All enrollment options need to be present in the context.
* Returns pointer to received certificate, or NULL if none was received.
*/
X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
const OSSL_CRMF_MSG *crm)
{
OSSL_CMP_MSG *rep = NULL;
int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR;
int rid = is_p10 ? OSSL_CMP_CERTREQID_NONE : OSSL_CMP_CERTREQID;
int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1;
X509 *result = NULL;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
if (!initial_certreq(ctx, req_type, crm, &rep, rep_type))
goto err;
if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type)
<= 0)
goto err;
result = ctx->newCert;
err:
OSSL_CMP_MSG_free(rep);
return result;
}
int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
{
OSSL_CMP_MSG *rr = NULL;
OSSL_CMP_MSG *rp = NULL;
const int num_RevDetails = 1;
const int rsid = OSSL_CMP_REVREQSID;
OSSL_CMP_REVREPCONTENT *rrep = NULL;
OSSL_CMP_PKISI *si = NULL;
char buf[OSSL_CMP_PKISI_BUFLEN];
int ret = 0;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
return 0;
}
ctx->status = OSSL_CMP_PKISTATUS_request;
if (ctx->oldCert == NULL && ctx->p10CSR == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT);
return 0;
}
/* OSSL_CMP_rr_new() also checks if all necessary options are set */
if ((rr = ossl_cmp_rr_new(ctx)) == NULL)
goto end;
ctx->status = OSSL_CMP_PKISTATUS_trans;
if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
goto end;
rrep = rp->body->value.rp;
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if (sk_OSSL_CMP_PKISI_num(rrep->status) != num_RevDetails) {
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
goto end;
}
#else
if (sk_OSSL_CMP_PKISI_num(rrep->status) < 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
goto end;
}
#endif
/* evaluate PKIStatus field */
si = ossl_cmp_revrepcontent_get_pkisi(rrep, rsid);
if (!save_statusInfo(ctx, si))
goto err;
switch (ossl_cmp_pkisi_get_status(si)) {
case OSSL_CMP_PKISTATUS_accepted:
ossl_cmp_info(ctx, "revocation accepted (PKIStatus=accepted)");
ret = 1;
break;
case OSSL_CMP_PKISTATUS_grantedWithMods:
ossl_cmp_info(ctx, "revocation accepted (PKIStatus=grantedWithMods)");
ret = 1;
break;
case OSSL_CMP_PKISTATUS_rejection:
ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_REJECTED_BY_SERVER);
goto err;
case OSSL_CMP_PKISTATUS_revocationWarning:
ossl_cmp_info(ctx, "revocation accepted (PKIStatus=revocationWarning)");
ret = 1;
break;
case OSSL_CMP_PKISTATUS_revocationNotification:
/* interpretation as warning or error depends on CA */
ossl_cmp_warn(ctx,
"revocation accepted (PKIStatus=revocationNotification)");
ret = 1;
break;
case OSSL_CMP_PKISTATUS_waiting:
case OSSL_CMP_PKISTATUS_keyUpdateWarning:
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS);
goto err;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS);
goto err;
}
/* check any present CertId in optional revCerts field */
if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) >= 1) {
OSSL_CRMF_CERTID *cid;
OSSL_CRMF_CERTTEMPLATE *tmpl =
sk_OSSL_CMP_REVDETAILS_value(rr->body->value.rr, rsid)->certDetails;
const X509_NAME *issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
const ASN1_INTEGER *serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) != num_RevDetails) {
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
ret = 0;
goto err;
}
if ((cid = ossl_cmp_revrepcontent_get_CertId(rrep, rsid)) == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CERTID);
ret = 0;
goto err;
}
if (X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID_IN_RP);
ret = 0;
goto err;
#endif
}
if (ASN1_INTEGER_cmp(serial,
OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_SERIAL_IN_RP);
ret = 0;
goto err;
#endif
}
}
/* check number of any optionally present crls */
if (rrep->crls != NULL && sk_X509_CRL_num(rrep->crls) != num_RevDetails) {
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
ret = 0;
goto err;
}
err:
if (ret == 0
&& OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
ERR_add_error_data(1, buf);
end:
OSSL_CMP_MSG_free(rr);
OSSL_CMP_MSG_free(rp);
return ret;
}
STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx)
{
OSSL_CMP_MSG *genm;
OSSL_CMP_MSG *genp = NULL;
STACK_OF(OSSL_CMP_ITAV) *itavs = NULL;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
return NULL;
}
ctx->status = OSSL_CMP_PKISTATUS_request;
if ((genm = ossl_cmp_genm_new(ctx)) == NULL)
goto err;
ctx->status = OSSL_CMP_PKISTATUS_trans;
if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
goto err;
ctx->status = OSSL_CMP_PKISTATUS_accepted;
itavs = genp->body->value.genp;
if (itavs == NULL)
itavs = sk_OSSL_CMP_ITAV_new_null();
/* received stack of itavs not to be freed with the genp */
genp->body->value.genp = NULL;
err:
OSSL_CMP_MSG_free(genm);
OSSL_CMP_MSG_free(genp);
return itavs; /* NULL indicates error case */
}
diff --git a/crypto/openssl/crypto/cms/cms_asn1.c b/crypto/openssl/crypto/cms/cms_asn1.c
index 72cd14317d47..950952015923 100644
--- a/crypto/openssl/crypto/cms/cms_asn1.c
+++ b/crypto/openssl/crypto/cms/cms_asn1.c
@@ -1,415 +1,430 @@
/*
* Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/asn1t.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/cms.h>
#include "cms_local.h"
ASN1_SEQUENCE(CMS_IssuerAndSerialNumber) = {
ASN1_SIMPLE(CMS_IssuerAndSerialNumber, issuer, X509_NAME),
ASN1_SIMPLE(CMS_IssuerAndSerialNumber, serialNumber, ASN1_INTEGER)
} ASN1_SEQUENCE_END(CMS_IssuerAndSerialNumber)
ASN1_SEQUENCE(CMS_OtherCertificateFormat) = {
ASN1_SIMPLE(CMS_OtherCertificateFormat, otherCertFormat, ASN1_OBJECT),
ASN1_OPT(CMS_OtherCertificateFormat, otherCert, ASN1_ANY)
} static_ASN1_SEQUENCE_END(CMS_OtherCertificateFormat)
ASN1_CHOICE(CMS_CertificateChoices) = {
ASN1_SIMPLE(CMS_CertificateChoices, d.certificate, X509),
ASN1_IMP(CMS_CertificateChoices, d.extendedCertificate, ASN1_SEQUENCE, 0),
ASN1_IMP(CMS_CertificateChoices, d.v1AttrCert, ASN1_SEQUENCE, 1),
ASN1_IMP(CMS_CertificateChoices, d.v2AttrCert, ASN1_SEQUENCE, 2),
ASN1_IMP(CMS_CertificateChoices, d.other, CMS_OtherCertificateFormat, 3)
} ASN1_CHOICE_END(CMS_CertificateChoices)
ASN1_CHOICE(CMS_SignerIdentifier) = {
ASN1_SIMPLE(CMS_SignerIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
ASN1_IMP(CMS_SignerIdentifier, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0)
} static_ASN1_CHOICE_END(CMS_SignerIdentifier)
ASN1_NDEF_SEQUENCE(CMS_EncapsulatedContentInfo) = {
ASN1_SIMPLE(CMS_EncapsulatedContentInfo, eContentType, ASN1_OBJECT),
ASN1_NDEF_EXP_OPT(CMS_EncapsulatedContentInfo, eContent, ASN1_OCTET_STRING_NDEF, 0)
} static_ASN1_NDEF_SEQUENCE_END(CMS_EncapsulatedContentInfo)
/* Minor tweak to operation: free up signer key, cert */
static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
if (operation == ASN1_OP_FREE_POST) {
CMS_SignerInfo *si = (CMS_SignerInfo *)*pval;
EVP_PKEY_free(si->pkey);
X509_free(si->signer);
EVP_MD_CTX_free(si->mctx);
+ EVP_PKEY_CTX_free(si->pctx);
}
return 1;
}
ASN1_SEQUENCE_cb(CMS_SignerInfo, cms_si_cb) = {
ASN1_EMBED(CMS_SignerInfo, version, INT32),
ASN1_SIMPLE(CMS_SignerInfo, sid, CMS_SignerIdentifier),
ASN1_SIMPLE(CMS_SignerInfo, digestAlgorithm, X509_ALGOR),
ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, signedAttrs, X509_ATTRIBUTE, 0),
ASN1_SIMPLE(CMS_SignerInfo, signatureAlgorithm, X509_ALGOR),
ASN1_SIMPLE(CMS_SignerInfo, signature, ASN1_OCTET_STRING),
ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, unsignedAttrs, X509_ATTRIBUTE, 1)
} ASN1_SEQUENCE_END_cb(CMS_SignerInfo, CMS_SignerInfo)
ASN1_SEQUENCE(CMS_OtherRevocationInfoFormat) = {
ASN1_SIMPLE(CMS_OtherRevocationInfoFormat, otherRevInfoFormat, ASN1_OBJECT),
ASN1_OPT(CMS_OtherRevocationInfoFormat, otherRevInfo, ASN1_ANY)
} static_ASN1_SEQUENCE_END(CMS_OtherRevocationInfoFormat)
ASN1_CHOICE(CMS_RevocationInfoChoice) = {
ASN1_SIMPLE(CMS_RevocationInfoChoice, d.crl, X509_CRL),
ASN1_IMP(CMS_RevocationInfoChoice, d.other, CMS_OtherRevocationInfoFormat, 1)
} ASN1_CHOICE_END(CMS_RevocationInfoChoice)
ASN1_NDEF_SEQUENCE(CMS_SignedData) = {
ASN1_EMBED(CMS_SignedData, version, INT32),
ASN1_SET_OF(CMS_SignedData, digestAlgorithms, X509_ALGOR),
ASN1_SIMPLE(CMS_SignedData, encapContentInfo, CMS_EncapsulatedContentInfo),
ASN1_IMP_SET_OF_OPT(CMS_SignedData, certificates, CMS_CertificateChoices, 0),
ASN1_IMP_SET_OF_OPT(CMS_SignedData, crls, CMS_RevocationInfoChoice, 1),
ASN1_SET_OF(CMS_SignedData, signerInfos, CMS_SignerInfo)
} ASN1_NDEF_SEQUENCE_END(CMS_SignedData)
ASN1_SEQUENCE(CMS_OriginatorInfo) = {
ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, certificates, CMS_CertificateChoices, 0),
ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, crls, CMS_RevocationInfoChoice, 1)
} static_ASN1_SEQUENCE_END(CMS_OriginatorInfo)
-ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = {
+static int cms_ec_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+{
+ CMS_EncryptedContentInfo *ec = (CMS_EncryptedContentInfo *)*pval;
+
+ if (operation == ASN1_OP_FREE_POST)
+ OPENSSL_clear_free(ec->key, ec->keylen);
+ return 1;
+}
+
+ASN1_NDEF_SEQUENCE_cb(CMS_EncryptedContentInfo, cms_ec_cb) = {
ASN1_SIMPLE(CMS_EncryptedContentInfo, contentType, ASN1_OBJECT),
ASN1_SIMPLE(CMS_EncryptedContentInfo, contentEncryptionAlgorithm, X509_ALGOR),
ASN1_IMP_OPT(CMS_EncryptedContentInfo, encryptedContent, ASN1_OCTET_STRING_NDEF, 0)
-} static_ASN1_NDEF_SEQUENCE_END(CMS_EncryptedContentInfo)
+} ASN1_NDEF_SEQUENCE_END_cb(CMS_EncryptedContentInfo, CMS_EncryptedContentInfo)
ASN1_SEQUENCE(CMS_KeyTransRecipientInfo) = {
ASN1_EMBED(CMS_KeyTransRecipientInfo, version, INT32),
ASN1_SIMPLE(CMS_KeyTransRecipientInfo, rid, CMS_SignerIdentifier),
ASN1_SIMPLE(CMS_KeyTransRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
ASN1_SIMPLE(CMS_KeyTransRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(CMS_KeyTransRecipientInfo)
ASN1_SEQUENCE(CMS_OtherKeyAttribute) = {
ASN1_SIMPLE(CMS_OtherKeyAttribute, keyAttrId, ASN1_OBJECT),
ASN1_OPT(CMS_OtherKeyAttribute, keyAttr, ASN1_ANY)
} ASN1_SEQUENCE_END(CMS_OtherKeyAttribute)
ASN1_SEQUENCE(CMS_RecipientKeyIdentifier) = {
ASN1_SIMPLE(CMS_RecipientKeyIdentifier, subjectKeyIdentifier, ASN1_OCTET_STRING),
ASN1_OPT(CMS_RecipientKeyIdentifier, date, ASN1_GENERALIZEDTIME),
ASN1_OPT(CMS_RecipientKeyIdentifier, other, CMS_OtherKeyAttribute)
} ASN1_SEQUENCE_END(CMS_RecipientKeyIdentifier)
ASN1_CHOICE(CMS_KeyAgreeRecipientIdentifier) = {
ASN1_SIMPLE(CMS_KeyAgreeRecipientIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
ASN1_IMP(CMS_KeyAgreeRecipientIdentifier, d.rKeyId, CMS_RecipientKeyIdentifier, 0)
} static_ASN1_CHOICE_END(CMS_KeyAgreeRecipientIdentifier)
static int cms_rek_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
CMS_RecipientEncryptedKey *rek = (CMS_RecipientEncryptedKey *)*pval;
if (operation == ASN1_OP_FREE_POST) {
EVP_PKEY_free(rek->pkey);
}
return 1;
}
ASN1_SEQUENCE_cb(CMS_RecipientEncryptedKey, cms_rek_cb) = {
ASN1_SIMPLE(CMS_RecipientEncryptedKey, rid, CMS_KeyAgreeRecipientIdentifier),
ASN1_SIMPLE(CMS_RecipientEncryptedKey, encryptedKey, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END_cb(CMS_RecipientEncryptedKey, CMS_RecipientEncryptedKey)
ASN1_SEQUENCE(CMS_OriginatorPublicKey) = {
ASN1_SIMPLE(CMS_OriginatorPublicKey, algorithm, X509_ALGOR),
ASN1_SIMPLE(CMS_OriginatorPublicKey, publicKey, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END(CMS_OriginatorPublicKey)
ASN1_CHOICE(CMS_OriginatorIdentifierOrKey) = {
ASN1_SIMPLE(CMS_OriginatorIdentifierOrKey, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0),
ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.originatorKey, CMS_OriginatorPublicKey, 1)
} static_ASN1_CHOICE_END(CMS_OriginatorIdentifierOrKey)
static int cms_kari_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
CMS_KeyAgreeRecipientInfo *kari = (CMS_KeyAgreeRecipientInfo *)*pval;
if (operation == ASN1_OP_NEW_POST) {
kari->ctx = EVP_CIPHER_CTX_new();
if (kari->ctx == NULL)
return 0;
EVP_CIPHER_CTX_set_flags(kari->ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
kari->pctx = NULL;
} else if (operation == ASN1_OP_FREE_POST) {
EVP_PKEY_CTX_free(kari->pctx);
EVP_CIPHER_CTX_free(kari->ctx);
}
return 1;
}
ASN1_SEQUENCE_cb(CMS_KeyAgreeRecipientInfo, cms_kari_cb) = {
ASN1_EMBED(CMS_KeyAgreeRecipientInfo, version, INT32),
ASN1_EXP(CMS_KeyAgreeRecipientInfo, originator, CMS_OriginatorIdentifierOrKey, 0),
ASN1_EXP_OPT(CMS_KeyAgreeRecipientInfo, ukm, ASN1_OCTET_STRING, 1),
ASN1_SIMPLE(CMS_KeyAgreeRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
ASN1_SEQUENCE_OF(CMS_KeyAgreeRecipientInfo, recipientEncryptedKeys, CMS_RecipientEncryptedKey)
} ASN1_SEQUENCE_END_cb(CMS_KeyAgreeRecipientInfo, CMS_KeyAgreeRecipientInfo)
ASN1_SEQUENCE(CMS_KEKIdentifier) = {
ASN1_SIMPLE(CMS_KEKIdentifier, keyIdentifier, ASN1_OCTET_STRING),
ASN1_OPT(CMS_KEKIdentifier, date, ASN1_GENERALIZEDTIME),
ASN1_OPT(CMS_KEKIdentifier, other, CMS_OtherKeyAttribute)
} static_ASN1_SEQUENCE_END(CMS_KEKIdentifier)
ASN1_SEQUENCE(CMS_KEKRecipientInfo) = {
ASN1_EMBED(CMS_KEKRecipientInfo, version, INT32),
ASN1_SIMPLE(CMS_KEKRecipientInfo, kekid, CMS_KEKIdentifier),
ASN1_SIMPLE(CMS_KEKRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
ASN1_SIMPLE(CMS_KEKRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(CMS_KEKRecipientInfo)
ASN1_SEQUENCE(CMS_PasswordRecipientInfo) = {
ASN1_EMBED(CMS_PasswordRecipientInfo, version, INT32),
ASN1_IMP_OPT(CMS_PasswordRecipientInfo, keyDerivationAlgorithm, X509_ALGOR, 0),
ASN1_SIMPLE(CMS_PasswordRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
ASN1_SIMPLE(CMS_PasswordRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(CMS_PasswordRecipientInfo)
ASN1_SEQUENCE(CMS_OtherRecipientInfo) = {
ASN1_SIMPLE(CMS_OtherRecipientInfo, oriType, ASN1_OBJECT),
ASN1_OPT(CMS_OtherRecipientInfo, oriValue, ASN1_ANY)
} static_ASN1_SEQUENCE_END(CMS_OtherRecipientInfo)
/* Free up RecipientInfo additional data */
static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
if (operation == ASN1_OP_FREE_PRE) {
CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval;
if (ri->type == CMS_RECIPINFO_TRANS) {
CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
EVP_PKEY_free(ktri->pkey);
X509_free(ktri->recip);
EVP_PKEY_CTX_free(ktri->pctx);
} else if (ri->type == CMS_RECIPINFO_KEK) {
CMS_KEKRecipientInfo *kekri = ri->d.kekri;
OPENSSL_clear_free(kekri->key, kekri->keylen);
} else if (ri->type == CMS_RECIPINFO_PASS) {
CMS_PasswordRecipientInfo *pwri = ri->d.pwri;
OPENSSL_clear_free(pwri->pass, pwri->passlen);
}
}
return 1;
}
ASN1_CHOICE_cb(CMS_RecipientInfo, cms_ri_cb) = {
ASN1_SIMPLE(CMS_RecipientInfo, d.ktri, CMS_KeyTransRecipientInfo),
ASN1_IMP(CMS_RecipientInfo, d.kari, CMS_KeyAgreeRecipientInfo, 1),
ASN1_IMP(CMS_RecipientInfo, d.kekri, CMS_KEKRecipientInfo, 2),
ASN1_IMP(CMS_RecipientInfo, d.pwri, CMS_PasswordRecipientInfo, 3),
ASN1_IMP(CMS_RecipientInfo, d.ori, CMS_OtherRecipientInfo, 4)
} ASN1_CHOICE_END_cb(CMS_RecipientInfo, CMS_RecipientInfo, type)
ASN1_NDEF_SEQUENCE(CMS_EnvelopedData) = {
ASN1_EMBED(CMS_EnvelopedData, version, INT32),
ASN1_IMP_OPT(CMS_EnvelopedData, originatorInfo, CMS_OriginatorInfo, 0),
ASN1_SET_OF(CMS_EnvelopedData, recipientInfos, CMS_RecipientInfo),
ASN1_SIMPLE(CMS_EnvelopedData, encryptedContentInfo, CMS_EncryptedContentInfo),
ASN1_IMP_SET_OF_OPT(CMS_EnvelopedData, unprotectedAttrs, X509_ATTRIBUTE, 1)
} ASN1_NDEF_SEQUENCE_END(CMS_EnvelopedData)
ASN1_NDEF_SEQUENCE(CMS_DigestedData) = {
ASN1_EMBED(CMS_DigestedData, version, INT32),
ASN1_SIMPLE(CMS_DigestedData, digestAlgorithm, X509_ALGOR),
ASN1_SIMPLE(CMS_DigestedData, encapContentInfo, CMS_EncapsulatedContentInfo),
ASN1_SIMPLE(CMS_DigestedData, digest, ASN1_OCTET_STRING)
} ASN1_NDEF_SEQUENCE_END(CMS_DigestedData)
ASN1_NDEF_SEQUENCE(CMS_EncryptedData) = {
ASN1_EMBED(CMS_EncryptedData, version, INT32),
ASN1_SIMPLE(CMS_EncryptedData, encryptedContentInfo, CMS_EncryptedContentInfo),
ASN1_IMP_SET_OF_OPT(CMS_EncryptedData, unprotectedAttrs, X509_ATTRIBUTE, 1)
} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedData)
/* Defined in RFC 5083 - Section 2.1. AuthEnvelopedData Type */
ASN1_NDEF_SEQUENCE(CMS_AuthEnvelopedData) = {
ASN1_EMBED(CMS_AuthEnvelopedData, version, INT32),
ASN1_IMP_OPT(CMS_AuthEnvelopedData, originatorInfo, CMS_OriginatorInfo, 0),
ASN1_SET_OF(CMS_AuthEnvelopedData, recipientInfos, CMS_RecipientInfo),
ASN1_SIMPLE(CMS_AuthEnvelopedData, authEncryptedContentInfo, CMS_EncryptedContentInfo),
ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, authAttrs, X509_ALGOR, 2),
ASN1_SIMPLE(CMS_AuthEnvelopedData, mac, ASN1_OCTET_STRING),
ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, unauthAttrs, X509_ALGOR, 3)
} ASN1_NDEF_SEQUENCE_END(CMS_AuthEnvelopedData)
ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = {
ASN1_EMBED(CMS_AuthenticatedData, version, INT32),
ASN1_IMP_OPT(CMS_AuthenticatedData, originatorInfo, CMS_OriginatorInfo, 0),
ASN1_SET_OF(CMS_AuthenticatedData, recipientInfos, CMS_RecipientInfo),
ASN1_SIMPLE(CMS_AuthenticatedData, macAlgorithm, X509_ALGOR),
ASN1_IMP(CMS_AuthenticatedData, digestAlgorithm, X509_ALGOR, 1),
ASN1_SIMPLE(CMS_AuthenticatedData, encapContentInfo, CMS_EncapsulatedContentInfo),
ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ALGOR, 2),
ASN1_SIMPLE(CMS_AuthenticatedData, mac, ASN1_OCTET_STRING),
ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ALGOR, 3)
} static_ASN1_NDEF_SEQUENCE_END(CMS_AuthenticatedData)
ASN1_NDEF_SEQUENCE(CMS_CompressedData) = {
ASN1_EMBED(CMS_CompressedData, version, INT32),
ASN1_SIMPLE(CMS_CompressedData, compressionAlgorithm, X509_ALGOR),
ASN1_SIMPLE(CMS_CompressedData, encapContentInfo, CMS_EncapsulatedContentInfo),
} ASN1_NDEF_SEQUENCE_END(CMS_CompressedData)
/* This is the ANY DEFINED BY table for the top level ContentInfo structure */
ASN1_ADB_TEMPLATE(cms_default) = ASN1_EXP(CMS_ContentInfo, d.other, ASN1_ANY, 0);
ASN1_ADB(CMS_ContentInfo) = {
ADB_ENTRY(NID_pkcs7_data, ASN1_NDEF_EXP(CMS_ContentInfo, d.data, ASN1_OCTET_STRING_NDEF, 0)),
ADB_ENTRY(NID_pkcs7_signed, ASN1_NDEF_EXP(CMS_ContentInfo, d.signedData, CMS_SignedData, 0)),
ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP(CMS_ContentInfo, d.envelopedData, CMS_EnvelopedData, 0)),
ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP(CMS_ContentInfo, d.digestedData, CMS_DigestedData, 0)),
ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP(CMS_ContentInfo, d.encryptedData, CMS_EncryptedData, 0)),
ADB_ENTRY(NID_id_smime_ct_authEnvelopedData, ASN1_NDEF_EXP(CMS_ContentInfo, d.authEnvelopedData, CMS_AuthEnvelopedData, 0)),
ADB_ENTRY(NID_id_smime_ct_authData, ASN1_NDEF_EXP(CMS_ContentInfo, d.authenticatedData, CMS_AuthenticatedData, 0)),
ADB_ENTRY(NID_id_smime_ct_compressedData, ASN1_NDEF_EXP(CMS_ContentInfo, d.compressedData, CMS_CompressedData, 0)),
} ASN1_ADB_END(CMS_ContentInfo, 0, contentType, 0, &cms_default_tt, NULL);
/* CMS streaming support */
static int cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
ASN1_STREAM_ARG *sarg = exarg;
CMS_ContentInfo *cms = NULL;
if (pval)
cms = (CMS_ContentInfo *)*pval;
else
return 1;
switch (operation) {
case ASN1_OP_STREAM_PRE:
if (CMS_stream(&sarg->boundary, cms) <= 0)
return 0;
/* fall thru */
case ASN1_OP_DETACHED_PRE:
sarg->ndef_bio = CMS_dataInit(cms, sarg->out);
if (!sarg->ndef_bio)
return 0;
break;
case ASN1_OP_STREAM_POST:
case ASN1_OP_DETACHED_POST:
if (CMS_dataFinal(cms, sarg->ndef_bio) <= 0)
return 0;
break;
+ case ASN1_OP_FREE_POST:
+ OPENSSL_free(cms->ctx.propq);
+ break;
+
}
return 1;
}
ASN1_NDEF_SEQUENCE_cb(CMS_ContentInfo, cms_cb) = {
ASN1_SIMPLE(CMS_ContentInfo, contentType, ASN1_OBJECT),
ASN1_ADB_OBJECT(CMS_ContentInfo)
} ASN1_NDEF_SEQUENCE_END_cb(CMS_ContentInfo, CMS_ContentInfo)
/* Specials for signed attributes */
/*
* When signing attributes we want to reorder them to match the sorted
* encoding.
*/
ASN1_ITEM_TEMPLATE(CMS_Attributes_Sign) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, CMS_ATTRIBUTES, X509_ATTRIBUTE)
ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Sign)
/*
* When verifying attributes we need to use the received order. So we use
* SEQUENCE OF and tag it to SET OF
*/
ASN1_ITEM_TEMPLATE(CMS_Attributes_Verify) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL,
V_ASN1_SET, CMS_ATTRIBUTES, X509_ATTRIBUTE)
ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Verify)
ASN1_CHOICE(CMS_ReceiptsFrom) = {
ASN1_IMP_EMBED(CMS_ReceiptsFrom, d.allOrFirstTier, INT32, 0),
ASN1_IMP_SEQUENCE_OF(CMS_ReceiptsFrom, d.receiptList, GENERAL_NAMES, 1)
} static_ASN1_CHOICE_END(CMS_ReceiptsFrom)
ASN1_SEQUENCE(CMS_ReceiptRequest) = {
ASN1_SIMPLE(CMS_ReceiptRequest, signedContentIdentifier, ASN1_OCTET_STRING),
ASN1_SIMPLE(CMS_ReceiptRequest, receiptsFrom, CMS_ReceiptsFrom),
ASN1_SEQUENCE_OF(CMS_ReceiptRequest, receiptsTo, GENERAL_NAMES)
} ASN1_SEQUENCE_END(CMS_ReceiptRequest)
ASN1_SEQUENCE(CMS_Receipt) = {
ASN1_EMBED(CMS_Receipt, version, INT32),
ASN1_SIMPLE(CMS_Receipt, contentType, ASN1_OBJECT),
ASN1_SIMPLE(CMS_Receipt, signedContentIdentifier, ASN1_OCTET_STRING),
ASN1_SIMPLE(CMS_Receipt, originatorSignatureValue, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(CMS_Receipt)
/*
* Utilities to encode the CMS_SharedInfo structure used during key
* derivation.
*/
typedef struct {
X509_ALGOR *keyInfo;
ASN1_OCTET_STRING *entityUInfo;
ASN1_OCTET_STRING *suppPubInfo;
} CMS_SharedInfo;
ASN1_SEQUENCE(CMS_SharedInfo) = {
ASN1_SIMPLE(CMS_SharedInfo, keyInfo, X509_ALGOR),
ASN1_EXP_OPT(CMS_SharedInfo, entityUInfo, ASN1_OCTET_STRING, 0),
ASN1_EXP_OPT(CMS_SharedInfo, suppPubInfo, ASN1_OCTET_STRING, 2),
} static_ASN1_SEQUENCE_END(CMS_SharedInfo)
int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
ASN1_OCTET_STRING *ukm, int keylen)
{
union {
CMS_SharedInfo *pecsi;
ASN1_VALUE *a;
} intsi = {
NULL
};
ASN1_OCTET_STRING oklen;
unsigned char kl[4];
CMS_SharedInfo ecsi;
keylen <<= 3;
kl[0] = (keylen >> 24) & 0xff;
kl[1] = (keylen >> 16) & 0xff;
kl[2] = (keylen >> 8) & 0xff;
kl[3] = keylen & 0xff;
oklen.length = 4;
oklen.data = kl;
oklen.type = V_ASN1_OCTET_STRING;
oklen.flags = 0;
ecsi.keyInfo = kekalg;
ecsi.entityUInfo = ukm;
ecsi.suppPubInfo = &oklen;
intsi.pecsi = &ecsi;
return ASN1_item_i2d(intsi.a, pder, ASN1_ITEM_rptr(CMS_SharedInfo));
}
diff --git a/crypto/openssl/crypto/cms/cms_dh.c b/crypto/openssl/crypto/cms/cms_dh.c
index 2f54ed2673a9..3f931d6e6fef 100644
--- a/crypto/openssl/crypto/cms/cms_dh.c
+++ b/crypto/openssl/crypto/cms/cms_dh.c
@@ -1,343 +1,343 @@
/*
* Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <openssl/cms.h>
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/core_names.h>
#include "internal/sizes.h"
#include "crypto/evp.h"
#include "cms_local.h"
static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
{
const ASN1_OBJECT *aoid;
int atype;
const void *aval;
ASN1_INTEGER *public_key = NULL;
int rv = 0;
EVP_PKEY *pkpeer = NULL, *pk = NULL;
BIGNUM *bnpub = NULL;
const unsigned char *p;
unsigned char *buf = NULL;
int plen;
X509_ALGOR_get0(&aoid, &atype, &aval, alg);
if (OBJ_obj2nid(aoid) != NID_dhpublicnumber)
goto err;
/* Only absent parameters allowed in RFC XXXX */
- if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
+ if (atype != V_ASN1_UNDEF && atype != V_ASN1_NULL)
goto err;
pk = EVP_PKEY_CTX_get0_pkey(pctx);
if (pk == NULL || !EVP_PKEY_is_a(pk, "DHX"))
goto err;
/* Get public key */
plen = ASN1_STRING_length(pubkey);
p = ASN1_STRING_get0_data(pubkey);
if (p == NULL || plen == 0)
goto err;
if ((public_key = d2i_ASN1_INTEGER(NULL, &p, plen)) == NULL)
goto err;
/*
* Pad to full p parameter size as that is checked by
* EVP_PKEY_set1_encoded_public_key()
*/
plen = EVP_PKEY_get_size(pk);
if ((bnpub = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL)
goto err;
if ((buf = OPENSSL_malloc(plen)) == NULL)
goto err;
if (BN_bn2binpad(bnpub, buf, plen) < 0)
goto err;
pkpeer = EVP_PKEY_new();
if (pkpeer == NULL
|| !EVP_PKEY_copy_parameters(pkpeer, pk)
|| !EVP_PKEY_set1_encoded_public_key(pkpeer, buf, plen))
goto err;
if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
rv = 1;
err:
ASN1_INTEGER_free(public_key);
BN_free(bnpub);
OPENSSL_free(buf);
EVP_PKEY_free(pkpeer);
return rv;
}
static int dh_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 *dukm = NULL;
size_t dukmlen = 0;
int keylen, plen;
EVP_CIPHER *kekcipher = NULL;
EVP_CIPHER_CTX *kekctx;
char name[OSSL_MAX_NAME_SIZE];
if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
goto err;
/*
* For DH we only have one OID permissible. If ever any more get defined
* we will need something cleverer.
*/
if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) {
ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR);
goto err;
}
if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0
|| EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
goto err;
if (alg->parameter->type != V_ASN1_SEQUENCE)
goto err;
p = alg->parameter->value.sequence->data;
plen = alg->parameter->value.sequence->length;
kekalg = d2i_X509_ALGOR(NULL, &p, plen);
if (kekalg == NULL)
goto err;
kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
if (kekctx == NULL)
goto err;
if (OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0) <= 0)
goto err;
kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery);
if (kekcipher == NULL
|| EVP_CIPHER_get_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_get_key_length(kekctx);
if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
goto err;
/* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
OBJ_nid2obj(EVP_CIPHER_get_type(kekcipher)))
<= 0)
goto err;
if (ukm != NULL) {
dukmlen = ASN1_STRING_length(ukm);
dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
if (dukm == NULL)
goto err;
}
if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
goto err;
dukm = NULL;
rv = 1;
err:
X509_ALGOR_free(kekalg);
EVP_CIPHER_free(kekcipher);
OPENSSL_free(dukm);
return rv;
}
static int dh_cms_decrypt(CMS_RecipientInfo *ri)
{
EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (pctx == NULL)
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 == NULL || pubkey == NULL)
return 0;
if (!dh_cms_set_peerkey(pctx, alg, pubkey)) {
ERR_raise(ERR_LIB_CMS, CMS_R_PEER_KEY_ERROR);
return 0;
}
}
/* Set DH derivation parameters and initialise unwrap context */
if (!dh_cms_set_shared_info(pctx, ri)) {
ERR_raise(ERR_LIB_CMS, CMS_R_SHARED_INFO_ERROR);
return 0;
}
return 1;
}
static int dh_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, *dukm = NULL;
int penclen;
size_t dukmlen = 0;
int rv = 0;
int kdf_type, wrap_nid;
const EVP_MD *kdf_md;
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (pctx == NULL)
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;
/* Is everything uninitialised? */
X509_ALGOR_get0(&aoid, NULL, NULL, talg);
if (aoid == OBJ_nid2obj(NID_undef)) {
BIGNUM *bn_pub_key = NULL;
ASN1_INTEGER *pubk;
if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &bn_pub_key))
goto err;
pubk = BN_to_ASN1_INTEGER(bn_pub_key, NULL);
BN_free(bn_pub_key);
if (pubk == NULL)
goto err;
/* Set the key */
penclen = i2d_ASN1_INTEGER(pubk, &penc);
ASN1_INTEGER_free(pubk);
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_dhpublicnumber),
V_ASN1_UNDEF, NULL);
}
/* See if custom parameters set */
kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
if (kdf_type <= 0 || EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md) <= 0)
goto err;
if (kdf_type == EVP_PKEY_DH_KDF_NONE) {
kdf_type = EVP_PKEY_DH_KDF_X9_42;
if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
goto err;
} else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
/* Unknown KDF */
goto err;
if (kdf_md == NULL) {
/* Only SHA1 supported */
kdf_md = EVP_sha1();
if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
goto err;
} else if (EVP_MD_get_type(kdf_md) != NID_sha1)
/* Unsupported digest */
goto err;
if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
goto err;
/* Get wrap NID */
ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
wrap_nid = EVP_CIPHER_CTX_get_type(ctx);
if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
goto err;
keylen = EVP_CIPHER_CTX_get_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_dh_kdf_outlen(pctx, keylen) <= 0)
goto err;
if (ukm != NULL) {
dukmlen = ASN1_STRING_length(ukm);
dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
if (dukm == NULL)
goto err;
}
if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
goto err;
dukm = NULL;
/*
* Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
* of another AlgorithmIdentifier.
*/
penc = NULL;
penclen = i2d_X509_ALGOR(wrap_alg, &penc);
if (penclen <= 0)
goto err;
wrap_str = ASN1_STRING_new();
if (wrap_str == NULL)
goto err;
ASN1_STRING_set0(wrap_str, penc, penclen);
penc = NULL;
rv = X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
V_ASN1_SEQUENCE, wrap_str);
if (!rv)
ASN1_STRING_free(wrap_str);
err:
OPENSSL_free(penc);
X509_ALGOR_free(wrap_alg);
OPENSSL_free(dukm);
return rv;
}
int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt)
{
assert(decrypt == 0 || decrypt == 1);
if (decrypt == 1)
return dh_cms_decrypt(ri);
if (decrypt == 0)
return dh_cms_encrypt(ri);
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
diff --git a/crypto/openssl/crypto/cms/cms_env.c b/crypto/openssl/crypto/cms/cms_env.c
index 99cf1dcb396c..445a16fb771f 100644
--- a/crypto/openssl/crypto/cms/cms_env.c
+++ b/crypto/openssl/crypto/cms/cms_env.c
@@ -1,1355 +1,1346 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/asn1t.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
#include <openssl/evp.h>
#include "internal/sizes.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/x509.h"
#include "cms_local.h"
/* CMS EnvelopedData Utilities */
static void cms_env_set_version(CMS_EnvelopedData *env);
#define CMS_ENVELOPED_STANDARD 1
#define CMS_ENVELOPED_AUTH 2
static int cms_get_enveloped_type_simple(const CMS_ContentInfo *cms)
{
int nid = OBJ_obj2nid(cms->contentType);
switch (nid) {
case NID_pkcs7_enveloped:
return CMS_ENVELOPED_STANDARD;
case NID_id_smime_ct_authEnvelopedData:
return CMS_ENVELOPED_AUTH;
default:
return 0;
}
}
static int cms_get_enveloped_type(const CMS_ContentInfo *cms)
{
int ret = cms_get_enveloped_type_simple(cms);
if (ret == 0)
ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
return ret;
}
-void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf)
-{
- if (cms_get_enveloped_type_simple(cinf) != 0) {
- CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cinf);
- if (ec != NULL)
- OPENSSL_clear_free(ec->key, ec->keylen);
- }
-}
-
CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms)
{
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
return NULL;
}
return cms->d.envelopedData;
}
CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms)
{
if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_authEnvelopedData) {
ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
return NULL;
}
return cms->d.authEnvelopedData;
}
static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
{
if (cms->d.other == NULL) {
cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData);
if (cms->d.envelopedData == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
cms->d.envelopedData->version = 0;
cms->d.envelopedData->encryptedContentInfo->contentType =
OBJ_nid2obj(NID_pkcs7_data);
ASN1_OBJECT_free(cms->contentType);
cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
return cms->d.envelopedData;
}
return ossl_cms_get0_enveloped(cms);
}
static CMS_AuthEnvelopedData *
cms_auth_enveloped_data_init(CMS_ContentInfo *cms)
{
if (cms->d.other == NULL) {
cms->d.authEnvelopedData = M_ASN1_new_of(CMS_AuthEnvelopedData);
if (cms->d.authEnvelopedData == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
/* Defined in RFC 5083 - Section 2.1. "AuthEnvelopedData Type" */
cms->d.authEnvelopedData->version = 0;
cms->d.authEnvelopedData->authEncryptedContentInfo->contentType =
OBJ_nid2obj(NID_pkcs7_data);
ASN1_OBJECT_free(cms->contentType);
cms->contentType = OBJ_nid2obj(NID_id_smime_ct_authEnvelopedData);
return cms->d.authEnvelopedData;
}
return ossl_cms_get0_auth_enveloped(cms);
}
int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
{
EVP_PKEY *pkey;
int i;
if (ri->type == CMS_RECIPINFO_TRANS)
pkey = ri->d.ktri->pkey;
else if (ri->type == CMS_RECIPINFO_AGREE) {
EVP_PKEY_CTX *pctx = ri->d.kari->pctx;
if (pctx == NULL)
return 0;
pkey = EVP_PKEY_CTX_get0_pkey(pctx);
if (pkey == NULL)
return 0;
} else
return 0;
if (EVP_PKEY_is_a(pkey, "DHX") || EVP_PKEY_is_a(pkey, "DH"))
return ossl_cms_dh_envelope(ri, cmd);
else if (EVP_PKEY_is_a(pkey, "EC"))
return ossl_cms_ecdh_envelope(ri, cmd);
else if (EVP_PKEY_is_a(pkey, "RSA"))
return ossl_cms_rsa_envelope(ri, cmd);
/* Something else? We'll give engines etc a chance to handle this */
if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
return 1;
i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri);
if (i == -2) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
if (i <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
return 0;
}
return 1;
}
CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms)
{
switch (cms_get_enveloped_type(cms)) {
case CMS_ENVELOPED_STANDARD:
return cms->d.envelopedData == NULL ? NULL
: cms->d.envelopedData->encryptedContentInfo;
case CMS_ENVELOPED_AUTH:
return cms->d.authEnvelopedData == NULL ? NULL
: cms->d.authEnvelopedData->authEncryptedContentInfo;
default:
return NULL;
}
}
STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
{
switch (cms_get_enveloped_type(cms)) {
case CMS_ENVELOPED_STANDARD:
return cms->d.envelopedData->recipientInfos;
case CMS_ENVELOPED_AUTH:
return cms->d.authEnvelopedData->recipientInfos;
default:
return NULL;
}
}
void ossl_cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms)
{
int i;
CMS_RecipientInfo *ri;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
STACK_OF(CMS_RecipientInfo) *rinfos = CMS_get0_RecipientInfos(cms);
for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
ri = sk_CMS_RecipientInfo_value(rinfos, i);
if (ri != NULL) {
switch (ri->type) {
case CMS_RECIPINFO_AGREE:
ri->d.kari->cms_ctx = ctx;
break;
case CMS_RECIPINFO_TRANS:
ri->d.ktri->cms_ctx = ctx;
ossl_x509_set0_libctx(ri->d.ktri->recip,
ossl_cms_ctx_get0_libctx(ctx),
ossl_cms_ctx_get0_propq(ctx));
break;
case CMS_RECIPINFO_KEK:
ri->d.kekri->cms_ctx = ctx;
break;
case CMS_RECIPINFO_PASS:
ri->d.pwri->cms_ctx = ctx;
break;
default:
break;
}
}
}
}
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
{
return ri->type;
}
EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
{
if (ri->type == CMS_RECIPINFO_TRANS)
return ri->d.ktri->pctx;
else if (ri->type == CMS_RECIPINFO_AGREE)
return ri->d.kari->pctx;
return NULL;
}
CMS_ContentInfo *CMS_EnvelopedData_create_ex(const EVP_CIPHER *cipher,
OSSL_LIB_CTX *libctx,
const char *propq)
{
CMS_ContentInfo *cms;
CMS_EnvelopedData *env;
cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL)
goto merr;
env = cms_enveloped_data_init(cms);
if (env == NULL)
goto merr;
if (!ossl_cms_EncryptedContent_init(env->encryptedContentInfo, cipher, NULL,
0, ossl_cms_get0_cmsctx(cms)))
goto merr;
return cms;
merr:
CMS_ContentInfo_free(cms);
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
{
return CMS_EnvelopedData_create_ex(cipher, NULL, NULL);
}
CMS_ContentInfo *
CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx,
const char *propq)
{
CMS_ContentInfo *cms;
CMS_AuthEnvelopedData *aenv;
cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL)
goto merr;
aenv = cms_auth_enveloped_data_init(cms);
if (aenv == NULL)
goto merr;
if (!ossl_cms_EncryptedContent_init(aenv->authEncryptedContentInfo,
cipher, NULL, 0,
ossl_cms_get0_cmsctx(cms)))
goto merr;
return cms;
merr:
CMS_ContentInfo_free(cms);
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
CMS_ContentInfo *CMS_AuthEnvelopedData_create(const EVP_CIPHER *cipher)
{
return CMS_AuthEnvelopedData_create_ex(cipher, NULL, NULL);
}
/* Key Transport Recipient Info (KTRI) routines */
/* Initialise a ktri based on passed certificate and key */
static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
EVP_PKEY *pk, unsigned int flags,
const CMS_CTX *ctx)
{
CMS_KeyTransRecipientInfo *ktri;
int idtype;
ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
if (!ri->d.ktri)
return 0;
ri->type = CMS_RECIPINFO_TRANS;
ktri = ri->d.ktri;
ktri->cms_ctx = ctx;
if (flags & CMS_USE_KEYID) {
ktri->version = 2;
idtype = CMS_RECIPINFO_KEYIDENTIFIER;
} else {
ktri->version = 0;
idtype = CMS_RECIPINFO_ISSUER_SERIAL;
}
/*
* Not a typo: RecipientIdentifier and SignerIdentifier are the same
* structure.
*/
if (!ossl_cms_set1_SignerIdentifier(ktri->rid, recip, idtype, ctx))
return 0;
X509_up_ref(recip);
EVP_PKEY_up_ref(pk);
ktri->pkey = pk;
ktri->recip = recip;
if (flags & CMS_KEY_PARAM) {
ktri->pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
ktri->pkey,
ossl_cms_ctx_get0_propq(ctx));
if (ktri->pctx == NULL)
return 0;
if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
return 0;
} else if (!ossl_cms_env_asn1_ctrl(ri, 0))
return 0;
return 1;
}
/*
* Add a recipient certificate using appropriate type of RecipientInfo
*/
CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
EVP_PKEY *originatorPrivKey,
X509 *originator, unsigned int flags)
{
CMS_RecipientInfo *ri = NULL;
STACK_OF(CMS_RecipientInfo) *ris;
EVP_PKEY *pk = NULL;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
ris = CMS_get0_RecipientInfos(cms);
if (ris == NULL)
goto err;
/* Initialize recipient info */
ri = M_ASN1_new_of(CMS_RecipientInfo);
if (ri == NULL)
goto merr;
pk = X509_get0_pubkey(recip);
if (pk == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_GETTING_PUBLIC_KEY);
goto err;
}
switch (ossl_cms_pkey_get_ri_type(pk)) {
case CMS_RECIPINFO_TRANS:
if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags, ctx))
goto err;
break;
case CMS_RECIPINFO_AGREE:
if (!ossl_cms_RecipientInfo_kari_init(ri, recip, pk, originator,
originatorPrivKey, flags, ctx))
goto err;
break;
default:
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
goto err;
}
if (!sk_CMS_RecipientInfo_push(ris, ri))
goto merr;
return ri;
merr:
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
M_ASN1_free_of(ri, CMS_RecipientInfo);
return NULL;
}
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip,
unsigned int flags)
{
return CMS_add1_recipient(cms, recip, NULL, NULL, flags);
}
int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
EVP_PKEY **pk, X509 **recip,
X509_ALGOR **palg)
{
CMS_KeyTransRecipientInfo *ktri;
if (ri->type != CMS_RECIPINFO_TRANS) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return 0;
}
ktri = ri->d.ktri;
if (pk)
*pk = ktri->pkey;
if (recip)
*recip = ktri->recip;
if (palg)
*palg = ktri->keyEncryptionAlgorithm;
return 1;
}
int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
ASN1_OCTET_STRING **keyid,
X509_NAME **issuer,
ASN1_INTEGER **sno)
{
CMS_KeyTransRecipientInfo *ktri;
if (ri->type != CMS_RECIPINFO_TRANS) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return 0;
}
ktri = ri->d.ktri;
return ossl_cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer,
sno);
}
int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
{
if (ri->type != CMS_RECIPINFO_TRANS) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return -2;
}
return ossl_cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
}
int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
{
if (ri->type != CMS_RECIPINFO_TRANS) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return 0;
}
EVP_PKEY_free(ri->d.ktri->pkey);
ri->d.ktri->pkey = pkey;
return 1;
}
/* Encrypt content key in key transport recipient info */
static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
CMS_RecipientInfo *ri)
{
CMS_KeyTransRecipientInfo *ktri;
CMS_EncryptedContentInfo *ec;
EVP_PKEY_CTX *pctx;
unsigned char *ek = NULL;
size_t eklen;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
int ret = 0;
if (ri->type != CMS_RECIPINFO_TRANS) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return 0;
}
ktri = ri->d.ktri;
ec = ossl_cms_get0_env_enc_content(cms);
pctx = ktri->pctx;
if (pctx) {
if (!ossl_cms_env_asn1_ctrl(ri, 0))
goto err;
} else {
pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
ktri->pkey,
ossl_cms_ctx_get0_propq(ctx));
if (pctx == NULL)
return 0;
if (EVP_PKEY_encrypt_init(pctx) <= 0)
goto err;
}
if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
goto err;
ek = OPENSSL_malloc(eklen);
if (ek == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
goto err;
ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
ek = NULL;
ret = 1;
err:
EVP_PKEY_CTX_free(pctx);
ktri->pctx = NULL;
OPENSSL_free(ek);
return ret;
}
/* Decrypt content key from KTRI */
static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
CMS_RecipientInfo *ri)
{
CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
EVP_PKEY *pkey = ktri->pkey;
unsigned char *ek = NULL;
size_t eklen;
int ret = 0;
size_t fixlen = 0;
const EVP_CIPHER *cipher = NULL;
EVP_CIPHER *fetched_cipher = NULL;
CMS_EncryptedContentInfo *ec;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
const char *propq = ossl_cms_ctx_get0_propq(ctx);
ec = ossl_cms_get0_env_enc_content(cms);
if (ktri->pkey == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY);
return 0;
}
if (cms->d.envelopedData->encryptedContentInfo->havenocert
&& !cms->d.envelopedData->encryptedContentInfo->debug) {
X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
char name[OSSL_MAX_NAME_SIZE];
OBJ_obj2txt(name, sizeof(name), calg->algorithm, 0);
(void)ERR_set_mark();
fetched_cipher = EVP_CIPHER_fetch(libctx, name, propq);
if (fetched_cipher != NULL)
cipher = fetched_cipher;
else
cipher = EVP_get_cipherbyobj(calg->algorithm);
if (cipher == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER);
return 0;
}
(void)ERR_pop_to_mark();
fixlen = EVP_CIPHER_get_key_length(cipher);
EVP_CIPHER_free(fetched_cipher);
}
ktri->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
if (ktri->pctx == NULL)
goto err;
if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
goto err;
if (!ossl_cms_env_asn1_ctrl(ri, 1))
goto err;
if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen,
ktri->encryptedKey->data,
ktri->encryptedKey->length) <= 0)
goto err;
ek = OPENSSL_malloc(eklen);
if (ek == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen,
ktri->encryptedKey->data,
ktri->encryptedKey->length) <= 0
|| eklen == 0
|| (fixlen != 0 && eklen != fixlen)) {
ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
goto err;
}
ret = 1;
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = ek;
ec->keylen = eklen;
err:
EVP_PKEY_CTX_free(ktri->pctx);
ktri->pctx = NULL;
if (!ret)
OPENSSL_free(ek);
return ret;
}
/* Key Encrypted Key (KEK) RecipientInfo routines */
int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
const unsigned char *id, size_t idlen)
{
ASN1_OCTET_STRING tmp_os;
CMS_KEKRecipientInfo *kekri;
if (ri->type != CMS_RECIPINFO_KEK) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
return -2;
}
kekri = ri->d.kekri;
tmp_os.type = V_ASN1_OCTET_STRING;
tmp_os.flags = 0;
tmp_os.data = (unsigned char *)id;
tmp_os.length = (int)idlen;
return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
}
/* For now hard code AES key wrap info */
static size_t aes_wrap_keylen(int nid)
{
switch (nid) {
case NID_id_aes128_wrap:
return 16;
case NID_id_aes192_wrap:
return 24;
case NID_id_aes256_wrap:
return 32;
default:
return 0;
}
}
CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
unsigned char *key, size_t keylen,
unsigned char *id, size_t idlen,
ASN1_GENERALIZEDTIME *date,
ASN1_OBJECT *otherTypeId,
ASN1_TYPE *otherType)
{
CMS_RecipientInfo *ri = NULL;
CMS_KEKRecipientInfo *kekri;
STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
if (ris == NULL)
goto err;
if (nid == NID_undef) {
switch (keylen) {
case 16:
nid = NID_id_aes128_wrap;
break;
case 24:
nid = NID_id_aes192_wrap;
break;
case 32:
nid = NID_id_aes256_wrap;
break;
default:
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
}
} else {
size_t exp_keylen = aes_wrap_keylen(nid);
if (!exp_keylen) {
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEK_ALGORITHM);
goto err;
}
if (keylen != exp_keylen) {
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
}
}
/* Initialize recipient info */
ri = M_ASN1_new_of(CMS_RecipientInfo);
if (!ri)
goto merr;
ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);
if (!ri->d.kekri)
goto merr;
ri->type = CMS_RECIPINFO_KEK;
kekri = ri->d.kekri;
if (otherTypeId) {
kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);
if (kekri->kekid->other == NULL)
goto merr;
}
if (!sk_CMS_RecipientInfo_push(ris, ri))
goto merr;
/* After this point no calls can fail */
kekri->version = 4;
kekri->key = key;
kekri->keylen = keylen;
ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
kekri->kekid->date = date;
if (kekri->kekid->other) {
kekri->kekid->other->keyAttrId = otherTypeId;
kekri->kekid->other->keyAttr = otherType;
}
X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
return ri;
merr:
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
M_ASN1_free_of(ri, CMS_RecipientInfo);
return NULL;
}
int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
X509_ALGOR **palg,
ASN1_OCTET_STRING **pid,
ASN1_GENERALIZEDTIME **pdate,
ASN1_OBJECT **potherid,
ASN1_TYPE **pothertype)
{
CMS_KEKIdentifier *rkid;
if (ri->type != CMS_RECIPINFO_KEK) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
return 0;
}
rkid = ri->d.kekri->kekid;
if (palg)
*palg = ri->d.kekri->keyEncryptionAlgorithm;
if (pid)
*pid = rkid->keyIdentifier;
if (pdate)
*pdate = rkid->date;
if (potherid) {
if (rkid->other)
*potherid = rkid->other->keyAttrId;
else
*potherid = NULL;
}
if (pothertype) {
if (rkid->other)
*pothertype = rkid->other->keyAttr;
else
*pothertype = NULL;
}
return 1;
}
int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
unsigned char *key, size_t keylen)
{
CMS_KEKRecipientInfo *kekri;
if (ri->type != CMS_RECIPINFO_KEK) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
return 0;
}
kekri = ri->d.kekri;
kekri->key = key;
kekri->keylen = keylen;
return 1;
}
static EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen, const CMS_CTX *ctx)
{
const char *alg = NULL;
switch(keylen) {
case 16:
alg = "AES-128-WRAP";
break;
case 24:
alg = "AES-192-WRAP";
break;
case 32:
alg = "AES-256-WRAP";
break;
default:
return NULL;
}
return EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(ctx), alg,
ossl_cms_ctx_get0_propq(ctx));
}
/* Encrypt content key in KEK recipient info */
static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
CMS_RecipientInfo *ri)
{
CMS_EncryptedContentInfo *ec;
CMS_KEKRecipientInfo *kekri;
unsigned char *wkey = NULL;
int wkeylen;
int r = 0;
EVP_CIPHER *cipher = NULL;
int outlen = 0;
EVP_CIPHER_CTX *ctx = NULL;
const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
ec = ossl_cms_get0_env_enc_content(cms);
if (ec == NULL)
return 0;
kekri = ri->d.kekri;
if (kekri->key == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY);
return 0;
}
cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
if (cipher == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
}
/* 8 byte prefix for AES wrap ciphers */
wkey = OPENSSL_malloc(ec->keylen + 8);
if (wkey == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
if (!EVP_EncryptInit_ex(ctx, cipher, NULL, kekri->key, NULL)
|| !EVP_EncryptUpdate(ctx, wkey, &wkeylen, ec->key, ec->keylen)
|| !EVP_EncryptFinal_ex(ctx, wkey + wkeylen, &outlen)) {
ERR_raise(ERR_LIB_CMS, CMS_R_WRAP_ERROR);
goto err;
}
wkeylen += outlen;
if (!ossl_assert((size_t)wkeylen == ec->keylen + 8)) {
ERR_raise(ERR_LIB_CMS, CMS_R_WRAP_ERROR);
goto err;
}
ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);
r = 1;
err:
EVP_CIPHER_free(cipher);
if (!r)
OPENSSL_free(wkey);
EVP_CIPHER_CTX_free(ctx);
return r;
}
/* Decrypt content key in KEK recipient info */
static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
CMS_RecipientInfo *ri)
{
CMS_EncryptedContentInfo *ec;
CMS_KEKRecipientInfo *kekri;
unsigned char *ukey = NULL;
int ukeylen;
int r = 0, wrap_nid;
EVP_CIPHER *cipher = NULL;
int outlen = 0;
EVP_CIPHER_CTX *ctx = NULL;
const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
ec = ossl_cms_get0_env_enc_content(cms);
if (ec == NULL)
return 0;
kekri = ri->d.kekri;
if (!kekri->key) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY);
return 0;
}
wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
if (aes_wrap_keylen(wrap_nid) != kekri->keylen) {
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
return 0;
}
/* If encrypted key length is invalid don't bother */
if (kekri->encryptedKey->length < 16) {
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
goto err;
}
cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
if (cipher == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
}
ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8);
if (ukey == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_DecryptInit_ex(ctx, cipher, NULL, kekri->key, NULL)
|| !EVP_DecryptUpdate(ctx, ukey, &ukeylen,
kekri->encryptedKey->data,
kekri->encryptedKey->length)
|| !EVP_DecryptFinal_ex(ctx, ukey + ukeylen, &outlen)) {
ERR_raise(ERR_LIB_CMS, CMS_R_UNWRAP_ERROR);
goto err;
}
ukeylen += outlen;
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = ukey;
ec->keylen = ukeylen;
r = 1;
err:
EVP_CIPHER_free(cipher);
if (!r)
OPENSSL_free(ukey);
EVP_CIPHER_CTX_free(ctx);
return r;
}
int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
{
switch (ri->type) {
case CMS_RECIPINFO_TRANS:
return cms_RecipientInfo_ktri_decrypt(cms, ri);
case CMS_RECIPINFO_KEK:
return cms_RecipientInfo_kekri_decrypt(cms, ri);
case CMS_RECIPINFO_PASS:
return ossl_cms_RecipientInfo_pwri_crypt(cms, ri, 0);
default:
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE);
return 0;
}
}
int CMS_RecipientInfo_encrypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
{
switch (ri->type) {
case CMS_RECIPINFO_TRANS:
return cms_RecipientInfo_ktri_encrypt(cms, ri);
case CMS_RECIPINFO_AGREE:
return ossl_cms_RecipientInfo_kari_encrypt(cms, ri);
case CMS_RECIPINFO_KEK:
return cms_RecipientInfo_kekri_encrypt(cms, ri);
case CMS_RECIPINFO_PASS:
return ossl_cms_RecipientInfo_pwri_crypt(cms, ri, 1);
default:
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
return 0;
}
}
/* Check structures and fixup version numbers (if necessary) */
static void cms_env_set_originfo_version(CMS_EnvelopedData *env)
{
CMS_OriginatorInfo *org = env->originatorInfo;
int i;
if (org == NULL)
return;
for (i = 0; i < sk_CMS_CertificateChoices_num(org->certificates); i++) {
CMS_CertificateChoices *cch;
cch = sk_CMS_CertificateChoices_value(org->certificates, i);
if (cch->type == CMS_CERTCHOICE_OTHER) {
env->version = 4;
return;
} else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
if (env->version < 3)
env->version = 3;
}
}
for (i = 0; i < sk_CMS_RevocationInfoChoice_num(org->crls); i++) {
CMS_RevocationInfoChoice *rch;
rch = sk_CMS_RevocationInfoChoice_value(org->crls, i);
if (rch->type == CMS_REVCHOICE_OTHER) {
env->version = 4;
return;
}
}
}
static void cms_env_set_version(CMS_EnvelopedData *env)
{
int i;
CMS_RecipientInfo *ri;
/*
* Can't set version higher than 4 so if 4 or more already nothing to do.
*/
if (env->version >= 4)
return;
cms_env_set_originfo_version(env);
if (env->version >= 3)
return;
for (i = 0; i < sk_CMS_RecipientInfo_num(env->recipientInfos); i++) {
ri = sk_CMS_RecipientInfo_value(env->recipientInfos, i);
if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER) {
env->version = 3;
return;
} else if (ri->type != CMS_RECIPINFO_TRANS
|| ri->d.ktri->version != 0) {
env->version = 2;
}
}
if (env->originatorInfo || env->unprotectedAttrs)
env->version = 2;
if (env->version == 2)
return;
env->version = 0;
}
static int cms_env_encrypt_content_key(const CMS_ContentInfo *cms,
STACK_OF(CMS_RecipientInfo) *ris)
{
int i;
CMS_RecipientInfo *ri;
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
ri = sk_CMS_RecipientInfo_value(ris, i);
if (CMS_RecipientInfo_encrypt(cms, ri) <= 0)
return -1;
}
return 1;
}
static void cms_env_clear_ec(CMS_EncryptedContentInfo *ec)
{
ec->cipher = NULL;
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = NULL;
ec->keylen = 0;
}
static BIO *cms_EnvelopedData_Decryption_init_bio(CMS_ContentInfo *cms)
{
CMS_EncryptedContentInfo *ec = cms->d.envelopedData->encryptedContentInfo;
BIO *contentBio = ossl_cms_EncryptedContent_init_bio(ec,
ossl_cms_get0_cmsctx(cms));
EVP_CIPHER_CTX *ctx = NULL;
if (contentBio == NULL)
return NULL;
BIO_get_cipher_ctx(contentBio, &ctx);
if (ctx == NULL) {
BIO_free(contentBio);
return NULL;
}
/*
* If the selected cipher supports unprotected attributes,
* deal with it using special ctrl function
*/
if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
& EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0
&& EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED, 0,
cms->d.envelopedData->unprotectedAttrs) <= 0) {
BIO_free(contentBio);
return NULL;
}
return contentBio;
}
static BIO *cms_EnvelopedData_Encryption_init_bio(CMS_ContentInfo *cms)
{
CMS_EncryptedContentInfo *ec;
STACK_OF(CMS_RecipientInfo) *rinfos;
int ok = 0;
BIO *ret;
CMS_EnvelopedData *env = cms->d.envelopedData;
/* Get BIO first to set up key */
ec = env->encryptedContentInfo;
ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms));
/* If error end of processing */
if (!ret)
return ret;
/* Now encrypt content key according to each RecipientInfo type */
rinfos = env->recipientInfos;
if (cms_env_encrypt_content_key(cms, rinfos) < 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_SETTING_RECIPIENTINFO);
goto err;
}
/* And finally set the version */
cms_env_set_version(env);
ok = 1;
err:
cms_env_clear_ec(ec);
if (ok)
return ret;
BIO_free(ret);
return NULL;
}
BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
{
if (cms->d.envelopedData->encryptedContentInfo->cipher != NULL) {
/* If cipher is set it's encryption */
return cms_EnvelopedData_Encryption_init_bio(cms);
}
/* If cipher is not set it's decryption */
return cms_EnvelopedData_Decryption_init_bio(cms);
}
BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms)
{
CMS_EncryptedContentInfo *ec;
STACK_OF(CMS_RecipientInfo) *rinfos;
int ok = 0;
BIO *ret;
CMS_AuthEnvelopedData *aenv = cms->d.authEnvelopedData;
/* Get BIO first to set up key */
ec = aenv->authEncryptedContentInfo;
/* Set tag for decryption */
if (ec->cipher == NULL) {
ec->tag = aenv->mac->data;
ec->taglen = aenv->mac->length;
}
ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms));
/* If error or no cipher end of processing */
if (ret == NULL || ec->cipher == NULL)
return ret;
/* Now encrypt content key according to each RecipientInfo type */
rinfos = aenv->recipientInfos;
if (cms_env_encrypt_content_key(cms, rinfos) < 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_SETTING_RECIPIENTINFO);
goto err;
}
/* And finally set the version */
aenv->version = 0;
ok = 1;
err:
cms_env_clear_ec(ec);
if (ok)
return ret;
BIO_free(ret);
return NULL;
}
int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
{
CMS_EnvelopedData *env = NULL;
EVP_CIPHER_CTX *ctx = NULL;
BIO *mbio = BIO_find_type(chain, BIO_TYPE_CIPHER);
env = ossl_cms_get0_enveloped(cms);
if (env == NULL)
return 0;
if (mbio == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND);
return 0;
}
BIO_get_cipher_ctx(mbio, &ctx);
/*
* If the selected cipher supports unprotected attributes,
* deal with it using special ctrl function
*/
if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
& EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
if (env->unprotectedAttrs == NULL)
env->unprotectedAttrs = sk_X509_ATTRIBUTE_new_null();
if (env->unprotectedAttrs == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED,
1, env->unprotectedAttrs) <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
return 0;
}
}
cms_env_set_version(cms->d.envelopedData);
return 1;
}
int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio)
{
EVP_CIPHER_CTX *ctx;
unsigned char *tag = NULL;
int taglen, ok = 0;
BIO_get_cipher_ctx(cmsbio, &ctx);
/*
* The tag is set only for encryption. There is nothing to do for
* decryption.
*/
if (!EVP_CIPHER_CTX_is_encrypting(ctx))
return 1;
taglen = EVP_CIPHER_CTX_get_tag_length(ctx);
if (taglen <= 0
|| (tag = OPENSSL_malloc(taglen)) == NULL
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen,
tag) <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_GET_TAG);
goto err;
}
if (!ASN1_OCTET_STRING_set(cms->d.authEnvelopedData->mac, tag, taglen))
goto err;
ok = 1;
err:
OPENSSL_free(tag);
return ok;
}
/*
* Get RecipientInfo type (if any) supported by a key (public or private). To
* retain compatibility with previous behaviour if the ctrl value isn't
* supported we assume key transport.
*/
int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk)
{
/* Check types that we know about */
if (EVP_PKEY_is_a(pk, "DH"))
return CMS_RECIPINFO_AGREE;
else if (EVP_PKEY_is_a(pk, "DHX"))
return CMS_RECIPINFO_AGREE;
else if (EVP_PKEY_is_a(pk, "DSA"))
return CMS_RECIPINFO_NONE;
else if (EVP_PKEY_is_a(pk, "EC"))
return CMS_RECIPINFO_AGREE;
else if (EVP_PKEY_is_a(pk, "RSA"))
return CMS_RECIPINFO_TRANS;
/*
* Otherwise this might ben an engine implementation, so see if we can get
* the type from the ameth.
*/
if (pk->ameth && pk->ameth->pkey_ctrl) {
int i, r;
i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_RI_TYPE, 0, &r);
if (i > 0)
return r;
}
return CMS_RECIPINFO_TRANS;
}
int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type)
{
int supportedRiType;
if (pk->ameth != NULL && pk->ameth->pkey_ctrl != NULL) {
int i, r;
i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED,
ri_type, &r);
if (i > 0)
return r;
}
supportedRiType = ossl_cms_pkey_get_ri_type(pk);
if (supportedRiType < 0)
return 0;
return (supportedRiType == ri_type);
}
diff --git a/crypto/openssl/crypto/cms/cms_err.c b/crypto/openssl/crypto/cms/cms_err.c
index 4bd6a0dc1bf1..e67d783be290 100644
--- a/crypto/openssl/crypto/cms/cms_err.c
+++ b/crypto/openssl/crypto/cms/cms_err.c
@@ -1,180 +1,182 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/cmserr.h>
#include "crypto/cmserr.h"
#ifndef OPENSSL_NO_CMS
# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA CMS_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ADD_SIGNER_ERROR), "add signer error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ATTRIBUTE_ERROR), "attribute error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_ALREADY_PRESENT),
- "certificate already present"},
+ "certificate already present"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_HAS_NO_KEYID),
- "certificate has no keyid"},
+ "certificate has no keyid"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_VERIFY_ERROR),
- "certificate verify error"},
+ "certificate verify error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_AEAD_SET_TAG_ERROR),
- "cipher aead set tag error"},
+ "cipher aead set tag error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_GET_TAG), "cipher get tag"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_INITIALISATION_ERROR),
- "cipher initialisation error"},
+ "cipher initialisation error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),
- "cipher parameter initialisation error"},
+ "cipher parameter initialisation error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CMS_DATAFINAL_ERROR),
- "cms datafinal error"},
+ "cms datafinal error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CMS_LIB), "cms lib"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENTIDENTIFIER_MISMATCH),
- "contentidentifier mismatch"},
+ "contentidentifier mismatch"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_NOT_FOUND), "content not found"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_MISMATCH),
- "content type mismatch"},
+ "content type mismatch"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA),
- "content type not compressed data"},
+ "content type not compressed data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA),
- "content type not enveloped data"},
+ "content type not enveloped data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA),
- "content type not signed data"},
+ "content type not signed data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_VERIFY_ERROR),
- "content verify error"},
+ "content verify error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CTRL_ERROR), "ctrl error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CTRL_FAILURE), "ctrl failure"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_DECODE_ERROR), "decode error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_DECRYPT_ERROR), "decrypt error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_GETTING_PUBLIC_KEY),
- "error getting public key"},
+ "error getting public key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),
- "error reading messagedigest attribute"},
+ "error reading messagedigest attribute"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_KEY), "error setting key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_RECIPIENTINFO),
- "error setting recipientinfo"},
+ "error setting recipientinfo"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT),
+ "error unsupported static key agreement"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR),
- "ess signing certid mismatch error"},
+ "ess signing certid mismatch error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),
- "invalid encrypted key length"},
+ "invalid encrypted key length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),
- "invalid key encryption parameter"},
+ "invalid key encryption parameter"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_LENGTH), "invalid key length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_LABEL), "invalid label"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_OAEP_PARAMETERS),
- "invalid oaep parameters"},
+ "invalid oaep parameters"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_KDF_PARAMETER_ERROR),
- "kdf parameter error"},
+ "kdf parameter error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MD_BIO_INIT_ERROR), "md bio init error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),
- "messagedigest attribute wrong length"},
+ "messagedigest attribute wrong length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MESSAGEDIGEST_WRONG_LENGTH),
- "messagedigest wrong length"},
+ "messagedigest wrong length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_ERROR), "msgsigdigest error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE),
- "msgsigdigest verification failure"},
+ "msgsigdigest verification failure"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_WRONG_LENGTH),
- "msgsigdigest wrong length"},
+ "msgsigdigest wrong length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NEED_ONE_SIGNER), "need one signer"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_A_SIGNED_RECEIPT),
- "not a signed receipt"},
+ "not a signed receipt"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_ENCRYPTED_DATA), "not encrypted data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEK), "not kek"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEY_AGREEMENT), "not key agreement"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEY_TRANSPORT), "not key transport"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_PWRI), "not pwri"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),
- "not supported for this key type"},
+ "not supported for this key type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CIPHER), "no cipher"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CONTENT), "no content"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CONTENT_TYPE), "no content type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_DEFAULT_DIGEST), "no default digest"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_DIGEST_SET), "no digest set"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_KEY), "no key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_KEY_OR_CERT), "no key or cert"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_DIGEST), "no matching digest"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_RECIPIENT),
- "no matching recipient"},
+ "no matching recipient"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_SIGNATURE),
- "no matching signature"},
+ "no matching signature"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MSGSIGDIGEST), "no msgsigdigest"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PASSWORD), "no password"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PRIVATE_KEY), "no private key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PUBLIC_KEY), "no public key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_RECEIPT_REQUEST), "no receipt request"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_SIGNERS), "no signers"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PEER_KEY_ERROR), "peer key error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),
- "private key does not match certificate"},
+ "private key does not match certificate"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECEIPT_DECODE_ERROR),
- "receipt decode error"},
+ "receipt decode error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECIPIENT_ERROR), "recipient error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SHARED_INFO_ERROR), "shared info error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND),
- "signer certificate not found"},
+ "signer certificate not found"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNFINAL_ERROR), "signfinal error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SMIME_TEXT_ERROR), "smime text error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_STORE_INIT_ERROR), "store init error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_COMPRESSED_DATA),
- "type not compressed data"},
+ "type not compressed data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_DATA), "type not data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_DIGESTED_DATA),
- "type not digested data"},
+ "type not digested data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_ENCRYPTED_DATA),
- "type not encrypted data"},
+ "type not encrypted data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_ENVELOPED_DATA),
- "type not enveloped data"},
+ "type not enveloped data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNABLE_TO_FINALIZE_CONTEXT),
- "unable to finalize context"},
+ "unable to finalize context"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_CIPHER), "unknown cipher"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_DIGEST_ALGORITHM),
- "unknown digest algorithm"},
+ "unknown digest algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_ID), "unknown id"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),
- "unsupported compression algorithm"},
+ "unsupported compression algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM),
- "unsupported content encryption algorithm"},
+ "unsupported content encryption algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_TYPE),
- "unsupported content type"},
+ "unsupported content type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE),
- "unsupported encryption type"},
+ "unsupported encryption type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEK_ALGORITHM),
- "unsupported kek algorithm"},
+ "unsupported kek algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),
- "unsupported key encryption algorithm"},
+ "unsupported key encryption algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_LABEL_SOURCE),
- "unsupported label source"},
+ "unsupported label source"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE),
- "unsupported recipientinfo type"},
+ "unsupported recipientinfo type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENT_TYPE),
- "unsupported recipient type"},
+ "unsupported recipient type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM),
- "unsupported signature algorithm"},
+ "unsupported signature algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_TYPE), "unsupported type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNWRAP_ERROR), "unwrap error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNWRAP_FAILURE), "unwrap failure"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_VERIFICATION_FAILURE),
- "verification failure"},
+ "verification failure"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_WRAP_ERROR), "wrap error"},
{0, NULL}
};
# endif
int ossl_err_load_CMS_strings(void)
{
# ifndef OPENSSL_NO_ERR
if (ERR_reason_error_string(CMS_str_reasons[0].error) == NULL)
ERR_load_strings_const(CMS_str_reasons);
# endif
return 1;
}
#else
NON_EMPTY_TRANSLATION_UNIT
#endif
diff --git a/crypto/openssl/crypto/cms/cms_kari.c b/crypto/openssl/crypto/cms/cms_kari.c
index a2f422a78d8b..8e9e6a5d148c 100644
--- a/crypto/openssl/crypto/cms/cms_kari.c
+++ b/crypto/openssl/crypto/cms/cms_kari.c
@@ -1,523 +1,530 @@
/*
- * Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2013-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* Low level key APIs (DH etc) are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
#include <openssl/aes.h>
#include "cms_local.h"
#include "crypto/asn1.h"
/* Key Agreement Recipient Info (KARI) routines */
int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
X509_ALGOR **palg,
ASN1_OCTET_STRING **pukm)
{
if (ri->type != CMS_RECIPINFO_AGREE) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return 0;
}
if (palg)
*palg = ri->d.kari->keyEncryptionAlgorithm;
if (pukm)
*pukm = ri->d.kari->ukm;
return 1;
}
/* Retrieve recipient encrypted keys from a kari */
STACK_OF(CMS_RecipientEncryptedKey)
*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri)
{
if (ri->type != CMS_RECIPINFO_AGREE) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return NULL;
}
return ri->d.kari->recipientEncryptedKeys;
}
int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
X509_ALGOR **pubalg,
ASN1_BIT_STRING **pubkey,
ASN1_OCTET_STRING **keyid,
X509_NAME **issuer,
ASN1_INTEGER **sno)
{
CMS_OriginatorIdentifierOrKey *oik;
if (ri->type != CMS_RECIPINFO_AGREE) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return 0;
}
oik = ri->d.kari->originator;
if (issuer)
*issuer = NULL;
if (sno)
*sno = NULL;
if (keyid)
*keyid = NULL;
if (pubalg)
*pubalg = NULL;
if (pubkey)
*pubkey = NULL;
if (oik->type == CMS_OIK_ISSUER_SERIAL) {
if (issuer)
*issuer = oik->d.issuerAndSerialNumber->issuer;
if (sno)
*sno = oik->d.issuerAndSerialNumber->serialNumber;
} else if (oik->type == CMS_OIK_KEYIDENTIFIER) {
if (keyid)
*keyid = oik->d.subjectKeyIdentifier;
} else if (oik->type == CMS_OIK_PUBKEY) {
if (pubalg)
*pubalg = oik->d.originatorKey->algorithm;
if (pubkey)
*pubkey = oik->d.originatorKey->publicKey;
} else
return 0;
return 1;
}
int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert)
{
CMS_OriginatorIdentifierOrKey *oik;
if (ri->type != CMS_RECIPINFO_AGREE) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return -2;
}
oik = ri->d.kari->originator;
if (oik->type == CMS_OIK_ISSUER_SERIAL)
return ossl_cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert);
else if (oik->type == CMS_OIK_KEYIDENTIFIER)
return ossl_cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert);
return -1;
}
int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
ASN1_OCTET_STRING **keyid,
ASN1_GENERALIZEDTIME **tm,
CMS_OtherKeyAttribute **other,
X509_NAME **issuer, ASN1_INTEGER **sno)
{
CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
if (rid->type == CMS_REK_ISSUER_SERIAL) {
if (issuer)
*issuer = rid->d.issuerAndSerialNumber->issuer;
if (sno)
*sno = rid->d.issuerAndSerialNumber->serialNumber;
if (keyid)
*keyid = NULL;
if (tm)
*tm = NULL;
if (other)
*other = NULL;
} else if (rid->type == CMS_REK_KEYIDENTIFIER) {
if (keyid)
*keyid = rid->d.rKeyId->subjectKeyIdentifier;
if (tm)
*tm = rid->d.rKeyId->date;
if (other)
*other = rid->d.rKeyId->other;
if (issuer)
*issuer = NULL;
if (sno)
*sno = NULL;
} else
return 0;
return 1;
}
int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
X509 *cert)
{
CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
if (rid->type == CMS_REK_ISSUER_SERIAL)
return ossl_cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert);
else if (rid->type == CMS_REK_KEYIDENTIFIER)
return ossl_cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier,
cert);
else
return -1;
}
int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri,
EVP_PKEY *pk, X509 *peer)
{
EVP_PKEY_CTX *pctx;
CMS_KeyAgreeRecipientInfo *kari = ri->d.kari;
EVP_PKEY_CTX_free(kari->pctx);
kari->pctx = NULL;
if (pk == NULL)
return 1;
pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(kari->cms_ctx),
pk,
ossl_cms_ctx_get0_propq(kari->cms_ctx));
if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0)
goto err;
if (peer != NULL) {
EVP_PKEY *pub_pkey = X509_get0_pubkey(peer);
if (EVP_PKEY_derive_set_peer(pctx, pub_pkey) <= 0)
goto err;
}
kari->pctx = pctx;
return 1;
err:
EVP_PKEY_CTX_free(pctx);
return 0;
}
int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
{
return CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, NULL);
}
EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri)
{
if (ri->type == CMS_RECIPINFO_AGREE)
return ri->d.kari->ctx;
return NULL;
}
/*
* Derive KEK and decrypt/encrypt with it to produce either the original CEK
* or the encrypted CEK.
*/
static int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
const unsigned char *in, size_t inlen,
CMS_KeyAgreeRecipientInfo *kari, int enc)
{
/* Key encryption key */
unsigned char kek[EVP_MAX_KEY_LENGTH];
size_t keklen;
int rv = 0;
unsigned char *out = NULL;
int outlen;
keklen = EVP_CIPHER_CTX_get_key_length(kari->ctx);
if (keklen > EVP_MAX_KEY_LENGTH)
return 0;
/* Derive KEK */
if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0)
goto err;
/* Set KEK in context */
if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc))
goto err;
/* obtain output length of ciphered key */
if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen))
goto err;
out = OPENSSL_malloc(outlen);
if (out == NULL)
goto err;
if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen))
goto err;
*pout = out;
*poutlen = (size_t)outlen;
rv = 1;
err:
OPENSSL_cleanse(kek, keklen);
if (!rv)
OPENSSL_free(out);
EVP_CIPHER_CTX_reset(kari->ctx);
/* FIXME: WHY IS kari->pctx freed here? /RL */
EVP_PKEY_CTX_free(kari->pctx);
kari->pctx = NULL;
return rv;
}
int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
CMS_RecipientInfo *ri,
CMS_RecipientEncryptedKey *rek)
{
int rv = 0;
unsigned char *enckey = NULL, *cek = NULL;
size_t enckeylen;
size_t ceklen;
CMS_EncryptedContentInfo *ec;
enckeylen = rek->encryptedKey->length;
enckey = rek->encryptedKey->data;
/* Setup all parameters to derive KEK */
if (!ossl_cms_env_asn1_ctrl(ri, 1))
goto err;
/* Attempt to decrypt CEK */
if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0))
goto err;
ec = ossl_cms_get0_env_enc_content(cms);
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = cek;
ec->keylen = ceklen;
cek = NULL;
rv = 1;
err:
OPENSSL_free(cek);
return rv;
}
/* Create ephemeral key and initialise context based on it */
static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
EVP_PKEY *pk)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *ekey = NULL;
int rv = 0;
const CMS_CTX *ctx = kari->cms_ctx;
OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
const char *propq = ossl_cms_ctx_get0_propq(ctx);
pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propq);
if (pctx == NULL)
goto err;
if (EVP_PKEY_keygen_init(pctx) <= 0)
goto err;
if (EVP_PKEY_keygen(pctx, &ekey) <= 0)
goto err;
EVP_PKEY_CTX_free(pctx);
pctx = EVP_PKEY_CTX_new_from_pkey(libctx, ekey, propq);
if (pctx == NULL)
goto err;
if (EVP_PKEY_derive_init(pctx) <= 0)
goto err;
kari->pctx = pctx;
rv = 1;
err:
if (!rv)
EVP_PKEY_CTX_free(pctx);
EVP_PKEY_free(ekey);
return rv;
}
/* Set originator private key and initialise context based on it */
static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari,
EVP_PKEY *originatorPrivKey )
{
EVP_PKEY_CTX *pctx = NULL;
int rv = 0;
const CMS_CTX *ctx = kari->cms_ctx;
pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
originatorPrivKey,
ossl_cms_ctx_get0_propq(ctx));
if (pctx == NULL)
goto err;
if (EVP_PKEY_derive_init(pctx) <= 0)
goto err;
kari->pctx = pctx;
rv = 1;
err:
if (rv == 0)
EVP_PKEY_CTX_free(pctx);
return rv;
}
/* Initialise a kari based on passed certificate and key */
int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
EVP_PKEY *recipPubKey, X509 *originator,
EVP_PKEY *originatorPrivKey,
unsigned int flags, const CMS_CTX *ctx)
{
CMS_KeyAgreeRecipientInfo *kari;
CMS_RecipientEncryptedKey *rek = NULL;
ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo);
if (ri->d.kari == NULL)
return 0;
ri->type = CMS_RECIPINFO_AGREE;
kari = ri->d.kari;
kari->version = 3;
kari->cms_ctx = ctx;
rek = M_ASN1_new_of(CMS_RecipientEncryptedKey);
if (rek == NULL)
return 0;
if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) {
M_ASN1_free_of(rek, CMS_RecipientEncryptedKey);
return 0;
}
if (flags & CMS_USE_KEYID) {
rek->rid->type = CMS_REK_KEYIDENTIFIER;
rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier);
if (rek->rid->d.rKeyId == NULL)
return 0;
if (!ossl_cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip))
return 0;
} else {
rek->rid->type = CMS_REK_ISSUER_SERIAL;
if (!ossl_cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip))
return 0;
}
if (originatorPrivKey == NULL && originator == NULL) {
/* Create ephemeral key */
if (!cms_kari_create_ephemeral_key(kari, recipPubKey))
return 0;
} else {
/* Use originator key */
CMS_OriginatorIdentifierOrKey *oik = ri->d.kari->originator;
if (originatorPrivKey == NULL || originator == NULL)
return 0;
if (flags & CMS_USE_ORIGINATOR_KEYID) {
oik->type = CMS_OIK_KEYIDENTIFIER;
oik->d.subjectKeyIdentifier = ASN1_OCTET_STRING_new();
if (oik->d.subjectKeyIdentifier == NULL)
return 0;
if (!ossl_cms_set1_keyid(&oik->d.subjectKeyIdentifier, originator))
return 0;
} else {
oik->type = CMS_REK_ISSUER_SERIAL;
if (!ossl_cms_set1_ias(&oik->d.issuerAndSerialNumber, originator))
return 0;
}
if (!cms_kari_set_originator_private_key(kari, originatorPrivKey))
return 0;
}
EVP_PKEY_up_ref(recipPubKey);
rek->pkey = recipPubKey;
return 1;
}
static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
const EVP_CIPHER *cipher)
{
const CMS_CTX *cms_ctx = kari->cms_ctx;
EVP_CIPHER_CTX *ctx = kari->ctx;
const EVP_CIPHER *kekcipher;
EVP_CIPHER *fetched_kekcipher;
const char *kekcipher_name;
int keylen;
int ret;
/* If a suitable wrap algorithm is already set nothing to do */
kekcipher = EVP_CIPHER_CTX_get0_cipher(ctx);
if (kekcipher != NULL) {
if (EVP_CIPHER_CTX_get_mode(ctx) != EVP_CIPH_WRAP_MODE)
return 0;
return 1;
}
if (cipher == NULL)
return 0;
keylen = EVP_CIPHER_get_key_length(cipher);
if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER) != 0) {
ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER,
0, &kekcipher);
if (ret <= 0)
return 0;
if (kekcipher != NULL) {
if (EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
return 0;
kekcipher_name = EVP_CIPHER_get0_name(kekcipher);
goto enc;
}
}
/*
* Pick a cipher based on content encryption cipher. If it is DES3 use
* DES3 wrap otherwise use AES wrap similar to key size.
*/
#ifndef OPENSSL_NO_DES
if (EVP_CIPHER_get_type(cipher) == NID_des_ede3_cbc)
kekcipher_name = SN_id_smime_alg_CMS3DESwrap;
else
#endif
if (keylen <= 16)
kekcipher_name = SN_id_aes128_wrap;
else if (keylen <= 24)
kekcipher_name = SN_id_aes192_wrap;
else
kekcipher_name = SN_id_aes256_wrap;
enc:
fetched_kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx),
kekcipher_name,
ossl_cms_ctx_get0_propq(cms_ctx));
if (fetched_kekcipher == NULL)
return 0;
ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL);
EVP_CIPHER_free(fetched_kekcipher);
return ret;
}
/* Encrypt content key in key agreement recipient info */
int ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
CMS_RecipientInfo *ri)
{
CMS_KeyAgreeRecipientInfo *kari;
CMS_EncryptedContentInfo *ec;
CMS_RecipientEncryptedKey *rek;
STACK_OF(CMS_RecipientEncryptedKey) *reks;
int i;
if (ri->type != CMS_RECIPINFO_AGREE) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return 0;
}
kari = ri->d.kari;
reks = kari->recipientEncryptedKeys;
ec = ossl_cms_get0_env_enc_content(cms);
/* Initialise wrap algorithm parameters */
if (!cms_wrap_init(kari, ec->cipher))
return 0;
/*
* If no originator key set up initialise for ephemeral key the public key
* ASN1 structure will set the actual public key value.
*/
if (kari->originator->type == -1) {
CMS_OriginatorIdentifierOrKey *oik = kari->originator;
oik->type = CMS_OIK_PUBKEY;
oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey);
if (!oik->d.originatorKey)
return 0;
+ } else {
+ /*
+ * Currently it is not possible to get public key as it is not stored
+ * during kari initialization.
+ */
+ ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT);
+ return 0;
}
/* Initialise KDF algorithm */
if (!ossl_cms_env_asn1_ctrl(ri, 0))
return 0;
/* For each rek, derive KEK, encrypt CEK */
for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
unsigned char *enckey;
size_t enckeylen;
rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0)
return 0;
if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen,
kari, 1))
return 0;
ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen);
}
return 1;
}
diff --git a/crypto/openssl/crypto/cms/cms_lib.c b/crypto/openssl/crypto/cms/cms_lib.c
index 8b135e95aacc..67b35627ba5e 100644
--- a/crypto/openssl/crypto/cms/cms_lib.c
+++ b/crypto/openssl/crypto/cms/cms_lib.c
@@ -1,733 +1,720 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/asn1t.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/cms.h>
#include <openssl/cms.h>
#include "internal/sizes.h"
#include "crypto/x509.h"
#include "cms_local.h"
static STACK_OF(CMS_CertificateChoices)
**cms_get0_certificate_choices(CMS_ContentInfo *cms);
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_ContentInfo)
IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a,
const unsigned char **in, long len)
{
CMS_ContentInfo *ci;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(a == NULL ? NULL : *a);
ci = (CMS_ContentInfo *)ASN1_item_d2i_ex((ASN1_VALUE **)a, in, len,
(CMS_ContentInfo_it()),
ossl_cms_ctx_get0_libctx(ctx),
ossl_cms_ctx_get0_propq(ctx));
if (ci != NULL) {
ERR_set_mark();
ossl_cms_resolve_libctx(ci);
ERR_pop_to_mark();
}
return ci;
}
int i2d_CMS_ContentInfo(const CMS_ContentInfo *a, unsigned char **out)
{
return ASN1_item_i2d((const ASN1_VALUE *)a, out, (CMS_ContentInfo_it()));
}
CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
{
CMS_ContentInfo *ci;
ci = (CMS_ContentInfo *)ASN1_item_new_ex(ASN1_ITEM_rptr(CMS_ContentInfo),
libctx, propq);
if (ci != NULL) {
ci->ctx.libctx = libctx;
ci->ctx.propq = NULL;
if (propq != NULL) {
ci->ctx.propq = OPENSSL_strdup(propq);
if (ci->ctx.propq == NULL) {
CMS_ContentInfo_free(ci);
ci = NULL;
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
}
}
}
return ci;
}
-CMS_ContentInfo *CMS_ContentInfo_new(void)
-{
- return CMS_ContentInfo_new_ex(NULL, NULL);
-}
-
-void CMS_ContentInfo_free(CMS_ContentInfo *cms)
-{
- if (cms != NULL) {
- ossl_cms_env_enc_content_free(cms);
- OPENSSL_free(cms->ctx.propq);
- ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo));
- }
-}
-
const CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms)
{
return cms != NULL ? &cms->ctx : NULL;
}
OSSL_LIB_CTX *ossl_cms_ctx_get0_libctx(const CMS_CTX *ctx)
{
return ctx != NULL ? ctx->libctx : NULL;
}
const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx)
{
return ctx != NULL ? ctx->propq : NULL;
}
void ossl_cms_resolve_libctx(CMS_ContentInfo *ci)
{
int i;
CMS_CertificateChoices *cch;
STACK_OF(CMS_CertificateChoices) **pcerts;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(ci);
OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
const char *propq = ossl_cms_ctx_get0_propq(ctx);
ossl_cms_SignerInfos_set_cmsctx(ci);
ossl_cms_RecipientInfos_set_cmsctx(ci);
pcerts = cms_get0_certificate_choices(ci);
if (pcerts != NULL) {
for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
cch = sk_CMS_CertificateChoices_value(*pcerts, i);
if (cch->type == CMS_CERTCHOICE_CERT)
ossl_x509_set0_libctx(cch->d.certificate, libctx, propq);
}
}
}
const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms)
{
return cms->contentType;
}
CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *libctx, const char *propq)
{
CMS_ContentInfo *cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms != NULL) {
cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
/* Never detached */
CMS_set_detached(cms, 0);
}
return cms;
}
BIO *ossl_cms_content_bio(CMS_ContentInfo *cms)
{
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
if (pos == NULL)
return NULL;
/* If content detached data goes nowhere: create NULL BIO */
if (*pos == NULL)
return BIO_new(BIO_s_null());
/*
* If content not detached and created return memory BIO
*/
if (*pos == NULL || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
return BIO_new(BIO_s_mem());
/* Else content was read in: return read only BIO for it */
return BIO_new_mem_buf((*pos)->data, (*pos)->length);
}
BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
{
BIO *cmsbio, *cont;
if (icont)
cont = icont;
else
cont = ossl_cms_content_bio(cms);
if (!cont) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
return NULL;
}
switch (OBJ_obj2nid(cms->contentType)) {
case NID_pkcs7_data:
return cont;
case NID_pkcs7_signed:
cmsbio = ossl_cms_SignedData_init_bio(cms);
break;
case NID_pkcs7_digest:
cmsbio = ossl_cms_DigestedData_init_bio(cms);
break;
#ifdef ZLIB
case NID_id_smime_ct_compressedData:
cmsbio = ossl_cms_CompressedData_init_bio(cms);
break;
#endif
case NID_pkcs7_encrypted:
cmsbio = ossl_cms_EncryptedData_init_bio(cms);
break;
case NID_pkcs7_enveloped:
cmsbio = ossl_cms_EnvelopedData_init_bio(cms);
break;
case NID_id_smime_ct_authEnvelopedData:
cmsbio = ossl_cms_AuthEnvelopedData_init_bio(cms);
break;
default:
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE);
goto err;
}
if (cmsbio)
return BIO_push(cmsbio, cont);
err:
if (!icont)
BIO_free(cont);
return NULL;
}
/* unfortunately cannot constify SMIME_write_ASN1() due to this function */
int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
{
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
if (pos == NULL)
return 0;
/* If embedded content find memory BIO and set content */
if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
BIO *mbio;
unsigned char *cont;
long contlen;
mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
if (!mbio) {
ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND);
return 0;
}
contlen = BIO_get_mem_data(mbio, &cont);
/* Set bio as read only so its content can't be clobbered */
BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
BIO_set_mem_eof_return(mbio, 0);
ASN1_STRING_set0(*pos, cont, contlen);
(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
}
switch (OBJ_obj2nid(cms->contentType)) {
case NID_pkcs7_data:
case NID_pkcs7_encrypted:
case NID_id_smime_ct_compressedData:
/* Nothing to do */
return 1;
case NID_pkcs7_enveloped:
return ossl_cms_EnvelopedData_final(cms, cmsbio);
case NID_id_smime_ct_authEnvelopedData:
return ossl_cms_AuthEnvelopedData_final(cms, cmsbio);
case NID_pkcs7_signed:
return ossl_cms_SignedData_final(cms, cmsbio);
case NID_pkcs7_digest:
return ossl_cms_DigestedData_do_final(cms, cmsbio, 0);
default:
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE);
return 0;
}
}
/*
* Return an OCTET STRING pointer to content. This allows it to be accessed
* or set later.
*/
ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
{
switch (OBJ_obj2nid(cms->contentType)) {
case NID_pkcs7_data:
return &cms->d.data;
case NID_pkcs7_signed:
return &cms->d.signedData->encapContentInfo->eContent;
case NID_pkcs7_enveloped:
return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
case NID_pkcs7_digest:
return &cms->d.digestedData->encapContentInfo->eContent;
case NID_pkcs7_encrypted:
return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
case NID_id_smime_ct_authEnvelopedData:
return &cms->d.authEnvelopedData->authEncryptedContentInfo
->encryptedContent;
case NID_id_smime_ct_authData:
return &cms->d.authenticatedData->encapContentInfo->eContent;
case NID_id_smime_ct_compressedData:
return &cms->d.compressedData->encapContentInfo->eContent;
default:
if (cms->d.other->type == V_ASN1_OCTET_STRING)
return &cms->d.other->value.octet_string;
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
return NULL;
}
}
/*
* Return an ASN1_OBJECT pointer to content type. This allows it to be
* accessed or set later.
*/
static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
{
switch (OBJ_obj2nid(cms->contentType)) {
case NID_pkcs7_signed:
return &cms->d.signedData->encapContentInfo->eContentType;
case NID_pkcs7_enveloped:
return &cms->d.envelopedData->encryptedContentInfo->contentType;
case NID_pkcs7_digest:
return &cms->d.digestedData->encapContentInfo->eContentType;
case NID_pkcs7_encrypted:
return &cms->d.encryptedData->encryptedContentInfo->contentType;
case NID_id_smime_ct_authEnvelopedData:
return &cms->d.authEnvelopedData->authEncryptedContentInfo
->contentType;
case NID_id_smime_ct_authData:
return &cms->d.authenticatedData->encapContentInfo->eContentType;
case NID_id_smime_ct_compressedData:
return &cms->d.compressedData->encapContentInfo->eContentType;
default:
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
return NULL;
}
}
const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
{
ASN1_OBJECT **petype;
petype = cms_get0_econtent_type(cms);
if (petype)
return *petype;
return NULL;
}
int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
{
ASN1_OBJECT **petype, *etype;
petype = cms_get0_econtent_type(cms);
if (petype == NULL)
return 0;
if (oid == NULL)
return 1;
etype = OBJ_dup(oid);
if (etype == NULL)
return 0;
ASN1_OBJECT_free(*petype);
*petype = etype;
return 1;
}
int CMS_is_detached(CMS_ContentInfo *cms)
{
ASN1_OCTET_STRING **pos;
pos = CMS_get0_content(cms);
if (pos == NULL)
return -1;
if (*pos != NULL)
return 0;
return 1;
}
int CMS_set_detached(CMS_ContentInfo *cms, int detached)
{
ASN1_OCTET_STRING **pos;
pos = CMS_get0_content(cms);
if (pos == NULL)
return 0;
if (detached) {
ASN1_OCTET_STRING_free(*pos);
*pos = NULL;
return 1;
}
if (*pos == NULL)
*pos = ASN1_OCTET_STRING_new();
if (*pos != NULL) {
/*
* NB: special flag to show content is created and not read in.
*/
(*pos)->flags |= ASN1_STRING_FLAG_CONT;
return 1;
}
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
/* Create a digest BIO from an X509_ALGOR structure */
BIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
const CMS_CTX *ctx)
{
BIO *mdbio = NULL;
const ASN1_OBJECT *digestoid;
const EVP_MD *digest = NULL;
EVP_MD *fetched_digest = NULL;
char alg[OSSL_MAX_NAME_SIZE];
X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
OBJ_obj2txt(alg, sizeof(alg), digestoid, 0);
(void)ERR_set_mark();
fetched_digest = EVP_MD_fetch(ossl_cms_ctx_get0_libctx(ctx), alg,
ossl_cms_ctx_get0_propq(ctx));
if (fetched_digest != NULL)
digest = fetched_digest;
else
digest = EVP_get_digestbyobj(digestoid);
if (digest == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
goto err;
}
(void)ERR_pop_to_mark();
mdbio = BIO_new(BIO_f_md());
if (mdbio == NULL || BIO_set_md(mdbio, digest) <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_MD_BIO_INIT_ERROR);
goto err;
}
EVP_MD_free(fetched_digest);
return mdbio;
err:
EVP_MD_free(fetched_digest);
BIO_free(mdbio);
return NULL;
}
/* Locate a message digest content from a BIO chain based on SignerInfo */
int ossl_cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
X509_ALGOR *mdalg)
{
int nid;
const ASN1_OBJECT *mdoid;
X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
nid = OBJ_obj2nid(mdoid);
/* Look for digest type to match signature */
for (;;) {
EVP_MD_CTX *mtmp;
chain = BIO_find_type(chain, BIO_TYPE_MD);
if (chain == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST);
return 0;
}
BIO_get_md_ctx(chain, &mtmp);
if (EVP_MD_CTX_get_type(mtmp) == nid
/*
* Workaround for broken implementations that use signature
* algorithm OID instead of digest.
*/
|| EVP_MD_get_pkey_type(EVP_MD_CTX_get0_md(mtmp)) == nid)
return EVP_MD_CTX_copy_ex(mctx, mtmp);
chain = BIO_next(chain);
}
}
static STACK_OF(CMS_CertificateChoices)
**cms_get0_certificate_choices(CMS_ContentInfo *cms)
{
switch (OBJ_obj2nid(cms->contentType)) {
case NID_pkcs7_signed:
return &cms->d.signedData->certificates;
case NID_pkcs7_enveloped:
if (cms->d.envelopedData->originatorInfo == NULL)
return NULL;
return &cms->d.envelopedData->originatorInfo->certificates;
case NID_id_smime_ct_authEnvelopedData:
if (cms->d.authEnvelopedData->originatorInfo == NULL)
return NULL;
return &cms->d.authEnvelopedData->originatorInfo->certificates;
default:
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
return NULL;
}
}
CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
{
STACK_OF(CMS_CertificateChoices) **pcerts;
CMS_CertificateChoices *cch;
pcerts = cms_get0_certificate_choices(cms);
if (pcerts == NULL)
return NULL;
if (*pcerts == NULL)
*pcerts = sk_CMS_CertificateChoices_new_null();
if (*pcerts == NULL)
return NULL;
cch = M_ASN1_new_of(CMS_CertificateChoices);
if (!cch)
return NULL;
if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
M_ASN1_free_of(cch, CMS_CertificateChoices);
return NULL;
}
return cch;
}
int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
{
CMS_CertificateChoices *cch;
STACK_OF(CMS_CertificateChoices) **pcerts;
int i;
pcerts = cms_get0_certificate_choices(cms);
if (pcerts == NULL)
return 0;
for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
cch = sk_CMS_CertificateChoices_value(*pcerts, i);
if (cch->type == CMS_CERTCHOICE_CERT) {
if (!X509_cmp(cch->d.certificate, cert)) {
ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_ALREADY_PRESENT);
return 0;
}
}
}
cch = CMS_add0_CertificateChoices(cms);
if (!cch)
return 0;
cch->type = CMS_CERTCHOICE_CERT;
cch->d.certificate = cert;
return 1;
}
int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
{
int r;
r = CMS_add0_cert(cms, cert);
if (r > 0)
X509_up_ref(cert);
return r;
}
static STACK_OF(CMS_RevocationInfoChoice)
**cms_get0_revocation_choices(CMS_ContentInfo *cms)
{
switch (OBJ_obj2nid(cms->contentType)) {
case NID_pkcs7_signed:
return &cms->d.signedData->crls;
case NID_pkcs7_enveloped:
if (cms->d.envelopedData->originatorInfo == NULL)
return NULL;
return &cms->d.envelopedData->originatorInfo->crls;
case NID_id_smime_ct_authEnvelopedData:
if (cms->d.authEnvelopedData->originatorInfo == NULL)
return NULL;
return &cms->d.authEnvelopedData->originatorInfo->crls;
default:
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
return NULL;
}
}
CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
{
STACK_OF(CMS_RevocationInfoChoice) **pcrls;
CMS_RevocationInfoChoice *rch;
pcrls = cms_get0_revocation_choices(cms);
if (pcrls == NULL)
return NULL;
if (*pcrls == NULL)
*pcrls = sk_CMS_RevocationInfoChoice_new_null();
if (*pcrls == NULL)
return NULL;
rch = M_ASN1_new_of(CMS_RevocationInfoChoice);
if (rch == NULL)
return NULL;
if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
M_ASN1_free_of(rch, CMS_RevocationInfoChoice);
return NULL;
}
return rch;
}
int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
{
CMS_RevocationInfoChoice *rch;
rch = CMS_add0_RevocationInfoChoice(cms);
if (!rch)
return 0;
rch->type = CMS_REVCHOICE_CRL;
rch->d.crl = crl;
return 1;
}
int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
{
if (!X509_CRL_up_ref(crl))
return 0;
if (CMS_add0_crl(cms, crl))
return 1;
X509_CRL_free(crl);
return 0;
}
STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
{
STACK_OF(X509) *certs = NULL;
CMS_CertificateChoices *cch;
STACK_OF(CMS_CertificateChoices) **pcerts;
int i;
pcerts = cms_get0_certificate_choices(cms);
if (pcerts == NULL)
return NULL;
for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
cch = sk_CMS_CertificateChoices_value(*pcerts, i);
if (cch->type == 0) {
if (!ossl_x509_add_cert_new(&certs, cch->d.certificate,
X509_ADD_FLAG_UP_REF)) {
sk_X509_pop_free(certs, X509_free);
return NULL;
}
}
}
return certs;
}
STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
{
STACK_OF(X509_CRL) *crls = NULL;
STACK_OF(CMS_RevocationInfoChoice) **pcrls;
CMS_RevocationInfoChoice *rch;
int i;
pcrls = cms_get0_revocation_choices(cms);
if (pcrls == NULL)
return NULL;
for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
if (rch->type == 0) {
if (!crls) {
crls = sk_X509_CRL_new_null();
if (!crls)
return NULL;
}
if (!sk_X509_CRL_push(crls, rch->d.crl)) {
sk_X509_CRL_pop_free(crls, X509_CRL_free);
return NULL;
}
X509_CRL_up_ref(rch->d.crl);
}
}
return crls;
}
int ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
{
int ret;
ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
if (ret)
return ret;
return ASN1_INTEGER_cmp(ias->serialNumber, X509_get0_serialNumber(cert));
}
int ossl_cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
{
const ASN1_OCTET_STRING *cert_keyid = X509_get0_subject_key_id(cert);
if (cert_keyid == NULL)
return -1;
return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
}
int ossl_cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
{
CMS_IssuerAndSerialNumber *ias;
ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber);
if (!ias)
goto err;
if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert)))
goto err;
if (!ASN1_STRING_copy(ias->serialNumber, X509_get0_serialNumber(cert)))
goto err;
M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber);
*pias = ias;
return 1;
err:
M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber);
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
int ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
{
ASN1_OCTET_STRING *keyid = NULL;
const ASN1_OCTET_STRING *cert_keyid;
cert_keyid = X509_get0_subject_key_id(cert);
if (cert_keyid == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID);
return 0;
}
keyid = ASN1_STRING_dup(cert_keyid);
if (!keyid) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_OCTET_STRING_free(*pkeyid);
*pkeyid = keyid;
return 1;
}
diff --git a/crypto/openssl/crypto/cms/cms_local.h b/crypto/openssl/crypto/cms/cms_local.h
index 253f6819e435..1e0e0910d1d1 100644
--- a/crypto/openssl/crypto/cms/cms_local.h
+++ b/crypto/openssl/crypto/cms/cms_local.h
@@ -1,504 +1,504 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 OSSL_CRYPTO_CMS_LOCAL_H
# define OSSL_CRYPTO_CMS_LOCAL_H
# include <openssl/x509.h>
/*
* Cryptographic message syntax (CMS) structures: taken from RFC3852
*/
/* Forward references */
typedef struct CMS_IssuerAndSerialNumber_st CMS_IssuerAndSerialNumber;
typedef struct CMS_EncapsulatedContentInfo_st CMS_EncapsulatedContentInfo;
typedef struct CMS_SignerIdentifier_st CMS_SignerIdentifier;
typedef struct CMS_SignedData_st CMS_SignedData;
typedef struct CMS_OtherRevocationInfoFormat_st CMS_OtherRevocationInfoFormat;
typedef struct CMS_OriginatorInfo_st CMS_OriginatorInfo;
typedef struct CMS_EncryptedContentInfo_st CMS_EncryptedContentInfo;
typedef struct CMS_EnvelopedData_st CMS_EnvelopedData;
typedef struct CMS_DigestedData_st CMS_DigestedData;
typedef struct CMS_EncryptedData_st CMS_EncryptedData;
typedef struct CMS_AuthenticatedData_st CMS_AuthenticatedData;
typedef struct CMS_AuthEnvelopedData_st CMS_AuthEnvelopedData;
typedef struct CMS_CompressedData_st CMS_CompressedData;
typedef struct CMS_OtherCertificateFormat_st CMS_OtherCertificateFormat;
typedef struct CMS_KeyTransRecipientInfo_st CMS_KeyTransRecipientInfo;
typedef struct CMS_OriginatorPublicKey_st CMS_OriginatorPublicKey;
typedef struct CMS_OriginatorIdentifierOrKey_st CMS_OriginatorIdentifierOrKey;
typedef struct CMS_KeyAgreeRecipientInfo_st CMS_KeyAgreeRecipientInfo;
typedef struct CMS_RecipientKeyIdentifier_st CMS_RecipientKeyIdentifier;
typedef struct CMS_KeyAgreeRecipientIdentifier_st
CMS_KeyAgreeRecipientIdentifier;
typedef struct CMS_KEKIdentifier_st CMS_KEKIdentifier;
typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo;
typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo;
typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo;
typedef struct CMS_ReceiptsFrom_st CMS_ReceiptsFrom;
typedef struct CMS_CTX_st CMS_CTX;
struct CMS_CTX_st {
OSSL_LIB_CTX *libctx;
char *propq;
};
struct CMS_ContentInfo_st {
ASN1_OBJECT *contentType;
union {
ASN1_OCTET_STRING *data;
CMS_SignedData *signedData;
CMS_EnvelopedData *envelopedData;
CMS_DigestedData *digestedData;
CMS_EncryptedData *encryptedData;
CMS_AuthEnvelopedData *authEnvelopedData;
CMS_AuthenticatedData *authenticatedData;
CMS_CompressedData *compressedData;
ASN1_TYPE *other;
/* Other types ... */
void *otherData;
} d;
CMS_CTX ctx;
};
DEFINE_STACK_OF(CMS_CertificateChoices)
struct CMS_SignedData_st {
int32_t version;
STACK_OF(X509_ALGOR) *digestAlgorithms;
CMS_EncapsulatedContentInfo *encapContentInfo;
STACK_OF(CMS_CertificateChoices) *certificates;
STACK_OF(CMS_RevocationInfoChoice) *crls;
STACK_OF(CMS_SignerInfo) *signerInfos;
};
struct CMS_EncapsulatedContentInfo_st {
ASN1_OBJECT *eContentType;
ASN1_OCTET_STRING *eContent;
/* Set to 1 if incomplete structure only part set up */
int partial;
};
struct CMS_SignerInfo_st {
int32_t version;
CMS_SignerIdentifier *sid;
X509_ALGOR *digestAlgorithm;
STACK_OF(X509_ATTRIBUTE) *signedAttrs;
X509_ALGOR *signatureAlgorithm;
ASN1_OCTET_STRING *signature;
STACK_OF(X509_ATTRIBUTE) *unsignedAttrs;
/* Signing certificate and key */
X509 *signer;
EVP_PKEY *pkey;
/* Digest and public key context for alternative parameters */
EVP_MD_CTX *mctx;
EVP_PKEY_CTX *pctx;
const CMS_CTX *cms_ctx;
};
struct CMS_SignerIdentifier_st {
int type;
union {
CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
ASN1_OCTET_STRING *subjectKeyIdentifier;
} d;
};
struct CMS_EnvelopedData_st {
int32_t version;
CMS_OriginatorInfo *originatorInfo;
STACK_OF(CMS_RecipientInfo) *recipientInfos;
CMS_EncryptedContentInfo *encryptedContentInfo;
STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs;
};
struct CMS_OriginatorInfo_st {
STACK_OF(CMS_CertificateChoices) *certificates;
STACK_OF(CMS_RevocationInfoChoice) *crls;
};
struct CMS_EncryptedContentInfo_st {
ASN1_OBJECT *contentType;
X509_ALGOR *contentEncryptionAlgorithm;
ASN1_OCTET_STRING *encryptedContent;
/* Content encryption algorithm, key and tag */
const EVP_CIPHER *cipher;
unsigned char *key;
size_t keylen;
unsigned char *tag;
size_t taglen;
/* Set to 1 if we are debugging decrypt and don't fake keys for MMA */
int debug;
/* Set to 1 if we have no cert and need extra safety measures for MMA */
int havenocert;
};
struct CMS_RecipientInfo_st {
int type;
union {
CMS_KeyTransRecipientInfo *ktri;
CMS_KeyAgreeRecipientInfo *kari;
CMS_KEKRecipientInfo *kekri;
CMS_PasswordRecipientInfo *pwri;
CMS_OtherRecipientInfo *ori;
} d;
};
typedef CMS_SignerIdentifier CMS_RecipientIdentifier;
struct CMS_KeyTransRecipientInfo_st {
int32_t version;
CMS_RecipientIdentifier *rid;
X509_ALGOR *keyEncryptionAlgorithm;
ASN1_OCTET_STRING *encryptedKey;
/* Recipient Key and cert */
X509 *recip;
EVP_PKEY *pkey;
/* Public key context for this operation */
EVP_PKEY_CTX *pctx;
const CMS_CTX *cms_ctx;
};
struct CMS_KeyAgreeRecipientInfo_st {
int32_t version;
CMS_OriginatorIdentifierOrKey *originator;
ASN1_OCTET_STRING *ukm;
X509_ALGOR *keyEncryptionAlgorithm;
STACK_OF(CMS_RecipientEncryptedKey) *recipientEncryptedKeys;
/* Public key context associated with current operation */
EVP_PKEY_CTX *pctx;
/* Cipher context for CEK wrapping */
EVP_CIPHER_CTX *ctx;
const CMS_CTX *cms_ctx;
};
struct CMS_OriginatorIdentifierOrKey_st {
int type;
union {
CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
ASN1_OCTET_STRING *subjectKeyIdentifier;
CMS_OriginatorPublicKey *originatorKey;
} d;
};
struct CMS_OriginatorPublicKey_st {
X509_ALGOR *algorithm;
ASN1_BIT_STRING *publicKey;
};
struct CMS_RecipientEncryptedKey_st {
CMS_KeyAgreeRecipientIdentifier *rid;
ASN1_OCTET_STRING *encryptedKey;
/* Public key associated with this recipient */
EVP_PKEY *pkey;
};
struct CMS_KeyAgreeRecipientIdentifier_st {
int type;
union {
CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
CMS_RecipientKeyIdentifier *rKeyId;
} d;
};
struct CMS_RecipientKeyIdentifier_st {
ASN1_OCTET_STRING *subjectKeyIdentifier;
ASN1_GENERALIZEDTIME *date;
CMS_OtherKeyAttribute *other;
};
struct CMS_KEKRecipientInfo_st {
int32_t version;
CMS_KEKIdentifier *kekid;
X509_ALGOR *keyEncryptionAlgorithm;
ASN1_OCTET_STRING *encryptedKey;
/* Extra info: symmetric key to use */
unsigned char *key;
size_t keylen;
const CMS_CTX *cms_ctx;
};
struct CMS_KEKIdentifier_st {
ASN1_OCTET_STRING *keyIdentifier;
ASN1_GENERALIZEDTIME *date;
CMS_OtherKeyAttribute *other;
};
struct CMS_PasswordRecipientInfo_st {
int32_t version;
X509_ALGOR *keyDerivationAlgorithm;
X509_ALGOR *keyEncryptionAlgorithm;
ASN1_OCTET_STRING *encryptedKey;
/* Extra info: password to use */
unsigned char *pass;
size_t passlen;
const CMS_CTX *cms_ctx;
};
struct CMS_OtherRecipientInfo_st {
ASN1_OBJECT *oriType;
ASN1_TYPE *oriValue;
};
struct CMS_DigestedData_st {
int32_t version;
X509_ALGOR *digestAlgorithm;
CMS_EncapsulatedContentInfo *encapContentInfo;
ASN1_OCTET_STRING *digest;
};
struct CMS_EncryptedData_st {
int32_t version;
CMS_EncryptedContentInfo *encryptedContentInfo;
STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs;
};
struct CMS_AuthenticatedData_st {
int32_t version;
CMS_OriginatorInfo *originatorInfo;
STACK_OF(CMS_RecipientInfo) *recipientInfos;
X509_ALGOR *macAlgorithm;
X509_ALGOR *digestAlgorithm;
CMS_EncapsulatedContentInfo *encapContentInfo;
STACK_OF(X509_ATTRIBUTE) *authAttrs;
ASN1_OCTET_STRING *mac;
STACK_OF(X509_ATTRIBUTE) *unauthAttrs;
};
struct CMS_AuthEnvelopedData_st {
int32_t version;
CMS_OriginatorInfo *originatorInfo;
STACK_OF(CMS_RecipientInfo) *recipientInfos;
CMS_EncryptedContentInfo *authEncryptedContentInfo;
STACK_OF(X509_ATTRIBUTE) *authAttrs;
ASN1_OCTET_STRING *mac;
STACK_OF(X509_ATTRIBUTE) *unauthAttrs;
};
struct CMS_CompressedData_st {
int32_t version;
X509_ALGOR *compressionAlgorithm;
STACK_OF(CMS_RecipientInfo) *recipientInfos;
CMS_EncapsulatedContentInfo *encapContentInfo;
};
struct CMS_RevocationInfoChoice_st {
int type;
union {
X509_CRL *crl;
CMS_OtherRevocationInfoFormat *other;
} d;
};
# define CMS_REVCHOICE_CRL 0
# define CMS_REVCHOICE_OTHER 1
struct CMS_OtherRevocationInfoFormat_st {
ASN1_OBJECT *otherRevInfoFormat;
ASN1_TYPE *otherRevInfo;
};
struct CMS_CertificateChoices {
int type;
union {
X509 *certificate;
ASN1_STRING *extendedCertificate; /* Obsolete */
ASN1_STRING *v1AttrCert; /* Left encoded for now */
ASN1_STRING *v2AttrCert; /* Left encoded for now */
CMS_OtherCertificateFormat *other;
} d;
};
# define CMS_CERTCHOICE_CERT 0
# define CMS_CERTCHOICE_EXCERT 1
# define CMS_CERTCHOICE_V1ACERT 2
# define CMS_CERTCHOICE_V2ACERT 3
# define CMS_CERTCHOICE_OTHER 4
struct CMS_OtherCertificateFormat_st {
ASN1_OBJECT *otherCertFormat;
ASN1_TYPE *otherCert;
};
/*
* This is also defined in pkcs7.h but we duplicate it to allow the CMS code
* to be independent of PKCS#7
*/
struct CMS_IssuerAndSerialNumber_st {
X509_NAME *issuer;
ASN1_INTEGER *serialNumber;
};
struct CMS_OtherKeyAttribute_st {
ASN1_OBJECT *keyAttrId;
ASN1_TYPE *keyAttr;
};
/* ESS structures */
struct CMS_ReceiptRequest_st {
ASN1_OCTET_STRING *signedContentIdentifier;
CMS_ReceiptsFrom *receiptsFrom;
STACK_OF(GENERAL_NAMES) *receiptsTo;
};
struct CMS_ReceiptsFrom_st {
int type;
union {
int32_t allOrFirstTier;
STACK_OF(GENERAL_NAMES) *receiptList;
} d;
};
struct CMS_Receipt_st {
int32_t version;
ASN1_OBJECT *contentType;
ASN1_OCTET_STRING *signedContentIdentifier;
ASN1_OCTET_STRING *originatorSignatureValue;
};
DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
DECLARE_ASN1_ITEM(CMS_SignerInfo)
+DECLARE_ASN1_ITEM(CMS_EncryptedContentInfo)
DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber)
DECLARE_ASN1_ITEM(CMS_Attributes_Sign)
DECLARE_ASN1_ITEM(CMS_Attributes_Verify)
DECLARE_ASN1_ITEM(CMS_RecipientInfo)
DECLARE_ASN1_ITEM(CMS_PasswordRecipientInfo)
DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber)
# define CMS_SIGNERINFO_ISSUER_SERIAL 0
# define CMS_SIGNERINFO_KEYIDENTIFIER 1
# define CMS_RECIPINFO_ISSUER_SERIAL 0
# define CMS_RECIPINFO_KEYIDENTIFIER 1
# define CMS_REK_ISSUER_SERIAL 0
# define CMS_REK_KEYIDENTIFIER 1
# define CMS_OIK_ISSUER_SERIAL 0
# define CMS_OIK_KEYIDENTIFIER 1
# define CMS_OIK_PUBKEY 2
BIO *ossl_cms_content_bio(CMS_ContentInfo *cms);
const CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms);
OSSL_LIB_CTX *ossl_cms_ctx_get0_libctx(const CMS_CTX *ctx);
const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx);
void ossl_cms_resolve_libctx(CMS_ContentInfo *ci);
CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *ctx, const char *propq);
CMS_ContentInfo *ossl_cms_DigestedData_create(const EVP_MD *md,
OSSL_LIB_CTX *libctx,
const char *propq);
BIO *ossl_cms_DigestedData_init_bio(const CMS_ContentInfo *cms);
int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms,
BIO *chain, int verify);
BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms);
int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain);
int ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
int type, const CMS_CTX *ctx);
int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
ASN1_OCTET_STRING **keyid,
X509_NAME **issuer,
ASN1_INTEGER **sno);
int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert);
CMS_ContentInfo *ossl_cms_CompressedData_create(int comp_nid,
OSSL_LIB_CTX *libctx,
const char *propq);
BIO *ossl_cms_CompressedData_init_bio(const CMS_ContentInfo *cms);
BIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
const CMS_CTX *ctx);
int ossl_cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
X509_ALGOR *mdalg);
int ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert);
int ossl_cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert);
int ossl_cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert);
int ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert);
BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
const CMS_CTX *ctx);
BIO *ossl_cms_EncryptedData_init_bio(const CMS_ContentInfo *cms);
int ossl_cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
const EVP_CIPHER *cipher,
const unsigned char *key, size_t keylen,
const CMS_CTX *ctx);
int ossl_cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms);
int ossl_cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
ASN1_OCTET_STRING *ossl_cms_encode_Receipt(CMS_SignerInfo *si);
BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain);
BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms);
int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio);
-void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf);
CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms);
CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms);
CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms);
/* RecipientInfo routines */
int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd);
int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk);
int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type);
void ossl_cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms);
/* KARI routines */
int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
EVP_PKEY *recipPubKey, X509 *originator,
EVP_PKEY *originatorPrivKey,
unsigned int flags,
const CMS_CTX *ctx);
int ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
CMS_RecipientInfo *ri);
/* PWRI routines */
int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
CMS_RecipientInfo *ri, int en_de);
/* SignerInfo routines */
int ossl_cms_si_check_attributes(const CMS_SignerInfo *si);
void ossl_cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms);
/* ESS routines */
int ossl_cms_check_signing_certs(const CMS_SignerInfo *si,
const STACK_OF(X509) *chain);
int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt);
int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt);
int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt);
int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify);
int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify);
DECLARE_ASN1_ITEM(CMS_CertificateChoices)
DECLARE_ASN1_ITEM(CMS_DigestedData)
DECLARE_ASN1_ITEM(CMS_EncryptedData)
DECLARE_ASN1_ITEM(CMS_EnvelopedData)
DECLARE_ASN1_ITEM(CMS_AuthEnvelopedData)
DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
DECLARE_ASN1_ITEM(CMS_KeyAgreeRecipientInfo)
DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
DECLARE_ASN1_ITEM(CMS_OriginatorPublicKey)
DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)
DECLARE_ASN1_ITEM(CMS_Receipt)
DECLARE_ASN1_ITEM(CMS_ReceiptRequest)
DECLARE_ASN1_ITEM(CMS_RecipientEncryptedKey)
DECLARE_ASN1_ITEM(CMS_RecipientKeyIdentifier)
DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice)
DECLARE_ASN1_ITEM(CMS_SignedData)
DECLARE_ASN1_ITEM(CMS_CompressedData)
#endif
diff --git a/crypto/openssl/crypto/cms/cms_rsa.c b/crypto/openssl/crypto/cms/cms_rsa.c
index 12bc81843897..5e26e89d5012 100644
--- a/crypto/openssl/crypto/cms/cms_rsa.c
+++ b/crypto/openssl/crypto/cms/cms_rsa.c
@@ -1,280 +1,283 @@
/*
* Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <openssl/cms.h>
#include <openssl/err.h>
#include <openssl/core_names.h>
#include "crypto/asn1.h"
#include "crypto/rsa.h"
#include "crypto/evp.h"
#include "cms_local.h"
static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg)
{
RSA_OAEP_PARAMS *oaep;
oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
alg->parameter);
if (oaep == NULL)
return NULL;
if (oaep->maskGenFunc != NULL) {
oaep->maskHash = ossl_x509_algor_mgf1_decode(oaep->maskGenFunc);
if (oaep->maskHash == NULL) {
RSA_OAEP_PARAMS_free(oaep);
return NULL;
}
}
return oaep;
}
static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
{
EVP_PKEY_CTX *pkctx;
X509_ALGOR *cmsalg;
int nid;
int rv = -1;
unsigned char *label = NULL;
int labellen = 0;
const EVP_MD *mgf1md = NULL, *md = NULL;
RSA_OAEP_PARAMS *oaep;
pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (pkctx == NULL)
return 0;
if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
return -1;
nid = OBJ_obj2nid(cmsalg->algorithm);
if (nid == NID_rsaEncryption)
return 1;
if (nid != NID_rsaesOaep) {
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE);
return -1;
}
/* Decode OAEP parameters */
oaep = rsa_oaep_decode(cmsalg);
if (oaep == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_OAEP_PARAMETERS);
goto err;
}
mgf1md = ossl_x509_algor_get_md(oaep->maskHash);
if (mgf1md == NULL)
goto err;
md = ossl_x509_algor_get_md(oaep->hashFunc);
if (md == NULL)
goto err;
if (oaep->pSourceFunc != NULL) {
X509_ALGOR *plab = oaep->pSourceFunc;
if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_LABEL_SOURCE);
goto err;
}
if (plab->parameter->type != V_ASN1_OCTET_STRING) {
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_LABEL);
goto err;
}
label = plab->parameter->value.octet_string->data;
/* Stop label being freed when OAEP parameters are freed */
plab->parameter->value.octet_string->data = NULL;
labellen = plab->parameter->value.octet_string->length;
}
if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0)
goto err;
if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0)
goto err;
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
goto err;
if (label != NULL
&& EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0) {
OPENSSL_free(label);
goto err;
}
/* Carry on */
rv = 1;
err:
RSA_OAEP_PARAMS_free(oaep);
return rv;
}
static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
{
const EVP_MD *md, *mgf1md;
RSA_OAEP_PARAMS *oaep = NULL;
ASN1_STRING *os = NULL;
ASN1_OCTET_STRING *los = NULL;
X509_ALGOR *alg;
EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
unsigned char *label;
if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0)
return 0;
if (pkctx != NULL) {
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
return 0;
}
if (pad_mode == RSA_PKCS1_PADDING)
return X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption),
V_ASN1_NULL, NULL);
/* Not supported */
if (pad_mode != RSA_PKCS1_OAEP_PADDING)
return 0;
if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0)
goto err;
if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
goto err;
labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label);
if (labellen < 0)
goto err;
oaep = RSA_OAEP_PARAMS_new();
if (oaep == NULL)
goto err;
if (!ossl_x509_algor_new_from_md(&oaep->hashFunc, md))
goto err;
if (!ossl_x509_algor_md_to_mgf1(&oaep->maskGenFunc, mgf1md))
goto err;
if (labellen > 0) {
oaep->pSourceFunc = X509_ALGOR_new();
if (oaep->pSourceFunc == NULL)
goto err;
los = ASN1_OCTET_STRING_new();
if (los == NULL)
goto err;
if (!ASN1_OCTET_STRING_set(los, label, labellen))
goto err;
if (!X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
V_ASN1_OCTET_STRING, los))
goto err;
los = NULL;
}
/* create string with oaep parameter encoding. */
if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os))
goto err;
if (!X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os))
goto err;
os = NULL;
rv = 1;
err:
RSA_OAEP_PARAMS_free(oaep);
ASN1_STRING_free(os);
ASN1_OCTET_STRING_free(los);
return rv;
}
int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt)
{
assert(decrypt == 0 || decrypt == 1);
if (decrypt == 1)
return rsa_cms_decrypt(ri);
if (decrypt == 0)
return rsa_cms_encrypt(ri);
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
static int rsa_cms_sign(CMS_SignerInfo *si)
{
int pad_mode = RSA_PKCS1_PADDING;
X509_ALGOR *alg;
EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
unsigned char aid[128];
const unsigned char *pp = aid;
size_t aid_len = 0;
OSSL_PARAM params[2];
CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
if (pkctx != NULL) {
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
return 0;
}
if (pad_mode == RSA_PKCS1_PADDING) {
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
return 1;
}
/* We don't support it */
if (pad_mode != RSA_PKCS1_PSS_PADDING)
return 0;
if (evp_pkey_ctx_is_legacy(pkctx)) {
/* No provider -> we cannot query it for algorithm ID. */
ASN1_STRING *os = NULL;
os = ossl_rsa_ctx_to_pss_string(pkctx);
if (os == NULL)
return 0;
- return X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os);
+ if (X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os))
+ return 1;
+ ASN1_STRING_free(os);
+ return 0;
}
params[0] = OSSL_PARAM_construct_octet_string(
OSSL_SIGNATURE_PARAM_ALGORITHM_ID, aid, sizeof(aid));
params[1] = OSSL_PARAM_construct_end();
if (EVP_PKEY_CTX_get_params(pkctx, params) <= 0)
return 0;
if ((aid_len = params[0].return_size) == 0)
return 0;
if (d2i_X509_ALGOR(&alg, &pp, aid_len) == NULL)
return 0;
return 1;
}
static int rsa_cms_verify(CMS_SignerInfo *si)
{
int nid, nid2;
X509_ALGOR *alg;
EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pkctx);
CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
nid = OBJ_obj2nid(alg->algorithm);
if (nid == EVP_PKEY_RSA_PSS)
return ossl_rsa_pss_to_ctx(NULL, pkctx, alg, NULL) > 0;
/* Only PSS allowed for PSS keys */
if (EVP_PKEY_is_a(pkey, "RSA-PSS")) {
ERR_raise(ERR_LIB_RSA, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return 0;
}
if (nid == NID_rsaEncryption)
return 1;
/* Workaround for some implementation that use a signature OID */
if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
if (nid2 == NID_rsaEncryption)
return 1;
}
return 0;
}
int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify)
{
assert(verify == 0 || verify == 1);
if (verify == 1)
return rsa_cms_verify(si);
if (verify == 0)
return rsa_cms_sign(si);
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
diff --git a/crypto/openssl/crypto/cms/cms_sd.c b/crypto/openssl/crypto/cms/cms_sd.c
index 3a21664e9da2..4758d048386e 100644
--- a/crypto/openssl/crypto/cms/cms_sd.c
+++ b/crypto/openssl/crypto/cms/cms_sd.c
@@ -1,1100 +1,1116 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/asn1t.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
#include <openssl/ess.h>
#include "internal/sizes.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/ess.h"
#include "crypto/x509.h" /* for ossl_x509_add_cert_new() */
#include "cms_local.h"
/* CMS SignedData Utilities */
static CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms)
{
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) {
ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
return NULL;
}
return cms->d.signedData;
}
static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
{
if (cms->d.other == NULL) {
cms->d.signedData = M_ASN1_new_of(CMS_SignedData);
if (!cms->d.signedData) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
cms->d.signedData->version = 1;
cms->d.signedData->encapContentInfo->eContentType =
OBJ_nid2obj(NID_pkcs7_data);
cms->d.signedData->encapContentInfo->partial = 1;
ASN1_OBJECT_free(cms->contentType);
cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
return cms->d.signedData;
}
return cms_get0_signed(cms);
}
/* Just initialise SignedData e.g. for certs only structure */
int CMS_SignedData_init(CMS_ContentInfo *cms)
{
if (cms_signed_data_init(cms))
return 1;
else
return 0;
}
/* Check structures and fixup version numbers (if necessary) */
static void cms_sd_set_version(CMS_SignedData *sd)
{
int i;
CMS_CertificateChoices *cch;
CMS_RevocationInfoChoice *rch;
CMS_SignerInfo *si;
for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) {
cch = sk_CMS_CertificateChoices_value(sd->certificates, i);
if (cch->type == CMS_CERTCHOICE_OTHER) {
if (sd->version < 5)
sd->version = 5;
} else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
if (sd->version < 4)
sd->version = 4;
} else if (cch->type == CMS_CERTCHOICE_V1ACERT) {
if (sd->version < 3)
sd->version = 3;
}
}
for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) {
rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i);
if (rch->type == CMS_REVCHOICE_OTHER) {
if (sd->version < 5)
sd->version = 5;
}
}
if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data)
&& (sd->version < 3))
sd->version = 3;
for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
if (si->version < 3)
si->version = 3;
if (sd->version < 3)
sd->version = 3;
} else if (si->version < 1)
si->version = 1;
}
if (sd->version < 1)
sd->version = 1;
}
/*
* RFC 5652 Section 11.1 Content Type
* The content-type attribute within signed-data MUST
* 1) be present if there are signed attributes
* 2) match the content type in the signed-data,
* 3) be a signed attribute.
* 4) not have more than one copy of the attribute.
*
* Note that since the CMS_SignerInfo_sign() always adds the "signing time"
* attribute, the content type attribute MUST be added also.
* Assumptions: This assumes that the attribute does not already exist.
*/
static int cms_set_si_contentType_attr(CMS_ContentInfo *cms, CMS_SignerInfo *si)
{
ASN1_OBJECT *ctype = cms->d.signedData->encapContentInfo->eContentType;
/* Add the contentType attribute */
return CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
V_ASN1_OBJECT, ctype, -1) > 0;
}
/* Copy an existing messageDigest value */
static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
{
STACK_OF(CMS_SignerInfo) *sinfos;
CMS_SignerInfo *sitmp;
int i;
sinfos = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
ASN1_OCTET_STRING *messageDigest;
sitmp = sk_CMS_SignerInfo_value(sinfos, i);
if (sitmp == si)
continue;
if (CMS_signed_get_attr_count(sitmp) < 0)
continue;
if (OBJ_cmp(si->digestAlgorithm->algorithm,
sitmp->digestAlgorithm->algorithm))
continue;
messageDigest = CMS_signed_get0_data_by_OBJ(sitmp,
OBJ_nid2obj
(NID_pkcs9_messageDigest),
-3, V_ASN1_OCTET_STRING);
if (!messageDigest) {
ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
return 0;
}
if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
V_ASN1_OCTET_STRING,
messageDigest, -1))
return 1;
else
return 0;
}
ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST);
return 0;
}
int ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
int type, const CMS_CTX *ctx)
{
switch (type) {
case CMS_SIGNERINFO_ISSUER_SERIAL:
if (!ossl_cms_set1_ias(&sid->d.issuerAndSerialNumber, cert))
return 0;
break;
case CMS_SIGNERINFO_KEYIDENTIFIER:
if (!ossl_cms_set1_keyid(&sid->d.subjectKeyIdentifier, cert))
return 0;
break;
default:
ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_ID);
return 0;
}
sid->type = type;
return 1;
}
int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
ASN1_OCTET_STRING **keyid,
X509_NAME **issuer,
ASN1_INTEGER **sno)
{
if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) {
if (issuer)
*issuer = sid->d.issuerAndSerialNumber->issuer;
if (sno)
*sno = sid->d.issuerAndSerialNumber->serialNumber;
} else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
if (keyid)
*keyid = sid->d.subjectKeyIdentifier;
} else
return 0;
return 1;
}
int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
{
if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL)
return ossl_cms_ias_cert_cmp(sid->d.issuerAndSerialNumber, cert);
else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
return ossl_cms_keyid_cert_cmp(sid->d.subjectKeyIdentifier, cert);
else
return -1;
}
static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
{
EVP_PKEY *pkey = si->pkey;
int i;
if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC"))
return ossl_cms_ecdsa_dsa_sign(si, cmd) > 0;
else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS"))
return ossl_cms_rsa_sign(si, cmd) > 0;
/* Something else? We'll give engines etc a chance to handle this */
if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
return 1;
i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
if (i == -2) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
if (i <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
return 0;
}
return 1;
}
/* Add SigningCertificate signed attribute to the signer info. */
static int ossl_cms_add1_signing_cert(CMS_SignerInfo *si,
const ESS_SIGNING_CERT *sc)
{
ASN1_STRING *seq = NULL;
unsigned char *p, *pp = NULL;
int ret, len = i2d_ESS_SIGNING_CERT(sc, NULL);
if (len <= 0 || (pp = OPENSSL_malloc(len)) == NULL)
return 0;
p = pp;
i2d_ESS_SIGNING_CERT(sc, &p);
if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) {
ASN1_STRING_free(seq);
OPENSSL_free(pp);
return 0;
}
OPENSSL_free(pp);
ret = CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificate,
V_ASN1_SEQUENCE, seq, -1);
ASN1_STRING_free(seq);
return ret;
}
/* Add SigningCertificateV2 signed attribute to the signer info. */
static int ossl_cms_add1_signing_cert_v2(CMS_SignerInfo *si,
const ESS_SIGNING_CERT_V2 *sc)
{
ASN1_STRING *seq = NULL;
unsigned char *p, *pp = NULL;
int ret, len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
if (len <= 0 || (pp = OPENSSL_malloc(len)) == NULL)
return 0;
p = pp;
i2d_ESS_SIGNING_CERT_V2(sc, &p);
if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) {
ASN1_STRING_free(seq);
OPENSSL_free(pp);
return 0;
}
OPENSSL_free(pp);
ret = CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificateV2,
V_ASN1_SEQUENCE, seq, -1);
ASN1_STRING_free(seq);
return ret;
}
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
unsigned int flags)
{
CMS_SignedData *sd;
CMS_SignerInfo *si = NULL;
X509_ALGOR *alg;
int i, type;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
if (!X509_check_private_key(signer, pk)) {
ERR_raise(ERR_LIB_CMS, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
return NULL;
}
sd = cms_signed_data_init(cms);
if (!sd)
goto err;
si = M_ASN1_new_of(CMS_SignerInfo);
if (!si)
goto merr;
/* Call for side-effect of computing hash and caching extensions */
X509_check_purpose(signer, -1, -1);
X509_up_ref(signer);
EVP_PKEY_up_ref(pk);
si->cms_ctx = ctx;
si->pkey = pk;
si->signer = signer;
si->mctx = EVP_MD_CTX_new();
si->pctx = NULL;
if (si->mctx == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (flags & CMS_USE_KEYID) {
si->version = 3;
if (sd->version < 3)
sd->version = 3;
type = CMS_SIGNERINFO_KEYIDENTIFIER;
} else {
type = CMS_SIGNERINFO_ISSUER_SERIAL;
si->version = 1;
}
if (!ossl_cms_set1_SignerIdentifier(si->sid, signer, type, ctx))
goto err;
if (md == NULL) {
int def_nid;
if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) {
ERR_raise_data(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST,
"pkey nid=%d", EVP_PKEY_get_id(pk));
goto err;
}
md = EVP_get_digestbynid(def_nid);
if (md == NULL) {
ERR_raise_data(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST,
"default md nid=%d", def_nid);
goto err;
}
}
if (!md) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET);
goto err;
}
if (md == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET);
goto err;
}
X509_ALGOR_set_md(si->digestAlgorithm, md);
/* See if digest is present in digestAlgorithms */
for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
const ASN1_OBJECT *aoid;
char name[OSSL_MAX_NAME_SIZE];
alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
X509_ALGOR_get0(&aoid, NULL, NULL, alg);
OBJ_obj2txt(name, sizeof(name), aoid, 0);
if (EVP_MD_is_a(md, name))
break;
}
if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) {
alg = X509_ALGOR_new();
if (alg == NULL)
goto merr;
X509_ALGOR_set_md(alg, md);
if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) {
X509_ALGOR_free(alg);
goto merr;
}
}
if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0)) {
ERR_raise_data(ERR_LIB_CMS, CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM,
"pkey nid=%d", EVP_PKEY_get_id(pk));
goto err;
}
if (!(flags & CMS_NOATTR)) {
/*
* Initialize signed attributes structure so other attributes
* such as signing time etc are added later even if we add none here.
*/
if (!si->signedAttrs) {
si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
if (!si->signedAttrs)
goto merr;
}
if (!(flags & CMS_NOSMIMECAP)) {
STACK_OF(X509_ALGOR) *smcap = NULL;
i = CMS_add_standard_smimecap(&smcap);
if (i)
i = CMS_add_smimecap(si, smcap);
sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
if (!i)
goto merr;
}
if (flags & CMS_CADES) {
ESS_SIGNING_CERT *sc = NULL;
ESS_SIGNING_CERT_V2 *sc2 = NULL;
int add_sc;
if (md == NULL || EVP_MD_is_a(md, SN_sha1)) {
if ((sc = OSSL_ESS_signing_cert_new_init(signer,
NULL, 1)) == NULL)
goto err;
add_sc = ossl_cms_add1_signing_cert(si, sc);
ESS_SIGNING_CERT_free(sc);
} else {
if ((sc2 = OSSL_ESS_signing_cert_v2_new_init(md, signer,
NULL, 1)) == NULL)
goto err;
add_sc = ossl_cms_add1_signing_cert_v2(si, sc2);
ESS_SIGNING_CERT_V2_free(sc2);
}
if (!add_sc)
goto err;
}
if (flags & CMS_REUSE_DIGEST) {
if (!cms_copy_messageDigest(cms, si))
goto err;
if (!cms_set_si_contentType_attr(cms, si))
goto err;
if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) &&
!CMS_SignerInfo_sign(si))
goto err;
}
}
if (!(flags & CMS_NOCERTS)) {
/* NB ignore -1 return for duplicate cert */
if (!CMS_add1_cert(cms, signer))
goto merr;
}
if (flags & CMS_KEY_PARAM) {
if (flags & CMS_NOATTR) {
si->pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
si->pkey,
ossl_cms_ctx_get0_propq(ctx));
if (si->pctx == NULL)
goto err;
if (EVP_PKEY_sign_init(si->pctx) <= 0)
goto err;
if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0)
goto err;
} else if (EVP_DigestSignInit_ex(si->mctx, &si->pctx,
EVP_MD_get0_name(md),
ossl_cms_ctx_get0_libctx(ctx),
ossl_cms_ctx_get0_propq(ctx),
pk, NULL) <= 0) {
+ si->pctx = NULL;
goto err;
}
+ else {
+ EVP_MD_CTX_set_flags(si->mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+ }
}
if (!sd->signerInfos)
sd->signerInfos = sk_CMS_SignerInfo_new_null();
if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si))
goto merr;
return si;
merr:
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
M_ASN1_free_of(si, CMS_SignerInfo);
return NULL;
}
void ossl_cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms)
{
int i;
CMS_SignerInfo *si;
STACK_OF(CMS_SignerInfo) *sinfos;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
ERR_set_mark();
sinfos = CMS_get0_SignerInfos(cms);
ERR_pop_to_mark(); /* removes error in case sinfos == NULL */
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
if (si != NULL)
si->cms_ctx = ctx;
}
}
static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
{
ASN1_TIME *tt;
int r = 0;
if (t != NULL)
tt = t;
else
tt = X509_gmtime_adj(NULL, 0);
if (tt == NULL)
goto merr;
if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
tt->type, tt, -1) <= 0)
goto merr;
r = 1;
merr:
if (t == NULL)
ASN1_TIME_free(tt);
if (!r)
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return r;
}
EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si)
{
return si->pctx;
}
EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si)
{
return si->mctx;
}
STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
{
CMS_SignedData *sd = cms_get0_signed(cms);
return sd != NULL ? sd->signerInfos : NULL;
}
STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
{
STACK_OF(X509) *signers = NULL;
STACK_OF(CMS_SignerInfo) *sinfos;
CMS_SignerInfo *si;
int i;
sinfos = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
if (si->signer != NULL) {
if (!ossl_x509_add_cert_new(&signers, si->signer,
X509_ADD_FLAG_DEFAULT)) {
sk_X509_free(signers);
return NULL;
}
}
}
return signers;
}
void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
{
if (signer != NULL) {
X509_up_ref(signer);
EVP_PKEY_free(si->pkey);
si->pkey = X509_get_pubkey(signer);
}
X509_free(si->signer);
si->signer = signer;
}
int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
ASN1_OCTET_STRING **keyid,
X509_NAME **issuer, ASN1_INTEGER **sno)
{
return ossl_cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno);
}
int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert)
{
return ossl_cms_SignerIdentifier_cert_cmp(si->sid, cert);
}
int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
unsigned int flags)
{
CMS_SignedData *sd;
CMS_SignerInfo *si;
CMS_CertificateChoices *cch;
STACK_OF(CMS_CertificateChoices) *certs;
X509 *x;
int i, j;
int ret = 0;
sd = cms_get0_signed(cms);
if (sd == NULL)
return -1;
certs = sd->certificates;
for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
if (si->signer != NULL)
continue;
for (j = 0; j < sk_X509_num(scerts); j++) {
x = sk_X509_value(scerts, j);
if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
CMS_SignerInfo_set1_signer_cert(si, x);
ret++;
break;
}
}
if (si->signer != NULL || (flags & CMS_NOINTERN))
continue;
for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) {
cch = sk_CMS_CertificateChoices_value(certs, j);
if (cch->type != 0)
continue;
x = cch->d.certificate;
if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
CMS_SignerInfo_set1_signer_cert(si, x);
ret++;
break;
}
}
}
return ret;
}
void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
X509 **signer, X509_ALGOR **pdig,
X509_ALGOR **psig)
{
if (pk != NULL)
*pk = si->pkey;
if (signer != NULL)
*signer = si->signer;
if (pdig != NULL)
*pdig = si->digestAlgorithm;
if (psig != NULL)
*psig = si->signatureAlgorithm;
}
ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si)
{
return si->signature;
}
static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
CMS_SignerInfo *si, BIO *chain)
{
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
int r = 0;
EVP_PKEY_CTX *pctx = NULL;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
if (mctx == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
if (si->pkey == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY);
goto err;
}
if (!ossl_cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
goto err;
/* Set SignerInfo algorithm details if we used custom parameter */
if (si->pctx && !cms_sd_asn1_ctrl(si, 0))
goto err;
/*
* If any signed attributes calculate and add messageDigest attribute
*/
if (CMS_signed_get_attr_count(si) >= 0) {
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen;
if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
goto err;
if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
V_ASN1_OCTET_STRING, md, mdlen))
goto err;
/* Copy content type across */
if (!cms_set_si_contentType_attr(cms, si))
goto err;
if (!CMS_SignerInfo_sign(si))
goto err;
} else if (si->pctx) {
unsigned char *sig;
size_t siglen;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen;
pctx = si->pctx;
+ si->pctx = NULL;
if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
goto err;
siglen = EVP_PKEY_get_size(si->pkey);
sig = OPENSSL_malloc(siglen);
if (sig == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) {
OPENSSL_free(sig);
goto err;
}
ASN1_STRING_set0(si->signature, sig, siglen);
} else {
unsigned char *sig;
unsigned int siglen;
sig = OPENSSL_malloc(EVP_PKEY_get_size(si->pkey));
if (sig == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_SignFinal_ex(mctx, sig, &siglen, si->pkey,
ossl_cms_ctx_get0_libctx(ctx),
ossl_cms_ctx_get0_propq(ctx))) {
ERR_raise(ERR_LIB_CMS, CMS_R_SIGNFINAL_ERROR);
OPENSSL_free(sig);
goto err;
}
ASN1_STRING_set0(si->signature, sig, siglen);
}
r = 1;
err:
EVP_MD_CTX_free(mctx);
EVP_PKEY_CTX_free(pctx);
return r;
}
int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
{
STACK_OF(CMS_SignerInfo) *sinfos;
CMS_SignerInfo *si;
int i;
sinfos = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
if (!cms_SignerInfo_content_sign(cms, si, chain))
return 0;
}
cms->d.signedData->encapContentInfo->partial = 0;
return 1;
}
int CMS_SignerInfo_sign(CMS_SignerInfo *si)
{
EVP_MD_CTX *mctx = si->mctx;
EVP_PKEY_CTX *pctx = NULL;
unsigned char *abuf = NULL;
int alen;
size_t siglen;
const CMS_CTX *ctx = si->cms_ctx;
char md_name[OSSL_MAX_NAME_SIZE];
if (OBJ_obj2txt(md_name, sizeof(md_name),
si->digestAlgorithm->algorithm, 0) <= 0)
return 0;
if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
if (!cms_add1_signingTime(si, NULL))
goto err;
}
if (!ossl_cms_si_check_attributes(si))
goto err;
if (si->pctx)
pctx = si->pctx;
else {
EVP_MD_CTX_reset(mctx);
if (EVP_DigestSignInit_ex(mctx, &pctx, md_name,
ossl_cms_ctx_get0_libctx(ctx),
ossl_cms_ctx_get0_propq(ctx), si->pkey,
NULL) <= 0)
goto err;
+ EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
si->pctx = pctx;
}
alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
ASN1_ITEM_rptr(CMS_Attributes_Sign));
if (!abuf)
goto err;
if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0)
goto err;
if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0)
goto err;
OPENSSL_free(abuf);
abuf = OPENSSL_malloc(siglen);
if (abuf == NULL)
goto err;
if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
goto err;
EVP_MD_CTX_reset(mctx);
ASN1_STRING_set0(si->signature, abuf, siglen);
return 1;
err:
OPENSSL_free(abuf);
EVP_MD_CTX_reset(mctx);
return 0;
}
int CMS_SignerInfo_verify(CMS_SignerInfo *si)
{
EVP_MD_CTX *mctx = NULL;
unsigned char *abuf = NULL;
int alen, r = -1;
char name[OSSL_MAX_NAME_SIZE];
const EVP_MD *md;
EVP_MD *fetched_md = NULL;
const CMS_CTX *ctx = si->cms_ctx;
OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
const char *propq = ossl_cms_ctx_get0_propq(ctx);
if (si->pkey == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_PUBLIC_KEY);
return -1;
}
if (!ossl_cms_si_check_attributes(si))
return -1;
OBJ_obj2txt(name, sizeof(name), si->digestAlgorithm->algorithm, 0);
(void)ERR_set_mark();
fetched_md = EVP_MD_fetch(libctx, name, propq);
if (fetched_md != NULL)
md = fetched_md;
else
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
if (md == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
return -1;
}
(void)ERR_pop_to_mark();
if (si->mctx == NULL && (si->mctx = EVP_MD_CTX_new()) == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
mctx = si->mctx;
+ if (si->pctx != NULL) {
+ EVP_PKEY_CTX_free(si->pctx);
+ si->pctx = NULL;
+ }
if (EVP_DigestVerifyInit_ex(mctx, &si->pctx, EVP_MD_get0_name(md), libctx,
- propq, si->pkey, NULL) <= 0)
+ propq, si->pkey, NULL) <= 0) {
+ si->pctx = NULL;
goto err;
+ }
+ EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
if (!cms_sd_asn1_ctrl(si, 1))
goto err;
alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
ASN1_ITEM_rptr(CMS_Attributes_Verify));
if (abuf == NULL || alen < 0)
goto err;
r = EVP_DigestVerifyUpdate(mctx, abuf, alen);
OPENSSL_free(abuf);
if (r <= 0) {
r = -1;
goto err;
}
r = EVP_DigestVerifyFinal(mctx,
si->signature->data, si->signature->length);
if (r <= 0)
ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
err:
EVP_MD_free(fetched_md);
EVP_MD_CTX_reset(mctx);
return r;
}
/* Create a chain of digest BIOs from a CMS ContentInfo */
BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms)
{
int i;
CMS_SignedData *sd;
BIO *chain = NULL;
sd = cms_get0_signed(cms);
if (sd == NULL)
return NULL;
if (cms->d.signedData->encapContentInfo->partial)
cms_sd_set_version(sd);
for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
X509_ALGOR *digestAlgorithm;
BIO *mdbio;
digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
mdbio = ossl_cms_DigestAlgorithm_init_bio(digestAlgorithm,
ossl_cms_get0_cmsctx(cms));
if (mdbio == NULL)
goto err;
if (chain != NULL)
BIO_push(chain, mdbio);
else
chain = mdbio;
}
return chain;
err:
BIO_free_all(chain);
return NULL;
}
int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
{
ASN1_OCTET_STRING *os = NULL;
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
EVP_PKEY_CTX *pkctx = NULL;
int r = -1;
unsigned char mval[EVP_MAX_MD_SIZE];
unsigned int mlen;
if (mctx == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
/* If we have any signed attributes look for messageDigest value */
if (CMS_signed_get_attr_count(si) >= 0) {
os = CMS_signed_get0_data_by_OBJ(si,
OBJ_nid2obj(NID_pkcs9_messageDigest),
-3, V_ASN1_OCTET_STRING);
if (os == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
goto err;
}
}
if (!ossl_cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
goto err;
if (EVP_DigestFinal_ex(mctx, mval, &mlen) <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
goto err;
}
/* If messageDigest found compare it */
if (os != NULL) {
if (mlen != (unsigned int)os->length) {
ERR_raise(ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
goto err;
}
if (memcmp(mval, os->data, mlen)) {
ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
r = 0;
} else
r = 1;
} else {
const EVP_MD *md = EVP_MD_CTX_get0_md(mctx);
const CMS_CTX *ctx = si->cms_ctx;
pkctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
si->pkey,
ossl_cms_ctx_get0_propq(ctx));
if (pkctx == NULL)
goto err;
if (EVP_PKEY_verify_init(pkctx) <= 0)
goto err;
if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0)
goto err;
si->pctx = pkctx;
- if (!cms_sd_asn1_ctrl(si, 1))
+ if (!cms_sd_asn1_ctrl(si, 1)) {
+ si->pctx = NULL;
goto err;
+ }
+ si->pctx = NULL;
r = EVP_PKEY_verify(pkctx, si->signature->data,
si->signature->length, mval, mlen);
if (r <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
r = 0;
}
}
err:
EVP_PKEY_CTX_free(pkctx);
EVP_MD_CTX_free(mctx);
return r;
}
int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs)
{
unsigned char *smder = NULL;
int smderlen, r;
smderlen = i2d_X509_ALGORS(algs, &smder);
if (smderlen <= 0)
return 0;
r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities,
V_ASN1_SEQUENCE, smder, smderlen);
OPENSSL_free(smder);
return r;
}
int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
int algnid, int keysize)
{
X509_ALGOR *alg = NULL;
ASN1_INTEGER *key = NULL;
if (keysize > 0) {
key = ASN1_INTEGER_new();
if (key == NULL || !ASN1_INTEGER_set(key, keysize))
goto err;
}
alg = X509_ALGOR_new();
if (alg == NULL)
goto err;
if (!X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key))
goto err;
key = NULL;
if (*algs == NULL)
*algs = sk_X509_ALGOR_new_null();
if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg))
goto err;
return 1;
err:
ASN1_INTEGER_free(key);
X509_ALGOR_free(alg);
return 0;
}
/* Check to see if a cipher exists and if so add S/MIME capabilities */
static int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
{
if (EVP_get_cipherbynid(nid))
return CMS_add_simple_smimecap(sk, nid, arg);
return 1;
}
static int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
{
if (EVP_get_digestbynid(nid))
return CMS_add_simple_smimecap(sk, nid, arg);
return 1;
}
int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap)
{
if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
|| !cms_add_digest_smcap(smcap, NID_id_GostR3411_2012_256, -1)
|| !cms_add_digest_smcap(smcap, NID_id_GostR3411_2012_512, -1)
|| !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1)
|| !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1)
|| !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1)
|| !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1)
|| !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1)
|| !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128)
|| !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64)
|| !cms_add_cipher_smcap(smcap, NID_des_cbc, -1)
|| !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40))
return 0;
return 1;
}
diff --git a/crypto/openssl/crypto/cms/cms_smime.c b/crypto/openssl/crypto/cms/cms_smime.c
index d7719267c8c8..65da2452fcea 100644
--- a/crypto/openssl/crypto/cms/cms_smime.c
+++ b/crypto/openssl/crypto/cms/cms_smime.c
@@ -1,977 +1,978 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
#include "cms_local.h"
#include "crypto/asn1.h"
static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
{
BIO *rbio;
if (out == NULL)
rbio = BIO_new(BIO_s_null());
else if (flags & CMS_TEXT) {
rbio = BIO_new(BIO_s_mem());
BIO_set_mem_eof_return(rbio, 0);
} else
rbio = out;
return rbio;
}
static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
{
unsigned char buf[4096];
int r = 0, i;
BIO *tmpout;
tmpout = cms_get_text_bio(out, flags);
if (tmpout == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Read all content through chain to process digest, decrypt etc */
for (;;) {
i = BIO_read(in, buf, sizeof(buf));
if (i <= 0) {
if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
if (BIO_get_cipher_status(in) <= 0)
goto err;
}
if (i < 0)
goto err;
break;
}
if (tmpout != NULL && (BIO_write(tmpout, buf, i) != i))
goto err;
}
if (flags & CMS_TEXT) {
if (!SMIME_text(tmpout, out)) {
ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
goto err;
}
}
r = 1;
err:
if (tmpout != out)
BIO_free(tmpout);
return r;
}
static int check_content(CMS_ContentInfo *cms)
{
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
if (pos == NULL || *pos == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
return 0;
}
return 1;
}
static void do_free_upto(BIO *f, BIO *upto)
{
if (upto != NULL) {
BIO *tbio;
do {
tbio = BIO_pop(f);
BIO_free(f);
f = tbio;
} while (f != NULL && f != upto);
} else {
BIO_free_all(f);
}
}
int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
{
BIO *cont;
int r;
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_DATA);
return 0;
}
cont = CMS_dataInit(cms, NULL);
if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
BIO_free_all(cont);
return r;
}
CMS_ContentInfo *CMS_data_create_ex(BIO *in, unsigned int flags,
OSSL_LIB_CTX *libctx, const char *propq)
{
CMS_ContentInfo *cms = ossl_cms_Data_create(libctx, propq);
if (cms == NULL)
return NULL;
if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
return cms;
CMS_ContentInfo_free(cms);
return NULL;
}
CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
{
return CMS_data_create_ex(in, flags, NULL, NULL);
}
int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
unsigned int flags)
{
BIO *cont;
int r;
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_DIGESTED_DATA);
return 0;
}
if (dcont == NULL && !check_content(cms))
return 0;
cont = CMS_dataInit(cms, dcont);
if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
if (r)
r = ossl_cms_DigestedData_do_final(cms, cont, 1);
do_free_upto(cont, dcont);
return r;
}
CMS_ContentInfo *CMS_digest_create_ex(BIO *in, const EVP_MD *md,
unsigned int flags, OSSL_LIB_CTX *ctx,
const char *propq)
{
CMS_ContentInfo *cms;
/*
* Because the EVP_MD is cached and can be a legacy algorithm, we
* cannot fetch the algorithm if it isn't supplied.
*/
if (md == NULL)
md = EVP_sha1();
cms = ossl_cms_DigestedData_create(md, ctx, propq);
if (cms == NULL)
return NULL;
if (!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
return cms;
CMS_ContentInfo_free(cms);
return NULL;
}
CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
unsigned int flags)
{
return CMS_digest_create_ex(in, md, flags, NULL, NULL);
}
int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
const unsigned char *key, size_t keylen,
BIO *dcont, BIO *out, unsigned int flags)
{
BIO *cont;
int r;
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENCRYPTED_DATA);
return 0;
}
if (dcont == NULL && !check_content(cms))
return 0;
if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
return 0;
cont = CMS_dataInit(cms, dcont);
if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
do_free_upto(cont, dcont);
return r;
}
CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
const unsigned char *key,
size_t keylen, unsigned int flags,
OSSL_LIB_CTX *libctx,
const char *propq)
{
CMS_ContentInfo *cms;
if (cipher == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER);
return NULL;
}
cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL)
return NULL;
if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
- return NULL;
+ goto err;
if (!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
if ((flags & (CMS_STREAM | CMS_PARTIAL))
|| CMS_final(cms, in, NULL, flags))
return cms;
+ err:
CMS_ContentInfo_free(cms);
return NULL;
}
CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
const unsigned char *key,
size_t keylen, unsigned int flags)
{
return CMS_EncryptedData_encrypt_ex(in, cipher, key, keylen, flags, NULL,
NULL);
}
static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
X509_STORE *store,
STACK_OF(X509) *certs,
STACK_OF(X509_CRL) *crls,
STACK_OF(X509) **chain,
const CMS_CTX *cms_ctx)
{
X509_STORE_CTX *ctx;
X509 *signer;
int i, j, r = 0;
ctx = X509_STORE_CTX_new_ex(ossl_cms_ctx_get0_libctx(cms_ctx),
ossl_cms_ctx_get0_propq(cms_ctx));
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
if (!X509_STORE_CTX_init(ctx, store, signer, certs)) {
ERR_raise(ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR);
goto err;
}
X509_STORE_CTX_set_default(ctx, "smime_sign");
if (crls != NULL)
X509_STORE_CTX_set0_crls(ctx, crls);
i = X509_verify_cert(ctx);
if (i <= 0) {
j = X509_STORE_CTX_get_error(ctx);
ERR_raise_data(ERR_LIB_CMS, CMS_R_CERTIFICATE_VERIFY_ERROR,
"Verify error: %s", X509_verify_cert_error_string(j));
goto err;
}
r = 1;
/* also send back the trust chain when required */
if (chain != NULL)
*chain = X509_STORE_CTX_get1_chain(ctx);
err:
X509_STORE_CTX_free(ctx);
return r;
}
int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
{
CMS_SignerInfo *si;
STACK_OF(CMS_SignerInfo) *sinfos;
STACK_OF(X509) *cms_certs = NULL;
STACK_OF(X509_CRL) *crls = NULL;
STACK_OF(X509) **si_chains = NULL;
X509 *signer;
int i, scount = 0, ret = 0;
BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
int cadesVerify = (flags & CMS_CADES) != 0;
const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
if (dcont == NULL && !check_content(cms))
return 0;
if (dcont != NULL && !(flags & CMS_BINARY)) {
const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
flags |= CMS_ASCIICRLF;
}
/* Attempt to find all signer certificates */
sinfos = CMS_get0_SignerInfos(cms);
if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_SIGNERS);
goto err;
}
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
if (signer)
scount++;
}
if (scount != sk_CMS_SignerInfo_num(sinfos))
scount += CMS_set1_signers_certs(cms, certs, flags);
if (scount != sk_CMS_SignerInfo_num(sinfos)) {
ERR_raise(ERR_LIB_CMS, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
goto err;
}
/* Attempt to verify all signers certs */
/* at this point scount == sk_CMS_SignerInfo_num(sinfos) */
if ((flags & CMS_NO_SIGNER_CERT_VERIFY) == 0 || cadesVerify) {
if (cadesVerify) {
/* Certificate trust chain is required to check CAdES signature */
si_chains = OPENSSL_zalloc(scount * sizeof(si_chains[0]));
if (si_chains == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
}
cms_certs = CMS_get1_certs(cms);
if (!(flags & CMS_NOCRL))
crls = CMS_get1_crls(cms);
for (i = 0; i < scount; i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls,
si_chains ? &si_chains[i] : NULL,
ctx))
goto err;
}
}
/* Attempt to verify all SignerInfo signed attribute signatures */
if ((flags & CMS_NO_ATTR_VERIFY) == 0 || cadesVerify) {
for (i = 0; i < scount; i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
if (CMS_signed_get_attr_count(si) < 0)
continue;
if (CMS_SignerInfo_verify(si) <= 0)
goto err;
if (cadesVerify) {
STACK_OF(X509) *si_chain = si_chains ? si_chains[i] : NULL;
if (ossl_cms_check_signing_certs(si, si_chain) <= 0)
goto err;
}
}
}
/*
* Performance optimization: if the content is a memory BIO then store
* its contents in a temporary read only memory BIO. This avoids
* potentially large numbers of slow copies of data which will occur when
* reading from a read write memory BIO when signatures are calculated.
*/
if (dcont != NULL && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
char *ptr;
long len;
len = BIO_get_mem_data(dcont, &ptr);
tmpin = (len == 0) ? dcont : BIO_new_mem_buf(ptr, len);
if (tmpin == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err2;
}
} else {
tmpin = dcont;
}
/*
* If not binary mode and detached generate digests by *writing* through
* the BIO. That makes it possible to canonicalise the input.
*/
if (!(flags & SMIME_BINARY) && dcont) {
/*
* Create output BIO so we can either handle text or to ensure
* included content doesn't override detached content.
*/
tmpout = cms_get_text_bio(out, flags);
if (tmpout == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
cmsbio = CMS_dataInit(cms, tmpout);
if (cmsbio == NULL)
goto err;
/*
* Don't use SMIME_TEXT for verify: it adds headers and we want to
* remove them.
*/
if (!SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT))
goto err;
if (flags & CMS_TEXT) {
if (!SMIME_text(tmpout, out)) {
ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
goto err;
}
}
} else {
cmsbio = CMS_dataInit(cms, tmpin);
if (cmsbio == NULL)
goto err;
if (!cms_copy_content(out, cmsbio, flags))
goto err;
}
if (!(flags & CMS_NO_CONTENT_VERIFY)) {
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_VERIFY_ERROR);
goto err;
}
}
}
ret = 1;
err:
if (!(flags & SMIME_BINARY) && dcont) {
do_free_upto(cmsbio, tmpout);
if (tmpin != dcont)
BIO_free(tmpin);
} else {
if (dcont && (tmpin == dcont))
do_free_upto(cmsbio, dcont);
else
BIO_free_all(cmsbio);
}
if (out != tmpout)
BIO_free_all(tmpout);
err2:
if (si_chains != NULL) {
for (i = 0; i < scount; ++i)
sk_X509_pop_free(si_chains[i], X509_free);
OPENSSL_free(si_chains);
}
sk_X509_pop_free(cms_certs, X509_free);
sk_X509_CRL_pop_free(crls, X509_CRL_free);
return ret;
}
int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
STACK_OF(X509) *certs,
X509_STORE *store, unsigned int flags)
{
int r;
flags &= ~(CMS_DETACHED | CMS_TEXT);
r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
if (r <= 0)
return r;
return ossl_cms_Receipt_verify(rcms, ocms);
}
CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey,
STACK_OF(X509) *certs, BIO *data,
unsigned int flags, OSSL_LIB_CTX *libctx,
const char *propq)
{
CMS_ContentInfo *cms;
int i;
cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL || !CMS_SignedData_init(cms))
goto merr;
if (flags & CMS_ASCIICRLF
&& !CMS_set1_eContentType(cms,
OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
goto err;
if (pkey != NULL && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
goto err;
}
for (i = 0; i < sk_X509_num(certs); i++) {
X509 *x = sk_X509_value(certs, i);
if (!CMS_add1_cert(cms, x))
goto merr;
}
if (!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
if ((flags & (CMS_STREAM | CMS_PARTIAL))
|| CMS_final(cms, data, NULL, flags))
return cms;
else
goto err;
merr:
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
CMS_ContentInfo_free(cms);
return NULL;
}
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, unsigned int flags)
{
return CMS_sign_ex(signcert, pkey, certs, data, flags, NULL, NULL);
}
CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
X509 *signcert, EVP_PKEY *pkey,
STACK_OF(X509) *certs, unsigned int flags)
{
CMS_SignerInfo *rct_si;
CMS_ContentInfo *cms = NULL;
ASN1_OCTET_STRING **pos, *os = NULL;
BIO *rct_cont = NULL;
int r = 0;
const CMS_CTX *ctx = si->cms_ctx;
flags &= ~(CMS_STREAM | CMS_TEXT);
/* Not really detached but avoids content being allocated */
flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
if (pkey == NULL || signcert == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY_OR_CERT);
return NULL;
}
/* Initialize signed data */
cms = CMS_sign_ex(NULL, NULL, certs, NULL, flags,
ossl_cms_ctx_get0_libctx(ctx),
ossl_cms_ctx_get0_propq(ctx));
if (cms == NULL)
goto err;
/* Set inner content type to signed receipt */
if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
goto err;
rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
if (!rct_si) {
ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
goto err;
}
os = ossl_cms_encode_Receipt(si);
if (os == NULL)
goto err;
/* Set content to digest */
rct_cont = BIO_new_mem_buf(os->data, os->length);
if (rct_cont == NULL)
goto err;
/* Add msgSigDigest attribute */
if (!ossl_cms_msgSigDigest_add1(rct_si, si))
goto err;
/* Finalize structure */
if (!CMS_final(cms, rct_cont, NULL, flags))
goto err;
/* Set embedded content */
pos = CMS_get0_content(cms);
if (pos == NULL)
goto err;
*pos = os;
r = 1;
err:
BIO_free(rct_cont);
if (r)
return cms;
CMS_ContentInfo_free(cms);
ASN1_OCTET_STRING_free(os);
return NULL;
}
CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *data,
const EVP_CIPHER *cipher, unsigned int flags,
OSSL_LIB_CTX *libctx, const char *propq)
{
CMS_ContentInfo *cms;
int i;
X509 *recip;
cms = (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
? CMS_AuthEnvelopedData_create_ex(cipher, libctx, propq)
: CMS_EnvelopedData_create_ex(cipher, libctx, propq);
if (cms == NULL)
goto merr;
for (i = 0; i < sk_X509_num(certs); i++) {
recip = sk_X509_value(certs, i);
if (!CMS_add1_recipient_cert(cms, recip, flags)) {
ERR_raise(ERR_LIB_CMS, CMS_R_RECIPIENT_ERROR);
goto err;
}
}
if (!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
if ((flags & (CMS_STREAM | CMS_PARTIAL))
|| CMS_final(cms, data, NULL, flags))
return cms;
else
goto err;
merr:
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
CMS_ContentInfo_free(cms);
return NULL;
}
CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
const EVP_CIPHER *cipher, unsigned int flags)
{
return CMS_encrypt_ex(certs, data, cipher, flags, NULL, NULL);
}
static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms,
CMS_RecipientInfo *ri,
EVP_PKEY *pk, X509 *cert, X509 *peer)
{
int i;
STACK_OF(CMS_RecipientEncryptedKey) *reks;
CMS_RecipientEncryptedKey *rek;
reks = CMS_RecipientInfo_kari_get0_reks(ri);
for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
int rv;
rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
continue;
CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, peer);
rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
if (rv > 0)
return 1;
return cert == NULL ? 0 : -1;
}
return 0;
}
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
{
return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL);
}
int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
X509 *cert, X509 *peer)
{
STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
CMS_RecipientInfo *ri;
int i, r, cms_pkey_ri_type;
int debug = 0, match_ri = 0;
CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
/* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
if (ec != NULL) {
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = NULL;
ec->keylen = 0;
}
if (ris != NULL && ec != NULL)
debug = ec->debug;
cms_pkey_ri_type = ossl_cms_pkey_get_ri_type(pk);
if (cms_pkey_ri_type == CMS_RECIPINFO_NONE) {
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
int ri_type;
ri = sk_CMS_RecipientInfo_value(ris, i);
ri_type = CMS_RecipientInfo_type(ri);
if (!ossl_cms_pkey_is_ri_type_supported(pk, ri_type))
continue;
match_ri = 1;
if (ri_type == CMS_RECIPINFO_AGREE) {
r = cms_kari_set1_pkey_and_peer(cms, ri, pk, cert, peer);
if (r > 0)
return 1;
if (r < 0)
return 0;
}
/* If we have a cert, try matching RecipientInfo, else try them all */
else if (cert == NULL || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
EVP_PKEY_up_ref(pk);
CMS_RecipientInfo_set0_pkey(ri, pk);
r = CMS_RecipientInfo_decrypt(cms, ri);
CMS_RecipientInfo_set0_pkey(ri, NULL);
if (cert != NULL) {
/*
* If not debugging clear any error and return success to
* avoid leaking of information useful to MMA
*/
if (!debug) {
ERR_clear_error();
return 1;
}
if (r > 0)
return 1;
ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
return 0;
}
/*
* If no cert and not debugging don't leave loop after first
* successful decrypt. Always attempt to decrypt all recipients
* to avoid leaking timing of a successful decrypt.
*/
else if (r > 0 && (debug || cms_pkey_ri_type != CMS_RECIPINFO_TRANS))
return 1;
}
}
/* If no cert, key transport and not debugging always return success */
if (cert == NULL
&& cms_pkey_ri_type == CMS_RECIPINFO_TRANS
&& match_ri
&& !debug) {
ERR_clear_error();
return 1;
}
if (!match_ri)
ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
unsigned char *key, size_t keylen,
const unsigned char *id, size_t idlen)
{
STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri;
int i, r, match_ri = 0;
ris = CMS_get0_RecipientInfos(cms);
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
ri = sk_CMS_RecipientInfo_value(ris, i);
if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
continue;
/* If we have an id, try matching RecipientInfo, else try them all */
if (id == NULL
|| (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
match_ri = 1;
CMS_RecipientInfo_set0_key(ri, key, keylen);
r = CMS_RecipientInfo_decrypt(cms, ri);
CMS_RecipientInfo_set0_key(ri, NULL, 0);
if (r > 0)
return 1;
if (id != NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
return 0;
}
ERR_clear_error();
}
}
if (!match_ri)
ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
unsigned char *pass, ossl_ssize_t passlen)
{
STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
CMS_RecipientInfo *ri;
int i, r, match_ri = 0;
CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
/* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
if (ec != NULL) {
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = NULL;
ec->keylen = 0;
}
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
ri = sk_CMS_RecipientInfo_value(ris, i);
if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
continue;
/* Must try each PasswordRecipientInfo */
match_ri = 1;
CMS_RecipientInfo_set0_password(ri, pass, passlen);
r = CMS_RecipientInfo_decrypt(cms, ri);
CMS_RecipientInfo_set0_password(ri, NULL, 0);
if (r > 0)
return 1;
}
if (!match_ri)
ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
BIO *dcont, BIO *out, unsigned int flags)
{
int r;
BIO *cont;
CMS_EncryptedContentInfo *ec;
int nid = OBJ_obj2nid(CMS_get0_type(cms));
if (nid != NID_pkcs7_enveloped
&& nid != NID_id_smime_ct_authEnvelopedData) {
ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENVELOPED_DATA);
return 0;
}
if (dcont == NULL && !check_content(cms))
return 0;
ec = ossl_cms_get0_env_enc_content(cms);
ec->debug = (flags & CMS_DEBUG_DECRYPT) != 0;
ec->havenocert = cert == NULL;
if (pk == NULL && cert == NULL && dcont == NULL && out == NULL)
return 1;
if (pk != NULL && !CMS_decrypt_set1_pkey(cms, pk, cert))
return 0;
cont = CMS_dataInit(cms, dcont);
if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
do_free_upto(cont, dcont);
return r;
}
int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
{
BIO *cmsbio;
int ret = 0;
if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
return 0;
}
if (!SMIME_crlf_copy(data, cmsbio, flags)) {
goto err;
}
(void)BIO_flush(cmsbio);
if (!CMS_dataFinal(cms, cmsbio)) {
ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR);
goto err;
}
ret = 1;
err:
do_free_upto(cmsbio, dcont);
return ret;
}
#ifdef ZLIB
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
unsigned int flags)
{
BIO *cont;
int r;
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
return 0;
}
if (dcont == NULL && !check_content(cms))
return 0;
cont = CMS_dataInit(cms, dcont);
if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
do_free_upto(cont, dcont);
return r;
}
CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
{
CMS_ContentInfo *cms;
if (comp_nid <= 0)
comp_nid = NID_zlib_compression;
cms = ossl_cms_CompressedData_create(comp_nid, NULL, NULL);
if (cms == NULL)
return NULL;
if (!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
return cms;
CMS_ContentInfo_free(cms);
return NULL;
}
#else
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
unsigned int flags)
{
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
return 0;
}
CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
{
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
return NULL;
}
#endif
diff --git a/crypto/openssl/crypto/core_fetch.c b/crypto/openssl/crypto/core_fetch.c
index 38db36ee1f75..c063515fc04d 100644
--- a/crypto/openssl/crypto/core_fetch.c
+++ b/crypto/openssl/crypto/core_fetch.c
@@ -1,171 +1,172 @@
/*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <stddef.h>
#include <openssl/core.h>
#include "internal/cryptlib.h"
#include "internal/core.h"
#include "internal/property.h"
#include "internal/provider.h"
struct construct_data_st {
OSSL_LIB_CTX *libctx;
OSSL_METHOD_STORE *store;
int operation_id;
int force_store;
OSSL_METHOD_CONSTRUCT_METHOD *mcm;
void *mcm_data;
};
static int is_temporary_method_store(int no_store, void *cbdata)
{
struct construct_data_st *data = cbdata;
return no_store && !data->force_store;
}
static int ossl_method_construct_reserve_store(int no_store, void *cbdata)
{
struct construct_data_st *data = cbdata;
if (is_temporary_method_store(no_store, data) && data->store == NULL) {
/*
* If we have been told not to store the method "permanently", we
* ask for a temporary store, and store the method there.
* The owner of |data->mcm| is completely responsible for managing
* that temporary store.
*/
if ((data->store = data->mcm->get_tmp_store(data->mcm_data)) == NULL)
return 0;
}
return data->mcm->lock_store(data->store, data->mcm_data);
}
static int ossl_method_construct_unreserve_store(void *cbdata)
{
struct construct_data_st *data = cbdata;
return data->mcm->unlock_store(data->store, data->mcm_data);
}
static int ossl_method_construct_precondition(OSSL_PROVIDER *provider,
int operation_id, int no_store,
void *cbdata, int *result)
{
if (!ossl_assert(result != NULL)) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/* Assume that no bits are set */
*result = 0;
/* No flag bits for temporary stores */
if (!is_temporary_method_store(no_store, cbdata)
&& !ossl_provider_test_operation_bit(provider, operation_id, result))
return 0;
/*
* The result we get tells if methods have already been constructed.
* However, we want to tell whether construction should happen (true)
* or not (false), which is the opposite of what we got.
*/
*result = !*result;
return 1;
}
static int ossl_method_construct_postcondition(OSSL_PROVIDER *provider,
int operation_id, int no_store,
void *cbdata, int *result)
{
if (!ossl_assert(result != NULL)) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
*result = 1;
/* No flag bits for temporary stores */
return is_temporary_method_store(no_store, cbdata)
|| ossl_provider_set_operation_bit(provider, operation_id);
}
static void ossl_method_construct_this(OSSL_PROVIDER *provider,
const OSSL_ALGORITHM *algo,
int no_store, void *cbdata)
{
struct construct_data_st *data = cbdata;
void *method = NULL;
if ((method = data->mcm->construct(algo, provider, data->mcm_data))
== NULL)
return;
/*
* Note regarding putting the method in stores:
*
* we don't need to care if it actually got in or not here.
* If it didn't get in, it will simply not be available when
* ossl_method_construct() tries to get it from the store.
*
* It is *expected* that the put function increments the refcnt
* of the passed method.
*/
- data->mcm->put(data->store, method, provider, algo->algorithm_names,
+ data->mcm->put(no_store ? data->store : NULL,
+ method, provider, algo->algorithm_names,
algo->property_definition, data->mcm_data);
/* refcnt-- because we're dropping the reference */
data->mcm->destruct(method, data->mcm_data);
}
void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id,
OSSL_PROVIDER **provider_rw, int force_store,
OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data)
{
void *method = NULL;
OSSL_PROVIDER *provider = provider_rw != NULL ? *provider_rw : NULL;
struct construct_data_st cbdata;
/*
* We might be tempted to try to look into the method store without
* constructing to see if we can find our method there already.
* Unfortunately that does not work well if the query contains
* optional properties as newly loaded providers can match them better.
* We trust that ossl_method_construct_precondition() and
* ossl_method_construct_postcondition() make sure that the
* ossl_algorithm_do_all() does very little when methods from
* a provider have already been constructed.
*/
cbdata.store = NULL;
cbdata.force_store = force_store;
cbdata.mcm = mcm;
cbdata.mcm_data = mcm_data;
ossl_algorithm_do_all(libctx, operation_id, provider,
ossl_method_construct_precondition,
ossl_method_construct_reserve_store,
ossl_method_construct_this,
ossl_method_construct_unreserve_store,
ossl_method_construct_postcondition,
&cbdata);
/* If there is a temporary store, try there first */
if (cbdata.store != NULL)
method = mcm->get(cbdata.store, (const OSSL_PROVIDER **)provider_rw,
mcm_data);
/* If no method was found yet, try the global store */
if (method == NULL)
method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw, mcm_data);
return method;
}
diff --git a/crypto/openssl/crypto/dso/dso_dl.c b/crypto/openssl/crypto/dso/dso_dl.c
index f4e6e5f4573f..05b63cf1d9c2 100644
--- a/crypto/openssl/crypto/dso/dso_dl.c
+++ b/crypto/openssl/crypto/dso/dso_dl.c
@@ -1,287 +1,286 @@
/*
* Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "dso_local.h"
#ifdef DSO_DL
# include <dl.h>
/* Part of the hack in "dl_load" ... */
# define DSO_MAX_TRANSLATED_SIZE 256
static int dl_load(DSO *dso);
static int dl_unload(DSO *dso);
static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname);
static char *dl_name_converter(DSO *dso, const char *filename);
static char *dl_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static int dl_pathbyaddr(void *addr, char *path, int sz);
static void *dl_globallookup(const char *name);
static DSO_METHOD dso_meth_dl = {
"OpenSSL 'dl' shared library method",
dl_load,
dl_unload,
dl_bind_func,
NULL, /* ctrl */
dl_name_converter,
dl_merger,
NULL, /* init */
NULL, /* finish */
dl_pathbyaddr,
dl_globallookup
};
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_dl;
}
/*
* For this DSO_METHOD, our meth_data STACK will contain; (i) the handle
* (shl_t) returned from shl_load(). NB: I checked on HPUX11 and shl_t is
* itself a pointer type so the cast is safe.
*/
static int dl_load(DSO *dso)
{
shl_t ptr = NULL;
/*
* We don't do any fancy retries or anything, just take the method's (or
* DSO's if it has the callback set) best translation of the
* platform-independent filename and try once with that.
*/
char *filename = DSO_convert_filename(dso, NULL);
if (filename == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
goto err;
}
ptr = shl_load(filename, BIND_IMMEDIATE |
(dso->flags & DSO_FLAG_NO_NAME_TRANSLATION ? 0 :
DYNAMIC_PATH), 0L);
if (ptr == NULL) {
char errbuf[160];
if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
"filename(%s): %s", filename, errbuf);
else
ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
"filename(%s): errno %d", filename, errno);
goto err;
}
if (!sk_push(dso->meth_data, (char *)ptr)) {
ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
goto err;
}
/*
* Success, stick the converted filename we've loaded under into the DSO
* (it also serves as the indicator that we are currently loaded).
*/
dso->loaded_filename = filename;
return 1;
err:
/* Cleanup! */
OPENSSL_free(filename);
if (ptr != NULL)
shl_unload(ptr);
return 0;
}
static int dl_unload(DSO *dso)
{
shl_t ptr;
if (dso == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_num(dso->meth_data) < 1)
return 1;
/* Is this statement legal? */
ptr = (shl_t) sk_pop(dso->meth_data);
if (ptr == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
/*
* Should push the value back onto the stack in case of a retry.
*/
sk_push(dso->meth_data, (char *)ptr);
return 0;
}
shl_unload(ptr);
return 1;
}
static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname)
{
shl_t ptr;
void *sym;
if ((dso == NULL) || (symname == NULL)) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (sk_num(dso->meth_data) < 1) {
ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
return NULL;
}
ptr = (shl_t) sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
if (ptr == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
return NULL;
}
if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) {
char errbuf[160];
if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE,
"symname(%s): %s", symname, errbuf);
else
ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE,
"symname(%s): errno %d", symname, errno);
return NULL;
}
return (DSO_FUNC_TYPE)sym;
}
static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
{
char *merged;
if (!filespec1 && !filespec2) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
/*
* If the first file specification is a rooted path, it rules. same goes
* if the second file specification is missing.
*/
if (!filespec2 || filespec1[0] == '/') {
merged = OPENSSL_strdup(filespec1);
if (merged == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
/*
* If the first file specification is missing, the second one rules.
*/
else if (!filespec1) {
merged = OPENSSL_strdup(filespec2);
if (merged == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
/*
* This part isn't as trivial as it looks. It assumes that the
* second file specification really is a directory, and makes no
* checks whatsoever. Therefore, the result becomes the
* concatenation of filespec2 followed by a slash followed by
* filespec1.
*/
{
int spec2len, len;
spec2len = (filespec2 ? strlen(filespec2) : 0);
len = spec2len + (filespec1 ? strlen(filespec1) : 0);
if (spec2len && filespec2[spec2len - 1] == '/') {
spec2len--;
len--;
}
merged = OPENSSL_malloc(len + 2);
if (merged == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
strcpy(merged, filespec2);
merged[spec2len] = '/';
strcpy(&merged[spec2len + 1], filespec1);
}
return merged;
}
/*
* This function is identical to the one in dso_dlfcn.c, but as it is highly
* unlikely that both the "dl" *and* "dlfcn" variants are being compiled at
* the same time, there's no great duplicating the code. Figuring out an
* elegant way to share one copy of the code would be more difficult and
* would not leave the implementations independent.
*/
static char *dl_name_converter(DSO *dso, const char *filename)
{
char *translated;
int len, rsize, transform;
len = strlen(filename);
rsize = len + 1;
transform = (strstr(filename, "/") == NULL);
if (transform) {
/* We will convert this to "%s.s?" or "lib%s.s?" */
rsize += strlen(DSO_EXTENSION); /* The length of ".s?" */
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
rsize += 3; /* The length of "lib" */
}
translated = OPENSSL_malloc(rsize);
if (translated == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED);
return NULL;
}
- if (transform) {
- if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
- sprintf(translated, "lib%s%s", filename, DSO_EXTENSION);
- else
- sprintf(translated, "%s%s", filename, DSO_EXTENSION);
- } else
- sprintf(translated, "%s", filename);
+ if (transform)
+ BIO_snprintf(translated, rsize,
+ (DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0
+ ? "lib%s%s" : "%s%s", filename, DSO_EXTENSION);
+ else
+ BIO_snprintf(translated, rsize, "%s", filename);
return translated;
}
static int dl_pathbyaddr(void *addr, char *path, int sz)
{
struct shl_descriptor inf;
int i, len;
if (addr == NULL) {
union {
int (*f) (void *, char *, int);
void *p;
} t = {
dl_pathbyaddr
};
addr = t.p;
}
for (i = -1; shl_get_r(i, &inf) == 0; i++) {
if (((size_t)addr >= inf.tstart && (size_t)addr < inf.tend) ||
((size_t)addr >= inf.dstart && (size_t)addr < inf.dend)) {
len = (int)strlen(inf.filename);
if (sz <= 0)
return len + 1;
if (len >= sz)
len = sz - 1;
memcpy(path, inf.filename, len);
path[len++] = 0;
return len;
}
}
return -1;
}
static void *dl_globallookup(const char *name)
{
void *ret;
shl_t h = NULL;
return shl_findsym(&h, name, TYPE_UNDEFINED, &ret) ? NULL : ret;
}
#endif /* DSO_DL */
diff --git a/crypto/openssl/crypto/dso/dso_dlfcn.c b/crypto/openssl/crypto/dso/dso_dlfcn.c
index 6a988cc72791..1107da5fe657 100644
--- a/crypto/openssl/crypto/dso/dso_dlfcn.c
+++ b/crypto/openssl/crypto/dso/dso_dlfcn.c
@@ -1,456 +1,457 @@
/*
* Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* We need to do this early, because stdio.h includes the header files that
* handle _GNU_SOURCE and other similar macros. Defining it later is simply
* too late, because those headers are protected from re- inclusion.
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE /* make sure dladdr is declared */
#endif
#include "dso_local.h"
#include "e_os.h"
#ifdef DSO_DLFCN
# ifdef HAVE_DLFCN_H
# ifdef __osf__
# define __EXTENSIONS__
# endif
# include <dlfcn.h>
# define HAVE_DLINFO 1
# if defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
(defined(__osf__) && !defined(RTLD_NEXT)) || \
(defined(__OpenBSD__) && !defined(RTLD_SELF)) || \
defined(__ANDROID__) || defined(__TANDEM)
# undef HAVE_DLINFO
# endif
# endif
/* Part of the hack in "dlfcn_load" ... */
# define DSO_MAX_TRANSLATED_SIZE 256
static int dlfcn_load(DSO *dso);
static int dlfcn_unload(DSO *dso);
static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname);
static char *dlfcn_name_converter(DSO *dso, const char *filename);
static char *dlfcn_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static int dlfcn_pathbyaddr(void *addr, char *path, int sz);
static void *dlfcn_globallookup(const char *name);
static DSO_METHOD dso_meth_dlfcn = {
"OpenSSL 'dlfcn' shared library method",
dlfcn_load,
dlfcn_unload,
dlfcn_bind_func,
NULL, /* ctrl */
dlfcn_name_converter,
dlfcn_merger,
NULL, /* init */
NULL, /* finish */
dlfcn_pathbyaddr,
dlfcn_globallookup
};
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_dlfcn;
}
/*
* Prior to using the dlopen() function, we should decide on the flag we
* send. There's a few different ways of doing this and it's a messy
* venn-diagram to match up which platforms support what. So as we don't have
* autoconf yet, I'm implementing a hack that could be hacked further
* relatively easily to deal with cases as we find them. Initially this is to
* cope with OpenBSD.
*/
# if defined(__OpenBSD__) || defined(__NetBSD__)
# ifdef DL_LAZY
# define DLOPEN_FLAG DL_LAZY
# else
# ifdef RTLD_NOW
# define DLOPEN_FLAG RTLD_NOW
# else
# define DLOPEN_FLAG 0
# endif
# endif
# else
# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */
# endif
/*
* For this DSO_METHOD, our meth_data STACK will contain; (i) the handle
* (void*) returned from dlopen().
*/
static int dlfcn_load(DSO *dso)
{
void *ptr = NULL;
/* See applicable comments in dso_dl.c */
char *filename = DSO_convert_filename(dso, NULL);
int flags = DLOPEN_FLAG;
int saveerrno = get_last_sys_error();
if (filename == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
goto err;
}
# ifdef RTLD_GLOBAL
if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
flags |= RTLD_GLOBAL;
# endif
# ifdef _AIX
if (filename[strlen(filename) - 1] == ')')
flags |= RTLD_MEMBER;
# endif
ptr = dlopen(filename, flags);
if (ptr == NULL) {
ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
"filename(%s): %s", filename, dlerror());
goto err;
}
/*
* Some dlopen() implementations (e.g. solaris) do no preserve errno, even
* on a successful call.
*/
set_sys_error(saveerrno);
if (!sk_void_push(dso->meth_data, (char *)ptr)) {
ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
goto err;
}
/* Success */
dso->loaded_filename = filename;
return 1;
err:
/* Cleanup! */
OPENSSL_free(filename);
if (ptr != NULL)
dlclose(ptr);
return 0;
}
static int dlfcn_unload(DSO *dso)
{
void *ptr;
if (dso == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_void_num(dso->meth_data) < 1)
return 1;
ptr = sk_void_pop(dso->meth_data);
if (ptr == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
/*
* Should push the value back onto the stack in case of a retry.
*/
sk_void_push(dso->meth_data, ptr);
return 0;
}
/* For now I'm not aware of any errors associated with dlclose() */
dlclose(ptr);
return 1;
}
static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)
{
void *ptr;
union {
DSO_FUNC_TYPE sym;
void *dlret;
} u;
if ((dso == NULL) || (symname == NULL)) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (sk_void_num(dso->meth_data) < 1) {
ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
return NULL;
}
ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
if (ptr == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
return NULL;
}
u.dlret = dlsym(ptr, symname);
if (u.dlret == NULL) {
ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE,
"symname(%s): %s", symname, dlerror());
return NULL;
}
return u.sym;
}
static char *dlfcn_merger(DSO *dso, const char *filespec1,
const char *filespec2)
{
char *merged;
if (!filespec1 && !filespec2) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
/*
* If the first file specification is a rooted path, it rules. same goes
* if the second file specification is missing.
*/
if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
merged = OPENSSL_strdup(filespec1);
if (merged == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
/*
* If the first file specification is missing, the second one rules.
*/
else if (!filespec1) {
merged = OPENSSL_strdup(filespec2);
if (merged == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
/*
* This part isn't as trivial as it looks. It assumes that the
* second file specification really is a directory, and makes no
* checks whatsoever. Therefore, the result becomes the
* concatenation of filespec2 followed by a slash followed by
* filespec1.
*/
int spec2len, len;
spec2len = strlen(filespec2);
len = spec2len + strlen(filespec1);
if (spec2len && filespec2[spec2len - 1] == '/') {
spec2len--;
len--;
}
merged = OPENSSL_malloc(len + 2);
if (merged == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
strcpy(merged, filespec2);
merged[spec2len] = '/';
strcpy(&merged[spec2len + 1], filespec1);
}
return merged;
}
static char *dlfcn_name_converter(DSO *dso, const char *filename)
{
char *translated;
int len, rsize, transform;
len = strlen(filename);
rsize = len + 1;
transform = (strstr(filename, "/") == NULL);
if (transform) {
/* We will convert this to "%s.so" or "lib%s.so" etc */
rsize += strlen(DSO_EXTENSION); /* The length of ".so" */
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
rsize += 3; /* The length of "lib" */
}
translated = OPENSSL_malloc(rsize);
if (translated == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED);
return NULL;
}
if (transform) {
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
- sprintf(translated, "lib%s" DSO_EXTENSION, filename);
+ BIO_snprintf(translated, rsize, "lib%s" DSO_EXTENSION, filename);
else
- sprintf(translated, "%s" DSO_EXTENSION, filename);
- } else
- sprintf(translated, "%s", filename);
+ BIO_snprintf(translated, rsize, "%s" DSO_EXTENSION, filename);
+ } else {
+ BIO_snprintf(translated, rsize, "%s", filename);
+ }
return translated;
}
# ifdef __sgi
/*-
This is a quote from IRIX manual for dladdr(3c):
<dlfcn.h> does not contain a prototype for dladdr or definition of
Dl_info. The #include <dlfcn.h> in the SYNOPSIS line is traditional,
but contains no dladdr prototype and no IRIX library contains an
implementation. Write your own declaration based on the code below.
The following code is dependent on internal interfaces that are not
part of the IRIX compatibility guarantee; however, there is no future
intention to change this interface, so on a practical level, the code
below is safe to use on IRIX.
*/
# include <rld_interface.h>
# ifndef _RLD_INTERFACE_DLFCN_H_DLADDR
# define _RLD_INTERFACE_DLFCN_H_DLADDR
typedef struct Dl_info {
const char *dli_fname;
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
int dli_version;
int dli_reserved1;
long dli_reserved[4];
} Dl_info;
# else
typedef struct Dl_info Dl_info;
# endif
# define _RLD_DLADDR 14
static int dladdr(void *address, Dl_info *dl)
{
void *v;
v = _rld_new_interface(_RLD_DLADDR, address, dl);
return (int)v;
}
# endif /* __sgi */
# ifdef _AIX
/*-
* See IBM's AIX Version 7.2, Technical Reference:
* Base Operating System and Extensions, Volume 1 and 2
* https://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.base/technicalreferences.htm
*/
# include <sys/ldr.h>
# include <errno.h>
/* ~ 64 * (sizeof(struct ld_info) + _XOPEN_PATH_MAX + _XOPEN_NAME_MAX) */
# define DLFCN_LDINFO_SIZE 86976
typedef struct Dl_info {
const char *dli_fname;
} Dl_info;
/*
* This dladdr()-implementation will also find the ptrgl (Pointer Glue) virtual
* address of a function, which is just located in the DATA segment instead of
* the TEXT segment.
*/
static int dladdr(void *ptr, Dl_info *dl)
{
uintptr_t addr = (uintptr_t)ptr;
unsigned int found = 0;
struct ld_info *ldinfos, *next_ldi, *this_ldi;
if ((ldinfos = OPENSSL_malloc(DLFCN_LDINFO_SIZE)) == NULL) {
errno = ENOMEM;
dl->dli_fname = NULL;
return 0;
}
if ((loadquery(L_GETINFO, (void *)ldinfos, DLFCN_LDINFO_SIZE)) < 0) {
/*-
* Error handling is done through errno and dlerror() reading errno:
* ENOMEM (ldinfos buffer is too small),
* EINVAL (invalid flags),
* EFAULT (invalid ldinfos ptr)
*/
OPENSSL_free((void *)ldinfos);
dl->dli_fname = NULL;
return 0;
}
next_ldi = ldinfos;
do {
this_ldi = next_ldi;
if (((addr >= (uintptr_t)this_ldi->ldinfo_textorg)
&& (addr < ((uintptr_t)this_ldi->ldinfo_textorg +
this_ldi->ldinfo_textsize)))
|| ((addr >= (uintptr_t)this_ldi->ldinfo_dataorg)
&& (addr < ((uintptr_t)this_ldi->ldinfo_dataorg +
this_ldi->ldinfo_datasize)))) {
char *buffer, *member;
size_t buffer_sz, member_len;
buffer_sz = strlen(this_ldi->ldinfo_filename) + 1;
member = this_ldi->ldinfo_filename + buffer_sz;
if ((member_len = strlen(member)) > 0)
buffer_sz += 1 + member_len + 1;
found = 1;
if ((buffer = OPENSSL_malloc(buffer_sz)) != NULL) {
OPENSSL_strlcpy(buffer, this_ldi->ldinfo_filename, buffer_sz);
if (member_len > 0) {
/*
* Need to respect a possible member name and not just
* returning the path name in this case. See docs:
* sys/ldr.h, loadquery() and dlopen()/RTLD_MEMBER.
*/
OPENSSL_strlcat(buffer, "(", buffer_sz);
OPENSSL_strlcat(buffer, member, buffer_sz);
OPENSSL_strlcat(buffer, ")", buffer_sz);
}
dl->dli_fname = buffer;
} else {
errno = ENOMEM;
}
} else {
next_ldi = (struct ld_info *)((uintptr_t)this_ldi +
this_ldi->ldinfo_next);
}
} while (this_ldi->ldinfo_next && !found);
OPENSSL_free((void *)ldinfos);
return (found && dl->dli_fname != NULL);
}
# endif /* _AIX */
static int dlfcn_pathbyaddr(void *addr, char *path, int sz)
{
# ifdef HAVE_DLINFO
Dl_info dli;
int len;
if (addr == NULL) {
union {
int (*f) (void *, char *, int);
void *p;
} t = {
dlfcn_pathbyaddr
};
addr = t.p;
}
if (dladdr(addr, &dli)) {
len = (int)strlen(dli.dli_fname);
if (sz <= 0) {
# ifdef _AIX
OPENSSL_free((void *)dli.dli_fname);
# endif
return len + 1;
}
if (len >= sz)
len = sz - 1;
memcpy(path, dli.dli_fname, len);
path[len++] = 0;
# ifdef _AIX
OPENSSL_free((void *)dli.dli_fname);
# endif
return len;
}
ERR_add_error_data(2, "dlfcn_pathbyaddr(): ", dlerror());
# endif
return -1;
}
static void *dlfcn_globallookup(const char *name)
{
void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);
if (handle) {
ret = dlsym(handle, name);
dlclose(handle);
}
return ret;
}
#endif /* DSO_DLFCN */
diff --git a/crypto/openssl/crypto/dso/dso_win32.c b/crypto/openssl/crypto/dso/dso_win32.c
index 4d3059d43879..91a1a9d9aeb5 100644
--- a/crypto/openssl/crypto/dso/dso_win32.c
+++ b/crypto/openssl/crypto/dso/dso_win32.c
@@ -1,671 +1,667 @@
/*
* Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 "dso_local.h"
#if defined(DSO_WIN32)
# ifdef _WIN32_WCE
# if _WIN32_WCE < 300
static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName)
{
WCHAR lpProcNameW[64];
int i;
for (i = 0; lpProcName[i] && i < 64; i++)
lpProcNameW[i] = (WCHAR)lpProcName[i];
if (i == 64)
return NULL;
lpProcNameW[i] = 0;
return GetProcAddressW(hModule, lpProcNameW);
}
# endif
# undef GetProcAddress
# define GetProcAddress GetProcAddressA
static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName)
{
WCHAR *fnamw;
size_t len_0 = strlen(lpLibFileName) + 1, i;
# ifdef _MSC_VER
fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR));
# else
fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
# endif
if (fnamw == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
# if defined(_WIN32_WCE) && _WIN32_WCE>=101
if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0))
# endif
for (i = 0; i < len_0; i++)
fnamw[i] = (WCHAR)lpLibFileName[i];
return LoadLibraryW(fnamw);
}
# endif
/* Part of the hack in "win32_load" ... */
# define DSO_MAX_TRANSLATED_SIZE 256
static int win32_load(DSO *dso);
static int win32_unload(DSO *dso);
static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
static char *win32_name_converter(DSO *dso, const char *filename);
static char *win32_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static int win32_pathbyaddr(void *addr, char *path, int sz);
static void *win32_globallookup(const char *name);
static const char *openssl_strnchr(const char *string, int c, size_t len);
static DSO_METHOD dso_meth_win32 = {
"OpenSSL 'win32' shared library method",
win32_load,
win32_unload,
win32_bind_func,
NULL, /* ctrl */
win32_name_converter,
win32_merger,
NULL, /* init */
NULL, /* finish */
win32_pathbyaddr, /* pathbyaddr */
win32_globallookup
};
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_win32;
}
/*
* For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
* the handle (HINSTANCE) returned from LoadLibrary(), and copied.
*/
static int win32_load(DSO *dso)
{
HINSTANCE h = NULL, *p = NULL;
/* See applicable comments from dso_dl.c */
char *filename = DSO_convert_filename(dso, NULL);
if (filename == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
goto err;
}
h = LoadLibraryA(filename);
if (h == NULL) {
ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
"filename(%s)", filename);
goto err;
}
p = OPENSSL_malloc(sizeof(*p));
if (p == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
goto err;
}
*p = h;
if (!sk_void_push(dso->meth_data, p)) {
ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
goto err;
}
/* Success */
dso->loaded_filename = filename;
return 1;
err:
/* Cleanup ! */
OPENSSL_free(filename);
OPENSSL_free(p);
if (h != NULL)
FreeLibrary(h);
return 0;
}
static int win32_unload(DSO *dso)
{
HINSTANCE *p;
if (dso == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_void_num(dso->meth_data) < 1)
return 1;
p = sk_void_pop(dso->meth_data);
if (p == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
return 0;
}
if (!FreeLibrary(*p)) {
ERR_raise(ERR_LIB_DSO, DSO_R_UNLOAD_FAILED);
/*
* We should push the value back onto the stack in case of a retry.
*/
sk_void_push(dso->meth_data, p);
return 0;
}
/* Cleanup */
OPENSSL_free(p);
return 1;
}
static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
{
HINSTANCE *ptr;
union {
void *p;
FARPROC f;
} sym;
if ((dso == NULL) || (symname == NULL)) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (sk_void_num(dso->meth_data) < 1) {
ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
return NULL;
}
ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
if (ptr == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
return NULL;
}
sym.f = GetProcAddress(*ptr, symname);
if (sym.p == NULL) {
ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE, "symname(%s)", symname);
return NULL;
}
return (DSO_FUNC_TYPE)sym.f;
}
struct file_st {
const char *node;
int nodelen;
const char *device;
int devicelen;
const char *predir;
int predirlen;
const char *dir;
int dirlen;
const char *file;
int filelen;
};
static struct file_st *win32_splitter(DSO *dso, const char *filename,
int assume_last_is_dir)
{
struct file_st *result = NULL;
enum { IN_NODE, IN_DEVICE, IN_FILE } position;
const char *start = filename;
char last;
if (!filename) {
ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
return NULL;
}
result = OPENSSL_zalloc(sizeof(*result));
if (result == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
position = IN_DEVICE;
if ((filename[0] == '\\' && filename[1] == '\\')
|| (filename[0] == '/' && filename[1] == '/')) {
position = IN_NODE;
filename += 2;
start = filename;
result->node = start;
}
do {
last = filename[0];
switch (last) {
case ':':
if (position != IN_DEVICE) {
ERR_raise(ERR_LIB_DSO, DSO_R_INCORRECT_FILE_SYNTAX);
OPENSSL_free(result);
return NULL;
}
result->device = start;
result->devicelen = (int)(filename - start);
position = IN_FILE;
start = ++filename;
result->dir = start;
break;
case '\\':
case '/':
if (position == IN_NODE) {
result->nodelen = (int)(filename - start);
position = IN_FILE;
start = ++filename;
result->dir = start;
} else if (position == IN_DEVICE) {
position = IN_FILE;
filename++;
result->dir = start;
result->dirlen = (int)(filename - start);
start = filename;
} else {
filename++;
result->dirlen += (int)(filename - start);
start = filename;
}
break;
case '\0':
if (position == IN_NODE) {
result->nodelen = (int)(filename - start);
} else {
if (filename - start > 0) {
if (assume_last_is_dir) {
if (position == IN_DEVICE) {
result->dir = start;
result->dirlen = 0;
}
result->dirlen += (int)(filename - start);
} else {
result->file = start;
result->filelen = (int)(filename - start);
}
}
}
break;
default:
filename++;
break;
}
}
while (last);
if (!result->nodelen)
result->node = NULL;
if (!result->devicelen)
result->device = NULL;
if (!result->dirlen)
result->dir = NULL;
if (!result->filelen)
result->file = NULL;
return result;
}
static char *win32_joiner(DSO *dso, const struct file_st *file_split)
{
int len = 0, offset = 0;
char *result = NULL;
const char *start;
if (!file_split) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (file_split->node) {
len += 2 + file_split->nodelen; /* 2 for starting \\ */
if (file_split->predir || file_split->dir || file_split->file)
len++; /* 1 for ending \ */
} else if (file_split->device) {
len += file_split->devicelen + 1; /* 1 for ending : */
}
len += file_split->predirlen;
if (file_split->predir && (file_split->dir || file_split->file)) {
len++; /* 1 for ending \ */
}
len += file_split->dirlen;
if (file_split->dir && file_split->file) {
len++; /* 1 for ending \ */
}
len += file_split->filelen;
if (!len) {
ERR_raise(ERR_LIB_DSO, DSO_R_EMPTY_FILE_STRUCTURE);
return NULL;
}
result = OPENSSL_malloc(len + 1);
if (result == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (file_split->node) {
strcpy(&result[offset], "\\\\");
offset += 2;
strncpy(&result[offset], file_split->node, file_split->nodelen);
offset += file_split->nodelen;
if (file_split->predir || file_split->dir || file_split->file) {
result[offset] = '\\';
offset++;
}
} else if (file_split->device) {
strncpy(&result[offset], file_split->device, file_split->devicelen);
offset += file_split->devicelen;
result[offset] = ':';
offset++;
}
start = file_split->predir;
while (file_split->predirlen > (start - file_split->predir)) {
const char *end = openssl_strnchr(start, '/',
file_split->predirlen - (start -
file_split->predir));
if (!end)
end = start
+ file_split->predirlen - (start - file_split->predir);
strncpy(&result[offset], start, end - start);
offset += (int)(end - start);
result[offset] = '\\';
offset++;
start = end + 1;
}
start = file_split->dir;
while (file_split->dirlen > (start - file_split->dir)) {
const char *end = openssl_strnchr(start, '/',
file_split->dirlen - (start -
file_split->dir));
if (!end)
end = start + file_split->dirlen - (start - file_split->dir);
strncpy(&result[offset], start, end - start);
offset += (int)(end - start);
result[offset] = '\\';
offset++;
start = end + 1;
}
strncpy(&result[offset], file_split->file, file_split->filelen);
offset += file_split->filelen;
result[offset] = '\0';
return result;
}
static char *win32_merger(DSO *dso, const char *filespec1,
const char *filespec2)
{
char *merged = NULL;
struct file_st *filespec1_split = NULL;
struct file_st *filespec2_split = NULL;
if (!filespec1 && !filespec2) {
ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (!filespec2) {
merged = OPENSSL_strdup(filespec1);
if (merged == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else if (!filespec1) {
merged = OPENSSL_strdup(filespec2);
if (merged == NULL) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
filespec1_split = win32_splitter(dso, filespec1, 0);
if (!filespec1_split) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
filespec2_split = win32_splitter(dso, filespec2, 1);
if (!filespec2_split) {
ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
OPENSSL_free(filespec1_split);
return NULL;
}
/* Fill in into filespec1_split */
if (!filespec1_split->node && !filespec1_split->device) {
filespec1_split->node = filespec2_split->node;
filespec1_split->nodelen = filespec2_split->nodelen;
filespec1_split->device = filespec2_split->device;
filespec1_split->devicelen = filespec2_split->devicelen;
}
if (!filespec1_split->dir) {
filespec1_split->dir = filespec2_split->dir;
filespec1_split->dirlen = filespec2_split->dirlen;
} else if (filespec1_split->dir[0] != '\\'
&& filespec1_split->dir[0] != '/') {
filespec1_split->predir = filespec2_split->dir;
filespec1_split->predirlen = filespec2_split->dirlen;
}
if (!filespec1_split->file) {
filespec1_split->file = filespec2_split->file;
filespec1_split->filelen = filespec2_split->filelen;
}
merged = win32_joiner(dso, filespec1_split);
}
OPENSSL_free(filespec1_split);
OPENSSL_free(filespec2_split);
return merged;
}
static char *win32_name_converter(DSO *dso, const char *filename)
{
char *translated;
int len, transform;
- len = strlen(filename);
transform = ((strstr(filename, "/") == NULL) &&
(strstr(filename, "\\") == NULL) &&
(strstr(filename, ":") == NULL));
+ /* If transform != 0, then we convert to %s.dll, else just dupe filename */
+
+ len = strlen(filename) + 1;
if (transform)
- /* We will convert this to "%s.dll" */
- translated = OPENSSL_malloc(len + 5);
- else
- /* We will simply duplicate filename */
- translated = OPENSSL_malloc(len + 1);
+ len += strlen(".dll");
+ translated = OPENSSL_malloc(len);
if (translated == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED);
return NULL;
}
- if (transform)
- sprintf(translated, "%s.dll", filename);
- else
- sprintf(translated, "%s", filename);
+ BIO_snprintf(translated, len, "%s%s", filename, transform ? ".dll" : "");
return translated;
}
static const char *openssl_strnchr(const char *string, int c, size_t len)
{
size_t i;
const char *p;
for (i = 0, p = string; i < len && *p; i++, p++) {
if (*p == c)
return p;
}
return NULL;
}
# include <tlhelp32.h>
# ifdef _WIN32_WCE
# define DLLNAME "TOOLHELP.DLL"
# else
# ifdef MODULEENTRY32
# undef MODULEENTRY32 /* unmask the ASCII version! */
# endif
# define DLLNAME "KERNEL32.DLL"
# endif
typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *);
static int win32_pathbyaddr(void *addr, char *path, int sz)
{
HMODULE dll;
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
CREATETOOLHELP32SNAPSHOT create_snap;
CLOSETOOLHELP32SNAPSHOT close_snap;
MODULE32 module_first, module_next;
if (addr == NULL) {
union {
int (*f) (void *, char *, int);
void *p;
} t = {
win32_pathbyaddr
};
addr = t.p;
}
dll = LoadLibrary(TEXT(DLLNAME));
if (dll == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return -1;
}
create_snap = (CREATETOOLHELP32SNAPSHOT)
GetProcAddress(dll, "CreateToolhelp32Snapshot");
if (create_snap == NULL) {
FreeLibrary(dll);
ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return -1;
}
/* We take the rest for granted... */
# ifdef _WIN32_WCE
close_snap = (CLOSETOOLHELP32SNAPSHOT)
GetProcAddress(dll, "CloseToolhelp32Snapshot");
# else
close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
# endif
module_first = (MODULE32) GetProcAddress(dll, "Module32First");
module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
/*
* Take a snapshot of current process which includes
* list of all involved modules.
*/
hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
if (hModuleSnap == INVALID_HANDLE_VALUE) {
FreeLibrary(dll);
ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return -1;
}
me32.dwSize = sizeof(me32);
if (!(*module_first) (hModuleSnap, &me32)) {
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
ERR_raise(ERR_LIB_DSO, DSO_R_FAILURE);
return -1;
}
/* Enumerate the modules to find one which includes me. */
do {
if ((size_t) addr >= (size_t) me32.modBaseAddr &&
(size_t) addr < (size_t) (me32.modBaseAddr + me32.modBaseSize)) {
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
# ifdef _WIN32_WCE
# if _WIN32_WCE >= 101
return WideCharToMultiByte(CP_ACP, 0, me32.szExePath, -1,
path, sz, NULL, NULL);
# else
{
int i, len = (int)wcslen(me32.szExePath);
if (sz <= 0)
return len + 1;
if (len >= sz)
len = sz - 1;
for (i = 0; i < len; i++)
path[i] = (char)me32.szExePath[i];
path[len++] = '\0';
return len;
}
# endif
# else
{
int len = (int)strlen(me32.szExePath);
if (sz <= 0)
return len + 1;
if (len >= sz)
len = sz - 1;
memcpy(path, me32.szExePath, len);
path[len++] = '\0';
return len;
}
# endif
}
} while ((*module_next) (hModuleSnap, &me32));
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
return 0;
}
static void *win32_globallookup(const char *name)
{
HMODULE dll;
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
CREATETOOLHELP32SNAPSHOT create_snap;
CLOSETOOLHELP32SNAPSHOT close_snap;
MODULE32 module_first, module_next;
union {
void *p;
FARPROC f;
} ret = { NULL };
dll = LoadLibrary(TEXT(DLLNAME));
if (dll == NULL) {
ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return NULL;
}
create_snap = (CREATETOOLHELP32SNAPSHOT)
GetProcAddress(dll, "CreateToolhelp32Snapshot");
if (create_snap == NULL) {
FreeLibrary(dll);
ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return NULL;
}
/* We take the rest for granted... */
# ifdef _WIN32_WCE
close_snap = (CLOSETOOLHELP32SNAPSHOT)
GetProcAddress(dll, "CloseToolhelp32Snapshot");
# else
close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
# endif
module_first = (MODULE32) GetProcAddress(dll, "Module32First");
module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
if (hModuleSnap == INVALID_HANDLE_VALUE) {
FreeLibrary(dll);
ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return NULL;
}
me32.dwSize = sizeof(me32);
if (!(*module_first) (hModuleSnap, &me32)) {
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
return NULL;
}
do {
if ((ret.f = GetProcAddress(me32.hModule, name))) {
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
return ret.p;
}
} while ((*module_next) (hModuleSnap, &me32));
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
return NULL;
}
#endif /* DSO_WIN32 */
diff --git a/crypto/openssl/crypto/ec/ec_asn1.c b/crypto/openssl/crypto/ec/ec_asn1.c
index 7a0b35a59431..c018f392894d 100644
--- a/crypto/openssl/crypto/ec/ec_asn1.c
+++ b/crypto/openssl/crypto/ec/ec_asn1.c
@@ -1,1340 +1,1340 @@
/*
* Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* ECDSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <string.h>
#include "ec_local.h"
#include <openssl/err.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include "internal/nelem.h"
#include "crypto/asn1_dsa.h"
#ifndef FIPS_MODULE
/* some structures needed for the asn1 encoding */
typedef struct x9_62_pentanomial_st {
int32_t k1;
int32_t k2;
int32_t k3;
} X9_62_PENTANOMIAL;
typedef struct x9_62_characteristic_two_st {
int32_t m;
ASN1_OBJECT *type;
union {
char *ptr;
/* NID_X9_62_onBasis */
ASN1_NULL *onBasis;
/* NID_X9_62_tpBasis */
ASN1_INTEGER *tpBasis;
/* NID_X9_62_ppBasis */
X9_62_PENTANOMIAL *ppBasis;
/* anything else */
ASN1_TYPE *other;
} p;
} X9_62_CHARACTERISTIC_TWO;
typedef struct x9_62_fieldid_st {
ASN1_OBJECT *fieldType;
union {
char *ptr;
/* NID_X9_62_prime_field */
ASN1_INTEGER *prime;
/* NID_X9_62_characteristic_two_field */
X9_62_CHARACTERISTIC_TWO *char_two;
/* anything else */
ASN1_TYPE *other;
} p;
} X9_62_FIELDID;
typedef struct x9_62_curve_st {
ASN1_OCTET_STRING *a;
ASN1_OCTET_STRING *b;
ASN1_BIT_STRING *seed;
} X9_62_CURVE;
struct ec_parameters_st {
int32_t version;
X9_62_FIELDID *fieldID;
X9_62_CURVE *curve;
ASN1_OCTET_STRING *base;
ASN1_INTEGER *order;
ASN1_INTEGER *cofactor;
} /* ECPARAMETERS */ ;
typedef enum {
ECPKPARAMETERS_TYPE_NAMED = 0,
ECPKPARAMETERS_TYPE_EXPLICIT,
ECPKPARAMETERS_TYPE_IMPLICIT
} ecpk_parameters_type_t;
struct ecpk_parameters_st {
int type;
union {
ASN1_OBJECT *named_curve;
ECPARAMETERS *parameters;
ASN1_NULL *implicitlyCA;
} value;
} /* ECPKPARAMETERS */ ;
/* SEC1 ECPrivateKey */
typedef struct ec_privatekey_st {
int32_t version;
ASN1_OCTET_STRING *privateKey;
ECPKPARAMETERS *parameters;
ASN1_BIT_STRING *publicKey;
} EC_PRIVATEKEY;
/* the OpenSSL ASN.1 definitions */
ASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
ASN1_EMBED(X9_62_PENTANOMIAL, k1, INT32),
ASN1_EMBED(X9_62_PENTANOMIAL, k2, INT32),
ASN1_EMBED(X9_62_PENTANOMIAL, k3, INT32)
} static_ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
ASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY);
ASN1_ADB(X9_62_CHARACTERISTIC_TWO) = {
ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)),
ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)),
ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL))
} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
ASN1_EMBED(X9_62_CHARACTERISTIC_TWO, m, INT32),
ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
} static_ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
ASN1_ADB(X9_62_FIELDID) = {
ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO))
} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
ASN1_SEQUENCE(X9_62_FIELDID) = {
ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
ASN1_ADB_OBJECT(X9_62_FIELDID)
} static_ASN1_SEQUENCE_END(X9_62_FIELDID)
ASN1_SEQUENCE(X9_62_CURVE) = {
ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
} static_ASN1_SEQUENCE_END(X9_62_CURVE)
ASN1_SEQUENCE(ECPARAMETERS) = {
ASN1_EMBED(ECPARAMETERS, version, INT32),
ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
} ASN1_SEQUENCE_END(ECPARAMETERS)
DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
ASN1_CHOICE(ECPKPARAMETERS) = {
ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL)
} ASN1_CHOICE_END(ECPKPARAMETERS)
DECLARE_ASN1_FUNCTIONS(ECPKPARAMETERS)
DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECPKPARAMETERS, ECPKPARAMETERS)
IMPLEMENT_ASN1_FUNCTIONS(ECPKPARAMETERS)
ASN1_SEQUENCE(EC_PRIVATEKEY) = {
ASN1_EMBED(EC_PRIVATEKEY, version, INT32),
ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
} static_ASN1_SEQUENCE_END(EC_PRIVATEKEY)
DECLARE_ASN1_FUNCTIONS(EC_PRIVATEKEY)
DECLARE_ASN1_ENCODE_FUNCTIONS_name(EC_PRIVATEKEY, EC_PRIVATEKEY)
IMPLEMENT_ASN1_FUNCTIONS(EC_PRIVATEKEY)
/* some declarations of internal function */
/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */
static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
/* the function definitions */
static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
{
int ok = 0, nid;
BIGNUM *tmp = NULL;
if (group == NULL || field == NULL)
return 0;
/* clear the old values (if necessary) */
ASN1_OBJECT_free(field->fieldType);
ASN1_TYPE_free(field->p.other);
nid = EC_GROUP_get_field_type(group);
/* set OID for the field */
if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_OBJ_LIB);
goto err;
}
if (nid == NID_X9_62_prime_field) {
if ((tmp = BN_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
/* the parameters are specified by the prime number p */
if (!EC_GROUP_get_curve(group, tmp, NULL, NULL, NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* set the prime number */
field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL);
if (field->p.prime == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
} else if (nid == NID_X9_62_characteristic_two_field)
#ifdef OPENSSL_NO_EC2M
{
ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
goto err;
}
#else
{
int field_type;
X9_62_CHARACTERISTIC_TWO *char_two;
field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
char_two = field->p.char_two;
if (char_two == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
char_two->m = (long)EC_GROUP_get_degree(group);
field_type = EC_GROUP_get_basis_type(group);
if (field_type == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* set base type OID */
if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_OBJ_LIB);
goto err;
}
if (field_type == NID_X9_62_tpBasis) {
unsigned int k;
if (!EC_GROUP_get_trinomial_basis(group, &k))
goto err;
char_two->p.tpBasis = ASN1_INTEGER_new();
if (char_two->p.tpBasis == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) {
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
} else if (field_type == NID_X9_62_ppBasis) {
unsigned int k1, k2, k3;
if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
goto err;
char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
if (char_two->p.ppBasis == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
/* set k? values */
char_two->p.ppBasis->k1 = (long)k1;
char_two->p.ppBasis->k2 = (long)k2;
char_two->p.ppBasis->k3 = (long)k3;
} else { /* field_type == NID_X9_62_onBasis */
/* for ONB the parameters are (asn1) NULL */
char_two->p.onBasis = ASN1_NULL_new();
if (char_two->p.onBasis == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
}
#endif
else {
ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD);
goto err;
}
ok = 1;
err:
BN_free(tmp);
return ok;
}
static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
{
int ok = 0;
BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
unsigned char *a_buf = NULL, *b_buf = NULL;
size_t len;
if (!group || !curve || !curve->a || !curve->b)
return 0;
if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
/* get a and b */
if (!EC_GROUP_get_curve(group, NULL, tmp_1, tmp_2, NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/*
* Per SEC 1, the curve coefficients must be padded up to size. See C.2's
* definition of Curve, C.1's definition of FieldElement, and 2.3.5's
* definition of how to encode the field elements.
*/
len = ((size_t)EC_GROUP_get_degree(group) + 7) / 8;
if ((a_buf = OPENSSL_malloc(len)) == NULL
|| (b_buf = OPENSSL_malloc(len)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (BN_bn2binpad(tmp_1, a_buf, len) < 0
|| BN_bn2binpad(tmp_2, b_buf, len) < 0) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* set a and b */
if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len)
|| !ASN1_OCTET_STRING_set(curve->b, b_buf, len)) {
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
/* set the seed (optional) */
if (group->seed) {
if (!curve->seed)
if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
(int)group->seed_len)) {
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
} else {
ASN1_BIT_STRING_free(curve->seed);
curve->seed = NULL;
}
ok = 1;
err:
OPENSSL_free(a_buf);
OPENSSL_free(b_buf);
BN_free(tmp_1);
BN_free(tmp_2);
return ok;
}
ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
ECPARAMETERS *params)
{
size_t len = 0;
ECPARAMETERS *ret = NULL;
const BIGNUM *tmp;
unsigned char *buffer = NULL;
const EC_POINT *point = NULL;
point_conversion_form_t form;
ASN1_INTEGER *orig;
if (params == NULL) {
if ((ret = ECPARAMETERS_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
} else
ret = params;
/* set the version (always one) */
ret->version = (long)0x1;
/* set the fieldID */
if (!ec_asn1_group2fieldid(group, ret->fieldID)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* set the curve */
if (!ec_asn1_group2curve(group, ret->curve)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* set the base point */
if ((point = EC_GROUP_get0_generator(group)) == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
goto err;
}
form = EC_GROUP_get_point_conversion_form(group);
len = EC_POINT_point2buf(group, point, form, &buffer, NULL);
if (len == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
OPENSSL_free(buffer);
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
ASN1_STRING_set0(ret->base, buffer, len);
/* set the order */
tmp = EC_GROUP_get0_order(group);
if (tmp == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
ret->order = BN_to_ASN1_INTEGER(tmp, orig = ret->order);
if (ret->order == NULL) {
ret->order = orig;
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
/* set the cofactor (optional) */
tmp = EC_GROUP_get0_cofactor(group);
if (tmp != NULL) {
ret->cofactor = BN_to_ASN1_INTEGER(tmp, orig = ret->cofactor);
if (ret->cofactor == NULL) {
ret->cofactor = orig;
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
}
return ret;
err:
if (params == NULL)
ECPARAMETERS_free(ret);
return NULL;
}
ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group,
ECPKPARAMETERS *params)
{
int ok = 1, tmp;
ECPKPARAMETERS *ret = params;
if (ret == NULL) {
if ((ret = ECPKPARAMETERS_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
if (ret->type == ECPKPARAMETERS_TYPE_NAMED)
ASN1_OBJECT_free(ret->value.named_curve);
else if (ret->type == ECPKPARAMETERS_TYPE_EXPLICIT
&& ret->value.parameters != NULL)
ECPARAMETERS_free(ret->value.parameters);
}
if (EC_GROUP_get_asn1_flag(group) == OPENSSL_EC_NAMED_CURVE) {
/*
* use the asn1 OID to describe the elliptic curve parameters
*/
tmp = EC_GROUP_get_curve_name(group);
if (tmp) {
ASN1_OBJECT *asn1obj = OBJ_nid2obj(tmp);
if (asn1obj == NULL || OBJ_length(asn1obj) == 0) {
ASN1_OBJECT_free(asn1obj);
ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID);
ok = 0;
} else {
ret->type = ECPKPARAMETERS_TYPE_NAMED;
ret->value.named_curve = asn1obj;
}
} else
/* we don't know the nid => ERROR */
ok = 0;
} else {
/* use the ECPARAMETERS structure */
ret->type = ECPKPARAMETERS_TYPE_EXPLICIT;
if ((ret->value.parameters =
EC_GROUP_get_ecparameters(group, NULL)) == NULL)
ok = 0;
}
if (!ok) {
ECPKPARAMETERS_free(ret);
return NULL;
}
return ret;
}
EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
{
int ok = 0, tmp;
EC_GROUP *ret = NULL, *dup = NULL;
BIGNUM *p = NULL, *a = NULL, *b = NULL;
EC_POINT *point = NULL;
long field_bits;
int curve_name = NID_undef;
BN_CTX *ctx = NULL;
if (params->fieldID == NULL
|| params->fieldID->fieldType == NULL
|| params->fieldID->p.ptr == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
/*
* Now extract the curve parameters a and b. Note that, although SEC 1
* specifies the length of their encodings, historical versions of OpenSSL
* encoded them incorrectly, so we must accept any length for backwards
* compatibility.
*/
if (params->curve == NULL
|| params->curve->a == NULL || params->curve->a->data == NULL
|| params->curve->b == NULL || params->curve->b->data == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
if (a == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
if (b == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* get the field parameters */
tmp = OBJ_obj2nid(params->fieldID->fieldType);
if (tmp == NID_X9_62_characteristic_two_field)
#ifdef OPENSSL_NO_EC2M
{
ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
goto err;
}
#else
{
X9_62_CHARACTERISTIC_TWO *char_two;
char_two = params->fieldID->p.char_two;
field_bits = char_two->m;
if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
goto err;
}
if ((p = BN_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
/* get the base type */
tmp = OBJ_obj2nid(char_two->type);
if (tmp == NID_X9_62_tpBasis) {
long tmp_long;
if (!char_two->p.tpBasis) {
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
if (!(char_two->m > tmp_long && tmp_long > 0)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_TRINOMIAL_BASIS);
goto err;
}
/* create the polynomial */
if (!BN_set_bit(p, (int)char_two->m))
goto err;
if (!BN_set_bit(p, (int)tmp_long))
goto err;
if (!BN_set_bit(p, 0))
goto err;
} else if (tmp == NID_X9_62_ppBasis) {
X9_62_PENTANOMIAL *penta;
penta = char_two->p.ppBasis;
if (penta == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
if (!
(char_two->m > penta->k3 && penta->k3 > penta->k2
&& penta->k2 > penta->k1 && penta->k1 > 0)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_PENTANOMIAL_BASIS);
goto err;
}
/* create the polynomial */
if (!BN_set_bit(p, (int)char_two->m))
goto err;
if (!BN_set_bit(p, (int)penta->k1))
goto err;
if (!BN_set_bit(p, (int)penta->k2))
goto err;
if (!BN_set_bit(p, (int)penta->k3))
goto err;
if (!BN_set_bit(p, 0))
goto err;
} else if (tmp == NID_X9_62_onBasis) {
ERR_raise(ERR_LIB_EC, EC_R_NOT_IMPLEMENTED);
goto err;
} else { /* error */
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
/* create the EC_GROUP structure */
ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
}
#endif
else if (tmp == NID_X9_62_prime_field) {
/* we have a curve over a prime field */
/* extract the prime number */
if (params->fieldID->p.prime == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
if (p == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
if (BN_is_negative(p) || BN_is_zero(p)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
goto err;
}
field_bits = BN_num_bits(p);
if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
goto err;
}
/* create the EC_GROUP structure */
ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
} else {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
goto err;
}
if (ret == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* extract seed (optional) */
if (params->curve->seed != NULL) {
/*
* This happens for instance with
* fuzz/corpora/asn1/65cf44e85614c62f10cf3b7a7184c26293a19e4a
* and causes the OPENSSL_malloc below to choke on the
* zero length allocation request.
*/
if (params->curve->seed->length == 0) {
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
OPENSSL_free(ret->seed);
if ((ret->seed = OPENSSL_malloc(params->curve->seed->length)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
memcpy(ret->seed, params->curve->seed->data,
params->curve->seed->length);
ret->seed_len = params->curve->seed->length;
}
if (params->order == NULL
|| params->base == NULL
|| params->base->data == NULL
|| params->base->length == 0) {
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
if ((point = EC_POINT_new(ret)) == NULL)
goto err;
/* set the point conversion form */
EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
(params->base->data[0] & ~0x01));
/* extract the ec point */
if (!EC_POINT_oct2point(ret, point, params->base->data,
params->base->length, NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* extract the order */
if (ASN1_INTEGER_to_BN(params->order, a) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
if (BN_is_negative(a) || BN_is_zero(a)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
/* extract the cofactor (optional) */
if (params->cofactor == NULL) {
BN_free(b);
b = NULL;
} else if (ASN1_INTEGER_to_BN(params->cofactor, b) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
/* set the generator, order and cofactor (if present) */
if (!EC_GROUP_set_generator(ret, point, a, b)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/*
* Check if the explicit parameters group just created matches one of the
* built-in curves.
*
* We create a copy of the group just built, so that we can remove optional
* fields for the lookup: we do this to avoid the possibility that one of
* the optional parameters is used to force the library into using a less
* performant and less secure EC_METHOD instead of the specialized one.
* In any case, `seed` is not really used in any computation, while a
* cofactor different from the one in the built-in table is just
* mathematically wrong anyway and should not be used.
*/
if ((ctx = BN_CTX_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if ((dup = EC_GROUP_dup(ret)) == NULL
|| EC_GROUP_set_seed(dup, NULL, 0) != 1
|| !EC_GROUP_set_generator(dup, point, a, NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if ((curve_name = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) {
/*
* The input explicit parameters successfully matched one of the
* built-in curves: often for built-in curves we have specialized
* methods with better performance and hardening.
*
* In this case we replace the `EC_GROUP` created through explicit
* parameters with one created from a named group.
*/
EC_GROUP *named_group = NULL;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
/*
* NID_wap_wsg_idm_ecid_wtls12 and NID_secp224r1 are both aliases for
* the same curve, we prefer the SECP nid when matching explicit
* parameters as that is associated with a specialized EC_METHOD.
*/
if (curve_name == NID_wap_wsg_idm_ecid_wtls12)
curve_name = NID_secp224r1;
#endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
if ((named_group = EC_GROUP_new_by_curve_name(curve_name)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
EC_GROUP_free(ret);
ret = named_group;
/*
* Set the flag so that EC_GROUPs created from explicit parameters are
* serialized using explicit parameters by default.
*/
EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_EXPLICIT_CURVE);
/*
* If the input params do not contain the optional seed field we make
* sure it is not added to the returned group.
*
* The seed field is not really used inside libcrypto anyway, and
* adding it to parsed explicit parameter keys would alter their DER
* encoding output (because of the extra field) which could impact
* applications fingerprinting keys by their DER encoding.
*/
if (params->curve->seed == NULL) {
if (EC_GROUP_set_seed(ret, NULL, 0) != 1)
goto err;
}
}
ok = 1;
err:
if (!ok) {
EC_GROUP_free(ret);
ret = NULL;
}
EC_GROUP_free(dup);
BN_free(p);
BN_free(a);
BN_free(b);
EC_POINT_free(point);
BN_CTX_free(ctx);
return ret;
}
EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
{
EC_GROUP *ret = NULL;
int tmp = 0;
if (params == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
return NULL;
}
if (params->type == ECPKPARAMETERS_TYPE_NAMED) {
/* the curve is given by an OID */
tmp = OBJ_obj2nid(params->value.named_curve);
if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
return NULL;
}
EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
} else if (params->type == ECPKPARAMETERS_TYPE_EXPLICIT) {
/* the parameters are given by an ECPARAMETERS structure */
ret = EC_GROUP_new_from_ecparameters(params->value.parameters);
if (!ret) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
return NULL;
}
EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_EXPLICIT_CURVE);
} else if (params->type == ECPKPARAMETERS_TYPE_IMPLICIT) {
/* implicit parameters inherited from CA - unsupported */
return NULL;
} else {
ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
return NULL;
}
return ret;
}
/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
{
EC_GROUP *group = NULL;
ECPKPARAMETERS *params = NULL;
const unsigned char *p = *in;
if ((params = d2i_ECPKPARAMETERS(NULL, &p, len)) == NULL) {
ECPKPARAMETERS_free(params);
return NULL;
}
if ((group = EC_GROUP_new_from_ecpkparameters(params)) == NULL) {
ECPKPARAMETERS_free(params);
return NULL;
}
if (params->type == ECPKPARAMETERS_TYPE_EXPLICIT)
group->decoded_from_explicit_params = 1;
if (a) {
EC_GROUP_free(*a);
*a = group;
}
ECPKPARAMETERS_free(params);
*in = p;
return group;
}
int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
{
int ret = 0;
ECPKPARAMETERS *tmp = EC_GROUP_get_ecpkparameters(a, NULL);
if (tmp == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_GROUP2PKPARAMETERS_FAILURE);
return 0;
}
if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) {
ERR_raise(ERR_LIB_EC, EC_R_I2D_ECPKPARAMETERS_FAILURE);
ECPKPARAMETERS_free(tmp);
return 0;
}
ECPKPARAMETERS_free(tmp);
return ret;
}
/* some EC_KEY functions */
EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
{
EC_KEY *ret = NULL;
EC_PRIVATEKEY *priv_key = NULL;
const unsigned char *p = *in;
if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL)
return NULL;
if (a == NULL || *a == NULL) {
if ((ret = EC_KEY_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
} else
ret = *a;
if (priv_key->parameters) {
EC_GROUP_free(ret->group);
ret->group = EC_GROUP_new_from_ecpkparameters(priv_key->parameters);
if (ret->group != NULL
&& priv_key->parameters->type == ECPKPARAMETERS_TYPE_EXPLICIT)
ret->group->decoded_from_explicit_params = 1;
}
if (ret->group == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
ret->version = priv_key->version;
if (priv_key->privateKey) {
ASN1_OCTET_STRING *pkey = priv_key->privateKey;
if (EC_KEY_oct2priv(ret, ASN1_STRING_get0_data(pkey),
ASN1_STRING_length(pkey)) == 0)
goto err;
} else {
ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
goto err;
}
if (EC_GROUP_get_curve_name(ret->group) == NID_sm2)
EC_KEY_set_flags(ret, EC_FLAG_SM2_RANGE);
EC_POINT_clear_free(ret->pub_key);
ret->pub_key = EC_POINT_new(ret->group);
if (ret->pub_key == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (priv_key->publicKey) {
const unsigned char *pub_oct;
int pub_oct_len;
pub_oct = ASN1_STRING_get0_data(priv_key->publicKey);
pub_oct_len = ASN1_STRING_length(priv_key->publicKey);
if (!EC_KEY_oct2key(ret, pub_oct, pub_oct_len, NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
} else {
if (ret->group->meth->keygenpub == NULL
|| ret->group->meth->keygenpub(ret) == 0)
goto err;
/* Remember the original private-key-only encoding. */
ret->enc_flag |= EC_PKEY_NO_PUBKEY;
}
if (a)
*a = ret;
EC_PRIVATEKEY_free(priv_key);
*in = p;
ret->dirty_cnt++;
return ret;
err:
if (a == NULL || *a != ret)
EC_KEY_free(ret);
EC_PRIVATEKEY_free(priv_key);
return NULL;
}
int i2d_ECPrivateKey(const EC_KEY *a, unsigned char **out)
{
int ret = 0, ok = 0;
unsigned char *priv= NULL, *pub= NULL;
size_t privlen = 0, publen = 0;
EC_PRIVATEKEY *priv_key = NULL;
if (a == NULL || a->group == NULL ||
(!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
if ((priv_key = EC_PRIVATEKEY_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
priv_key->version = a->version;
privlen = EC_KEY_priv2buf(a, &priv);
if (privlen == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
ASN1_STRING_set0(priv_key->privateKey, priv, privlen);
priv = NULL;
if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) {
if ((priv_key->parameters =
EC_GROUP_get_ecpkparameters(a->group,
priv_key->parameters)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
}
if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) {
priv_key->publicKey = ASN1_BIT_STRING_new();
if (priv_key->publicKey == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
publen = EC_KEY_key2buf(a, a->conv_form, &pub, NULL);
if (publen == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
ASN1_STRING_set0(priv_key->publicKey, pub, publen);
pub = NULL;
}
if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
ok = 1;
err:
OPENSSL_clear_free(priv, privlen);
OPENSSL_free(pub);
EC_PRIVATEKEY_free(priv_key);
return (ok ? ret : 0);
}
int i2d_ECParameters(const EC_KEY *a, unsigned char **out)
{
if (a == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
return i2d_ECPKParameters(a->group, out);
}
EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
{
EC_KEY *ret;
if (in == NULL || *in == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (a == NULL || *a == NULL) {
if ((ret = EC_KEY_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
ret = *a;
if (!d2i_ECPKParameters(&ret->group, in, len)) {
if (a == NULL || *a != ret)
EC_KEY_free(ret);
else
ret->dirty_cnt++;
return NULL;
}
if (EC_GROUP_get_curve_name(ret->group) == NID_sm2)
EC_KEY_set_flags(ret, EC_FLAG_SM2_RANGE);
ret->dirty_cnt++;
if (a)
*a = ret;
return ret;
}
EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
{
EC_KEY *ret = NULL;
if (a == NULL || (*a) == NULL || (*a)->group == NULL) {
/*
* sorry, but a EC_GROUP-structure is necessary to set the public key
*/
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
ret = *a;
/* EC_KEY_opt2key updates dirty_cnt */
if (!EC_KEY_oct2key(ret, *in, len, NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
return 0;
}
*in += len;
return ret;
}
int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
{
size_t buf_len = 0;
int new_buffer = 0;
- if (a == NULL) {
+ if (a == NULL || a->pub_key == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
buf_len = EC_POINT_point2oct(a->group, a->pub_key,
a->conv_form, NULL, 0, NULL);
if (out == NULL || buf_len == 0)
/* out == NULL => just return the length of the octet string */
return buf_len;
if (*out == NULL) {
if ((*out = OPENSSL_malloc(buf_len)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
new_buffer = 1;
}
if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
*out, buf_len, NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
if (new_buffer) {
OPENSSL_free(*out);
*out = NULL;
}
return 0;
}
if (!new_buffer)
*out += buf_len;
return buf_len;
}
DECLARE_ASN1_FUNCTIONS(ECDSA_SIG)
DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECDSA_SIG, ECDSA_SIG)
#endif /* FIPS_MODULE */
ECDSA_SIG *ECDSA_SIG_new(void)
{
ECDSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
if (sig == NULL)
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return sig;
}
void ECDSA_SIG_free(ECDSA_SIG *sig)
{
if (sig == NULL)
return;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
OPENSSL_free(sig);
}
ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **psig, const unsigned char **ppin, long len)
{
ECDSA_SIG *sig;
if (len < 0)
return NULL;
if (psig != NULL && *psig != NULL) {
sig = *psig;
} else {
sig = ECDSA_SIG_new();
if (sig == NULL)
return NULL;
}
if (sig->r == NULL)
sig->r = BN_new();
if (sig->s == NULL)
sig->s = BN_new();
if (sig->r == NULL || sig->s == NULL
|| ossl_decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) {
if (psig == NULL || *psig == NULL)
ECDSA_SIG_free(sig);
return NULL;
}
if (psig != NULL && *psig == NULL)
*psig = sig;
return sig;
}
int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **ppout)
{
BUF_MEM *buf = NULL;
size_t encoded_len;
WPACKET pkt;
if (ppout == NULL) {
if (!WPACKET_init_null(&pkt, 0))
return -1;
} else if (*ppout == NULL) {
if ((buf = BUF_MEM_new()) == NULL
|| !WPACKET_init_len(&pkt, buf, 0)) {
BUF_MEM_free(buf);
return -1;
}
} else {
if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0))
return -1;
}
if (!ossl_encode_der_dsa_sig(&pkt, sig->r, sig->s)
|| !WPACKET_get_total_written(&pkt, &encoded_len)
|| !WPACKET_finish(&pkt)) {
BUF_MEM_free(buf);
WPACKET_cleanup(&pkt);
return -1;
}
if (ppout != NULL) {
if (*ppout == NULL) {
*ppout = (unsigned char *)buf->data;
buf->data = NULL;
BUF_MEM_free(buf);
} else {
*ppout += encoded_len;
}
}
return (int)encoded_len;
}
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig)
{
return sig->r;
}
const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig)
{
return sig->s;
}
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (r == NULL || s == NULL)
return 0;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
sig->r = r;
sig->s = s;
return 1;
}
int ECDSA_size(const EC_KEY *ec)
{
int ret;
ECDSA_SIG sig;
const EC_GROUP *group;
const BIGNUM *bn;
if (ec == NULL)
return 0;
group = EC_KEY_get0_group(ec);
if (group == NULL)
return 0;
bn = EC_GROUP_get0_order(group);
if (bn == NULL)
return 0;
sig.r = sig.s = (BIGNUM *)bn;
ret = i2d_ECDSA_SIG(&sig, NULL);
if (ret < 0)
ret = 0;
return ret;
}
diff --git a/crypto/openssl/crypto/ec/ec_backend.c b/crypto/openssl/crypto/ec/ec_backend.c
index 98e2c418e416..cad576fc48a1 100644
--- a/crypto/openssl/crypto/ec/ec_backend.c
+++ b/crypto/openssl/crypto/ec/ec_backend.c
@@ -1,842 +1,836 @@
/*
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* Low level APIs related to EC_KEY are deprecated for public use,
* but still ok for internal use.
*/
#include "internal/deprecated.h"
#include <openssl/core_names.h>
#include <openssl/objects.h>
#include <openssl/params.h>
#include <openssl/err.h>
#ifndef FIPS_MODULE
# include <openssl/engine.h>
# include <openssl/x509.h>
#endif
#include "crypto/bn.h"
#include "crypto/ec.h"
#include "ec_local.h"
#include "e_os.h"
#include "internal/param_build_set.h"
/* Mapping between a flag and a name */
static const OSSL_ITEM encoding_nameid_map[] = {
{ OPENSSL_EC_EXPLICIT_CURVE, OSSL_PKEY_EC_ENCODING_EXPLICIT },
{ OPENSSL_EC_NAMED_CURVE, OSSL_PKEY_EC_ENCODING_GROUP },
};
static const OSSL_ITEM check_group_type_nameid_map[] = {
{ 0, OSSL_PKEY_EC_GROUP_CHECK_DEFAULT },
{ EC_FLAG_CHECK_NAMED_GROUP, OSSL_PKEY_EC_GROUP_CHECK_NAMED },
{ EC_FLAG_CHECK_NAMED_GROUP_NIST, OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST },
};
static const OSSL_ITEM format_nameid_map[] = {
{ (int)POINT_CONVERSION_UNCOMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED },
{ (int)POINT_CONVERSION_COMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED },
{ (int)POINT_CONVERSION_HYBRID, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID },
};
int ossl_ec_encoding_name2id(const char *name)
{
size_t i, sz;
/* Return the default value if there is no name */
if (name == NULL)
return OPENSSL_EC_NAMED_CURVE;
for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) {
if (OPENSSL_strcasecmp(name, encoding_nameid_map[i].ptr) == 0)
return encoding_nameid_map[i].id;
}
return -1;
}
static char *ec_param_encoding_id2name(int id)
{
size_t i, sz;
for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) {
if (id == (int)encoding_nameid_map[i].id)
return encoding_nameid_map[i].ptr;
}
return NULL;
}
char *ossl_ec_check_group_type_id2name(int id)
{
size_t i, sz;
for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
if (id == (int)check_group_type_nameid_map[i].id)
return check_group_type_nameid_map[i].ptr;
}
return NULL;
}
static int ec_check_group_type_name2id(const char *name)
{
size_t i, sz;
/* Return the default value if there is no name */
if (name == NULL)
return 0;
for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
if (OPENSSL_strcasecmp(name, check_group_type_nameid_map[i].ptr) == 0)
return check_group_type_nameid_map[i].id;
}
return -1;
}
int ossl_ec_set_check_group_type_from_name(EC_KEY *ec, const char *name)
{
int flags = ec_check_group_type_name2id(name);
if (flags == -1)
return 0;
EC_KEY_clear_flags(ec, EC_FLAG_CHECK_NAMED_GROUP_MASK);
EC_KEY_set_flags(ec, flags);
return 1;
}
static int ec_set_check_group_type_from_param(EC_KEY *ec, const OSSL_PARAM *p)
{
const char *name = NULL;
int status = 0;
switch (p->data_type) {
case OSSL_PARAM_UTF8_STRING:
name = p->data;
status = (name != NULL);
break;
case OSSL_PARAM_UTF8_PTR:
status = OSSL_PARAM_get_utf8_ptr(p, &name);
break;
}
if (status)
return ossl_ec_set_check_group_type_from_name(ec, name);
return 0;
}
int ossl_ec_pt_format_name2id(const char *name)
{
size_t i, sz;
/* Return the default value if there is no name */
if (name == NULL)
return (int)POINT_CONVERSION_UNCOMPRESSED;
for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
if (OPENSSL_strcasecmp(name, format_nameid_map[i].ptr) == 0)
return format_nameid_map[i].id;
}
return -1;
}
char *ossl_ec_pt_format_id2name(int id)
{
size_t i, sz;
for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
if (id == (int)format_nameid_map[i].id)
return format_nameid_map[i].ptr;
}
return NULL;
}
static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
OSSL_PARAM params[], BN_CTX *bnctx,
unsigned char **genbuf)
{
int ret = 0, fid;
const char *field_type;
const OSSL_PARAM *param = NULL;
const OSSL_PARAM *param_p = NULL;
const OSSL_PARAM *param_a = NULL;
const OSSL_PARAM *param_b = NULL;
fid = EC_GROUP_get_field_type(group);
if (fid == NID_X9_62_prime_field) {
field_type = SN_X9_62_prime_field;
} else if (fid == NID_X9_62_characteristic_two_field) {
#ifdef OPENSSL_NO_EC2M
ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
goto err;
#else
field_type = SN_X9_62_characteristic_two_field;
#endif
} else {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
return 0;
}
param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P);
param_a = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A);
param_b = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B);
if (tmpl != NULL || param_p != NULL || param_a != NULL || param_b != NULL)
{
BIGNUM *p = BN_CTX_get(bnctx);
BIGNUM *a = BN_CTX_get(bnctx);
BIGNUM *b = BN_CTX_get(bnctx);
if (b == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_GROUP_get_curve(group, p, a, b, bnctx)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
goto err;
}
if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_P, p)
|| !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_A, a)
|| !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_B, b)) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER);
if (tmpl != NULL || param != NULL) {
const BIGNUM *order = EC_GROUP_get0_order(group);
if (order == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_ORDER,
order)) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE);
if (tmpl != NULL || param != NULL) {
if (!ossl_param_build_set_utf8_string(tmpl, params,
OSSL_PKEY_PARAM_EC_FIELD_TYPE,
field_type)) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR);
if (tmpl != NULL || param != NULL) {
size_t genbuf_len;
const EC_POINT *genpt = EC_GROUP_get0_generator(group);
point_conversion_form_t genform = EC_GROUP_get_point_conversion_form(group);
if (genpt == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
goto err;
}
genbuf_len = EC_POINT_point2buf(group, genpt, genform, genbuf, bnctx);
if (genbuf_len == 0) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
goto err;
}
if (!ossl_param_build_set_octet_string(tmpl, params,
OSSL_PKEY_PARAM_EC_GENERATOR,
*genbuf, genbuf_len)) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR);
if (tmpl != NULL || param != NULL) {
const BIGNUM *cofactor = EC_GROUP_get0_cofactor(group);
if (cofactor != NULL
&& !ossl_param_build_set_bn(tmpl, params,
OSSL_PKEY_PARAM_EC_COFACTOR, cofactor)) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
if (tmpl != NULL || param != NULL) {
unsigned char *seed = EC_GROUP_get0_seed(group);
size_t seed_len = EC_GROUP_get_seed_len(group);
if (seed != NULL
&& seed_len > 0
&& !ossl_param_build_set_octet_string(tmpl, params,
OSSL_PKEY_PARAM_EC_SEED,
seed, seed_len)) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
ret = 1;
err:
return ret;
}
int ossl_ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
OSSL_PARAM params[], OSSL_LIB_CTX *libctx,
const char *propq,
BN_CTX *bnctx, unsigned char **genbuf)
{
int ret = 0, curve_nid, encoding_flag;
const char *encoding_name, *pt_form_name;
point_conversion_form_t genform;
if (group == NULL) {
ERR_raise(ERR_LIB_EC,EC_R_PASSED_NULL_PARAMETER);
return 0;
}
genform = EC_GROUP_get_point_conversion_form(group);
pt_form_name = ossl_ec_pt_format_id2name(genform);
if (pt_form_name == NULL
|| !ossl_param_build_set_utf8_string(
tmpl, params,
OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, pt_form_name)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM);
return 0;
}
encoding_flag = EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE;
encoding_name = ec_param_encoding_id2name(encoding_flag);
if (encoding_name == NULL
|| !ossl_param_build_set_utf8_string(tmpl, params,
OSSL_PKEY_PARAM_EC_ENCODING,
encoding_name)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
if (!ossl_param_build_set_int(tmpl, params,
OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS,
group->decoded_from_explicit_params))
return 0;
curve_nid = EC_GROUP_get_curve_name(group);
/*
* Get the explicit parameters in these two cases:
* - We do not have a template, i.e. specific parameters are requested
* - The curve is not a named curve
*/
if (tmpl == NULL || curve_nid == NID_undef)
if (!ec_group_explicit_todata(group, tmpl, params, bnctx, genbuf))
goto err;
if (curve_nid != NID_undef) {
/* Named curve */
const char *curve_name = OSSL_EC_curve_nid2name(curve_nid);
if (curve_name == NULL
|| !ossl_param_build_set_utf8_string(tmpl, params,
OSSL_PKEY_PARAM_GROUP_NAME,
curve_name)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
goto err;
}
}
ret = 1;
err:
return ret;
}
/*
* The intention with the "backend" source file is to offer backend support
* for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
* implementations alike.
*/
int ossl_ec_set_ecdh_cofactor_mode(EC_KEY *ec, int mode)
{
const EC_GROUP *ecg = EC_KEY_get0_group(ec);
const BIGNUM *cofactor;
/*
* mode can be only 0 for disable, or 1 for enable here.
*
* This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
* also supports mode == -1 with the meaning of "reset to the default for
* the associated key".
*/
if (mode < 0 || mode > 1)
return 0;
if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL )
return 0;
/* ECDH cofactor mode has no effect if cofactor is 1 */
if (BN_is_one(cofactor))
return 1;
if (mode == 1)
EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH);
else if (mode == 0)
EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH);
return 1;
}
/*
* Callers of ossl_ec_key_fromdata MUST make sure that ec_key_params_fromdata has
* been called before!
*
* This function only gets the bare keypair, domain parameters and other
* parameters are treated separately, and domain parameters are required to
* define a keypair.
*/
int ossl_ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private)
{
const OSSL_PARAM *param_priv_key = NULL, *param_pub_key = NULL;
BN_CTX *ctx = NULL;
BIGNUM *priv_key = NULL;
unsigned char *pub_key = NULL;
size_t pub_key_len;
const EC_GROUP *ecg = NULL;
EC_POINT *pub_point = NULL;
int ok = 0;
ecg = EC_KEY_get0_group(ec);
if (ecg == NULL)
return 0;
param_pub_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
if (include_private)
param_priv_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
if (ctx == NULL)
goto err;
if (param_pub_key != NULL)
if (!OSSL_PARAM_get_octet_string(param_pub_key,
(void **)&pub_key, 0, &pub_key_len)
|| (pub_point = EC_POINT_new(ecg)) == NULL
|| !EC_POINT_oct2point(ecg, pub_point, pub_key, pub_key_len, ctx))
goto err;
if (param_priv_key != NULL && include_private) {
int fixed_words;
const BIGNUM *order;
/*
* Key import/export should never leak the bit length of the secret
* scalar in the key.
*
* For this reason, on export we use padded BIGNUMs with fixed length.
*
* When importing we also should make sure that, even if short lived,
* the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
* soon as possible, so that any processing of this BIGNUM might opt for
* constant time implementations in the backend.
*
* Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
* to preallocate the BIGNUM internal buffer to a fixed public size big
* enough that operations performed during the processing never trigger
* a realloc which would leak the size of the scalar through memory
* accesses.
*
* Fixed Length
* ------------
*
* The order of the large prime subgroup of the curve is our choice for
* a fixed public size, as that is generally the upper bound for
* generating a private key in EC cryptosystems and should fit all valid
* secret scalars.
*
* For padding on export we just use the bit length of the order
* converted to bytes (rounding up).
*
* For preallocating the BIGNUM storage we look at the number of "words"
* required for the internal representation of the order, and we
* preallocate 2 extra "words" in case any of the subsequent processing
* might temporarily overflow the order length.
*/
order = EC_GROUP_get0_order(ecg);
if (order == NULL || BN_is_zero(order))
goto err;
fixed_words = bn_get_top(order) + 2;
if ((priv_key = BN_secure_new()) == NULL)
goto err;
if (bn_wexpand(priv_key, fixed_words) == NULL)
goto err;
BN_set_flags(priv_key, BN_FLG_CONSTTIME);
if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key))
goto err;
}
if (priv_key != NULL
&& !EC_KEY_set_private_key(ec, priv_key))
goto err;
if (pub_point != NULL
&& !EC_KEY_set_public_key(ec, pub_point))
goto err;
ok = 1;
err:
BN_CTX_free(ctx);
BN_clear_free(priv_key);
OPENSSL_free(pub_key);
EC_POINT_free(pub_point);
return ok;
}
int ossl_ec_group_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
int ok = 0;
EC_GROUP *group = NULL;
if (ec == NULL)
return 0;
group = EC_GROUP_new_from_params(params, ossl_ec_key_get_libctx(ec),
ossl_ec_key_get0_propq(ec));
if (!EC_KEY_set_group(ec, group))
goto err;
ok = 1;
err:
EC_GROUP_free(group);
return ok;
}
static int ec_key_point_format_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
int format = -1;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
if (p != NULL) {
if (!ossl_ec_pt_format_param2id(p, &format)) {
ECerr(0, EC_R_INVALID_FORM);
return 0;
}
EC_KEY_set_conv_form(ec, format);
}
return 1;
}
static int ec_key_group_check_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE);
if (p != NULL)
return ec_set_check_group_type_from_param(ec, p);
return 1;
}
static int ec_set_include_public(EC_KEY *ec, int include)
{
int flags = EC_KEY_get_enc_flags(ec);
if (!include)
flags |= EC_PKEY_NO_PUBKEY;
else
flags &= ~EC_PKEY_NO_PUBKEY;
EC_KEY_set_enc_flags(ec, flags);
return 1;
}
int ossl_ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
if (ec == NULL)
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
if (p != NULL) {
int mode;
if (!OSSL_PARAM_get_int(p, &mode)
|| !ossl_ec_set_ecdh_cofactor_mode(ec, mode))
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC);
if (p != NULL) {
int include = 1;
if (!OSSL_PARAM_get_int(p, &include)
|| !ec_set_include_public(ec, include))
return 0;
}
if (!ec_key_point_format_fromdata(ec, params))
return 0;
if (!ec_key_group_check_fromdata(ec, params))
return 0;
return 1;
}
int ossl_ec_key_is_foreign(const EC_KEY *ec)
{
#ifndef FIPS_MODULE
if (ec->engine != NULL || EC_KEY_get_method(ec) != EC_KEY_OpenSSL())
return 1;
#endif
return 0;
}
EC_KEY *ossl_ec_key_dup(const EC_KEY *src, int selection)
{
EC_KEY *ret;
if (src == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((ret = ossl_ec_key_new_method_int(src->libctx, src->propq,
src->engine)) == NULL)
return NULL;
/* copy the parameters */
if (src->group != NULL
&& (selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
ret->group = ossl_ec_group_new_ex(src->libctx, src->propq,
src->group->meth);
if (ret->group == NULL
|| !EC_GROUP_copy(ret->group, src->group))
goto err;
- if (src->meth != NULL) {
-#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
- if (src->engine != NULL && ENGINE_init(src->engine) == 0)
- goto err;
- ret->engine = src->engine;
-#endif
+ if (src->meth != NULL)
ret->meth = src->meth;
- }
}
/* copy the public key */
if (src->pub_key != NULL
&& (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
if (ret->group == NULL)
/* no parameter-less keys allowed */
goto err;
ret->pub_key = EC_POINT_new(ret->group);
if (ret->pub_key == NULL
|| !EC_POINT_copy(ret->pub_key, src->pub_key))
goto err;
}
/* copy the private key */
if (src->priv_key != NULL
&& (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if (ret->group == NULL)
/* no parameter-less keys allowed */
goto err;
ret->priv_key = BN_new();
if (ret->priv_key == NULL || !BN_copy(ret->priv_key, src->priv_key))
goto err;
if (ret->group->meth->keycopy
&& ret->group->meth->keycopy(ret, src) == 0)
goto err;
}
/* copy the rest */
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) {
ret->enc_flag = src->enc_flag;
ret->conv_form = src->conv_form;
}
ret->version = src->version;
ret->flags = src->flags;
#ifndef FIPS_MODULE
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
&ret->ex_data, &src->ex_data))
goto err;
#endif
if (ret->meth != NULL && ret->meth->copy != NULL) {
if ((selection
& OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
goto err;
if (ret->meth->copy(ret, src) == 0)
goto err;
}
return ret;
err:
EC_KEY_free(ret);
return NULL;
}
int ossl_ec_encoding_param2id(const OSSL_PARAM *p, int *id)
{
const char *name = NULL;
int status = 0;
switch (p->data_type) {
case OSSL_PARAM_UTF8_STRING:
/* The OSSL_PARAM functions have no support for this */
name = p->data;
status = (name != NULL);
break;
case OSSL_PARAM_UTF8_PTR:
status = OSSL_PARAM_get_utf8_ptr(p, &name);
break;
}
if (status) {
int i = ossl_ec_encoding_name2id(name);
if (i >= 0) {
*id = i;
return 1;
}
}
return 0;
}
int ossl_ec_pt_format_param2id(const OSSL_PARAM *p, int *id)
{
const char *name = NULL;
int status = 0;
switch (p->data_type) {
case OSSL_PARAM_UTF8_STRING:
/* The OSSL_PARAM functions have no support for this */
name = p->data;
status = (name != NULL);
break;
case OSSL_PARAM_UTF8_PTR:
status = OSSL_PARAM_get_utf8_ptr(p, &name);
break;
}
if (status) {
int i = ossl_ec_pt_format_name2id(name);
if (i >= 0) {
*id = i;
return 1;
}
}
return 0;
}
#ifndef FIPS_MODULE
int ossl_x509_algor_is_sm2(const X509_ALGOR *palg)
{
int ptype = 0;
const void *pval = NULL;
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
if (ptype == V_ASN1_OBJECT)
return OBJ_obj2nid((ASN1_OBJECT *)pval) == NID_sm2;
if (ptype == V_ASN1_SEQUENCE) {
const ASN1_STRING *str = pval;
const unsigned char *der = str->data;
int derlen = str->length;
EC_GROUP *group;
int ret;
if ((group = d2i_ECPKParameters(NULL, &der, derlen)) == NULL)
ret = 0;
else
ret = (EC_GROUP_get_curve_name(group) == NID_sm2);
EC_GROUP_free(group);
return ret;
}
return 0;
}
EC_KEY *ossl_ec_key_param_from_x509_algor(const X509_ALGOR *palg,
OSSL_LIB_CTX *libctx, const char *propq)
{
int ptype = 0;
const void *pval = NULL;
EC_KEY *eckey = NULL;
EC_GROUP *group = NULL;
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
if ((eckey = EC_KEY_new_ex(libctx, propq)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto ecerr;
}
if (ptype == V_ASN1_SEQUENCE) {
const ASN1_STRING *pstr = pval;
const unsigned char *pm = pstr->data;
int pmlen = pstr->length;
if (d2i_ECParameters(&eckey, &pm, pmlen) == NULL) {
ERR_raise(ERR_LIB_EC, 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
*/
group = EC_GROUP_new_by_curve_name_ex(libctx, propq, 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 {
ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
goto ecerr;
}
return eckey;
ecerr:
EC_KEY_free(eckey);
EC_GROUP_free(group);
return NULL;
}
EC_KEY *ossl_ec_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
OSSL_LIB_CTX *libctx, const char *propq)
{
const unsigned char *p = NULL;
int pklen;
EC_KEY *eckey = NULL;
const X509_ALGOR *palg;
if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
return 0;
eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq);
if (eckey == NULL)
goto err;
/* We have parameters now set private key */
if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
goto err;
}
return eckey;
err:
EC_KEY_free(eckey);
return NULL;
}
#endif
diff --git a/crypto/openssl/crypto/ec/ec_lib.c b/crypto/openssl/crypto/ec/ec_lib.c
index b1696d93bd6d..a082876fb479 100644
--- a/crypto/openssl/crypto/ec/ec_lib.c
+++ b/crypto/openssl/crypto/ec/ec_lib.c
@@ -1,1760 +1,1761 @@
/*
- * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* EC_GROUP low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <string.h>
#include <openssl/params.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
#include "crypto/ec.h"
+#include "crypto/bn.h"
#include "internal/nelem.h"
#include "ec_local.h"
/* functions for EC_GROUP objects */
EC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
const EC_METHOD *meth)
{
EC_GROUP *ret;
if (meth == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_SLOT_FULL);
return NULL;
}
if (meth->group_init == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->libctx = libctx;
if (propq != NULL) {
ret->propq = OPENSSL_strdup(propq);
if (ret->propq == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
ret->meth = meth;
if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
ret->order = BN_new();
if (ret->order == NULL)
goto err;
ret->cofactor = BN_new();
if (ret->cofactor == NULL)
goto err;
}
ret->asn1_flag = OPENSSL_EC_EXPLICIT_CURVE;
ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
if (!meth->group_init(ret))
goto err;
return ret;
err:
BN_free(ret->order);
BN_free(ret->cofactor);
OPENSSL_free(ret->propq);
OPENSSL_free(ret);
return NULL;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
# ifndef FIPS_MODULE
EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
{
return ossl_ec_group_new_ex(NULL, NULL, meth);
}
# endif
#endif
void EC_pre_comp_free(EC_GROUP *group)
{
switch (group->pre_comp_type) {
case PCT_none:
break;
case PCT_nistz256:
#ifdef ECP_NISTZ256_ASM
EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
#endif
break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
case PCT_nistp224:
EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
break;
case PCT_nistp256:
EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
break;
case PCT_nistp521:
EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
break;
#else
case PCT_nistp224:
case PCT_nistp256:
case PCT_nistp521:
break;
#endif
case PCT_ec:
EC_ec_pre_comp_free(group->pre_comp.ec);
break;
}
group->pre_comp.ec = NULL;
}
void EC_GROUP_free(EC_GROUP *group)
{
if (!group)
return;
if (group->meth->group_finish != 0)
group->meth->group_finish(group);
EC_pre_comp_free(group);
BN_MONT_CTX_free(group->mont_data);
EC_POINT_free(group->generator);
BN_free(group->order);
BN_free(group->cofactor);
OPENSSL_free(group->seed);
OPENSSL_free(group->propq);
OPENSSL_free(group);
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
void EC_GROUP_clear_free(EC_GROUP *group)
{
if (!group)
return;
if (group->meth->group_clear_finish != 0)
group->meth->group_clear_finish(group);
else if (group->meth->group_finish != 0)
group->meth->group_finish(group);
EC_pre_comp_free(group);
BN_MONT_CTX_free(group->mont_data);
EC_POINT_clear_free(group->generator);
BN_clear_free(group->order);
BN_clear_free(group->cofactor);
OPENSSL_clear_free(group->seed, group->seed_len);
OPENSSL_clear_free(group, sizeof(*group));
}
#endif
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
{
if (dest->meth->group_copy == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (dest->meth != src->meth) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (dest == src)
return 1;
dest->libctx = src->libctx;
dest->curve_name = src->curve_name;
/* Copy precomputed */
dest->pre_comp_type = src->pre_comp_type;
switch (src->pre_comp_type) {
case PCT_none:
dest->pre_comp.ec = NULL;
break;
case PCT_nistz256:
#ifdef ECP_NISTZ256_ASM
dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
#endif
break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
case PCT_nistp224:
dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
break;
case PCT_nistp256:
dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
break;
case PCT_nistp521:
dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
break;
#else
case PCT_nistp224:
case PCT_nistp256:
case PCT_nistp521:
break;
#endif
case PCT_ec:
dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
break;
}
if (src->mont_data != NULL) {
if (dest->mont_data == NULL) {
dest->mont_data = BN_MONT_CTX_new();
if (dest->mont_data == NULL)
return 0;
}
if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
return 0;
} else {
/* src->generator == NULL */
BN_MONT_CTX_free(dest->mont_data);
dest->mont_data = NULL;
}
if (src->generator != NULL) {
if (dest->generator == NULL) {
dest->generator = EC_POINT_new(dest);
if (dest->generator == NULL)
return 0;
}
if (!EC_POINT_copy(dest->generator, src->generator))
return 0;
} else {
/* src->generator == NULL */
EC_POINT_clear_free(dest->generator);
dest->generator = NULL;
}
if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
if (!BN_copy(dest->order, src->order))
return 0;
if (!BN_copy(dest->cofactor, src->cofactor))
return 0;
}
dest->asn1_flag = src->asn1_flag;
dest->asn1_form = src->asn1_form;
dest->decoded_from_explicit_params = src->decoded_from_explicit_params;
if (src->seed) {
OPENSSL_free(dest->seed);
if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!memcpy(dest->seed, src->seed, src->seed_len))
return 0;
dest->seed_len = src->seed_len;
} else {
OPENSSL_free(dest->seed);
dest->seed = NULL;
dest->seed_len = 0;
}
return dest->meth->group_copy(dest, src);
}
EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
{
EC_GROUP *t = NULL;
int ok = 0;
if (a == NULL)
return NULL;
if ((t = ossl_ec_group_new_ex(a->libctx, a->propq, a->meth)) == NULL)
return NULL;
if (!EC_GROUP_copy(t, a))
goto err;
ok = 1;
err:
if (!ok) {
EC_GROUP_free(t);
return NULL;
}
return t;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
{
return group->meth;
}
int EC_METHOD_get_field_type(const EC_METHOD *meth)
{
return meth->field_type;
}
#endif
static int ec_precompute_mont_data(EC_GROUP *);
/*-
* Try computing cofactor from the generator order (n) and field cardinality (q).
* This works for all curves of cryptographic interest.
*
* Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q)
* h_min = (q + 1 - 2*sqrt(q))/n
* h_max = (q + 1 + 2*sqrt(q))/n
* h_max - h_min = 4*sqrt(q)/n
* So if n > 4*sqrt(q) holds, there is only one possible value for h:
* h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
*
* Otherwise, zero cofactor and return success.
*/
static int ec_guess_cofactor(EC_GROUP *group) {
int ret = 0;
BN_CTX *ctx = NULL;
BIGNUM *q = NULL;
/*-
* If the cofactor is too large, we cannot guess it.
* The RHS of below is a strict overestimate of lg(4 * sqrt(q))
*/
if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) {
/* default to 0 */
BN_zero(group->cofactor);
/* return success */
return 1;
}
if ((ctx = BN_CTX_new_ex(group->libctx)) == NULL)
return 0;
BN_CTX_start(ctx);
if ((q = BN_CTX_get(ctx)) == NULL)
goto err;
/* set q = 2**m for binary fields; q = p otherwise */
if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
BN_zero(q);
if (!BN_set_bit(q, BN_num_bits(group->field) - 1))
goto err;
} else {
if (!BN_copy(q, group->field))
goto err;
}
/* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */
if (!BN_rshift1(group->cofactor, group->order) /* n/2 */
|| !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */
/* q + 1 + n/2 */
|| !BN_add(group->cofactor, group->cofactor, BN_value_one())
/* (q + 1 + n/2)/n */
|| !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ret;
}
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor)
{
if (generator == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/* require group->field >= 1 */
if (group->field == NULL || BN_is_zero(group->field)
|| BN_is_negative(group->field)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
return 0;
}
/*-
* - require order >= 1
* - enforce upper bound due to Hasse thm: order can be no more than one bit
* longer than field cardinality
*/
if (order == NULL || BN_is_zero(order) || BN_is_negative(order)
|| BN_num_bits(order) > BN_num_bits(group->field) + 1) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
return 0;
}
/*-
* Unfortunately the cofactor is an optional field in many standards.
* Internally, the lib uses 0 cofactor as a marker for "unknown cofactor".
* So accept cofactor == NULL or cofactor >= 0.
*/
if (cofactor != NULL && BN_is_negative(cofactor)) {
ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR);
return 0;
}
if (group->generator == NULL) {
group->generator = EC_POINT_new(group);
if (group->generator == NULL)
return 0;
}
if (!EC_POINT_copy(group->generator, generator))
return 0;
if (!BN_copy(group->order, order))
return 0;
/* Either take the provided positive cofactor, or try to compute it */
if (cofactor != NULL && !BN_is_zero(cofactor)) {
if (!BN_copy(group->cofactor, cofactor))
return 0;
} else if (!ec_guess_cofactor(group)) {
BN_zero(group->cofactor);
return 0;
}
/*
* Some groups have an order with
* factors of two, which makes the Montgomery setup fail.
* |group->mont_data| will be NULL in this case.
*/
if (BN_is_odd(group->order)) {
return ec_precompute_mont_data(group);
}
BN_MONT_CTX_free(group->mont_data);
group->mont_data = NULL;
return 1;
}
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
{
return group->generator;
}
BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
{
return group->mont_data;
}
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
{
if (group->order == NULL)
return 0;
if (!BN_copy(order, group->order))
return 0;
return !BN_is_zero(order);
}
const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
{
return group->order;
}
int EC_GROUP_order_bits(const EC_GROUP *group)
{
return group->meth->group_order_bits(group);
}
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
BN_CTX *ctx)
{
if (group->cofactor == NULL)
return 0;
if (!BN_copy(cofactor, group->cofactor))
return 0;
return !BN_is_zero(group->cofactor);
}
const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
{
return group->cofactor;
}
void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
{
group->curve_name = nid;
group->asn1_flag =
(nid != NID_undef)
? OPENSSL_EC_NAMED_CURVE
: OPENSSL_EC_EXPLICIT_CURVE;
}
int EC_GROUP_get_curve_name(const EC_GROUP *group)
{
return group->curve_name;
}
const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group)
{
return group->field;
}
int EC_GROUP_get_field_type(const EC_GROUP *group)
{
return group->meth->field_type;
}
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
{
group->asn1_flag = flag;
}
int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
{
return group->asn1_flag;
}
void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
point_conversion_form_t form)
{
group->asn1_form = form;
}
point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
*group)
{
return group->asn1_form;
}
size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
{
OPENSSL_free(group->seed);
group->seed = NULL;
group->seed_len = 0;
if (!len || !p)
return 1;
if ((group->seed = OPENSSL_malloc(len)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(group->seed, p, len);
group->seed_len = len;
return len;
}
unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
{
return group->seed;
}
size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
{
return group->seed_len;
}
int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
if (group->meth->group_set_curve == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_set_curve(group, p, a, b, ctx);
}
int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
BN_CTX *ctx)
{
if (group->meth->group_get_curve == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_get_curve(group, p, a, b, ctx);
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
return EC_GROUP_set_curve(group, p, a, b, ctx);
}
int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *ctx)
{
return EC_GROUP_get_curve(group, p, a, b, ctx);
}
# ifndef OPENSSL_NO_EC2M
int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
return EC_GROUP_set_curve(group, p, a, b, ctx);
}
int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *ctx)
{
return EC_GROUP_get_curve(group, p, a, b, ctx);
}
# endif
#endif
int EC_GROUP_get_degree(const EC_GROUP *group)
{
if (group->meth->group_get_degree == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_get_degree(group);
}
int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
{
if (group->meth->group_check_discriminant == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_check_discriminant(group, ctx);
}
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
{
int r = 0;
BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
#ifndef FIPS_MODULE
BN_CTX *ctx_new = NULL;
#endif
/* compare the field types */
if (EC_GROUP_get_field_type(a) != EC_GROUP_get_field_type(b))
return 1;
/* compare the curve name (if present in both) */
if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
return 1;
if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
return 0;
#ifndef FIPS_MODULE
if (ctx == NULL)
ctx_new = ctx = BN_CTX_new();
#endif
if (ctx == NULL)
return -1;
BN_CTX_start(ctx);
a1 = BN_CTX_get(ctx);
a2 = BN_CTX_get(ctx);
a3 = BN_CTX_get(ctx);
b1 = BN_CTX_get(ctx);
b2 = BN_CTX_get(ctx);
b3 = BN_CTX_get(ctx);
if (b3 == NULL) {
BN_CTX_end(ctx);
#ifndef FIPS_MODULE
BN_CTX_free(ctx_new);
#endif
return -1;
}
/*
* XXX This approach assumes that the external representation of curves
* over the same field type is the same.
*/
if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
!b->meth->group_get_curve(b, b1, b2, b3, ctx))
r = 1;
/* return 1 if the curve parameters are different */
if (r || BN_cmp(a1, b1) != 0 || BN_cmp(a2, b2) != 0 || BN_cmp(a3, b3) != 0)
r = 1;
/* XXX EC_POINT_cmp() assumes that the methods are equal */
/* return 1 if the generators are different */
if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
EC_GROUP_get0_generator(b), ctx) != 0)
r = 1;
if (!r) {
const BIGNUM *ao, *bo, *ac, *bc;
/* compare the orders */
ao = EC_GROUP_get0_order(a);
bo = EC_GROUP_get0_order(b);
if (ao == NULL || bo == NULL) {
/* return an error if either order is NULL */
r = -1;
goto end;
}
if (BN_cmp(ao, bo) != 0) {
/* return 1 if orders are different */
r = 1;
goto end;
}
/*
* It gets here if the curve parameters and generator matched.
* Now check the optional cofactors (if both are present).
*/
ac = EC_GROUP_get0_cofactor(a);
bc = EC_GROUP_get0_cofactor(b);
/* Returns 1 (mismatch) if both cofactors are specified and different */
if (!BN_is_zero(ac) && !BN_is_zero(bc) && BN_cmp(ac, bc) != 0)
r = 1;
/* Returns 0 if the parameters matched */
}
end:
BN_CTX_end(ctx);
#ifndef FIPS_MODULE
BN_CTX_free(ctx_new);
#endif
return r;
}
/* functions for EC_POINT objects */
EC_POINT *EC_POINT_new(const EC_GROUP *group)
{
EC_POINT *ret;
if (group == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (group->meth->point_init == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->meth = group->meth;
ret->curve_name = group->curve_name;
if (!ret->meth->point_init(ret)) {
OPENSSL_free(ret);
return NULL;
}
return ret;
}
void EC_POINT_free(EC_POINT *point)
{
if (point == NULL)
return;
if (point->meth->point_finish != 0)
point->meth->point_finish(point);
OPENSSL_free(point);
}
void EC_POINT_clear_free(EC_POINT *point)
{
if (point == NULL)
return;
if (point->meth->point_clear_finish != 0)
point->meth->point_clear_finish(point);
else if (point->meth->point_finish != 0)
point->meth->point_finish(point);
OPENSSL_clear_free(point, sizeof(*point));
}
int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
{
if (dest->meth->point_copy == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (dest->meth != src->meth
|| (dest->curve_name != src->curve_name
&& dest->curve_name != 0
&& src->curve_name != 0)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (dest == src)
return 1;
return dest->meth->point_copy(dest, src);
}
EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
{
EC_POINT *t;
int r;
if (a == NULL)
return NULL;
t = EC_POINT_new(group);
if (t == NULL)
return NULL;
r = EC_POINT_copy(t, a);
if (!r) {
EC_POINT_free(t);
return NULL;
}
return t;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
{
return point->meth;
}
#endif
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
{
if (group->meth->point_set_to_infinity == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (group->meth != point->meth) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->point_set_to_infinity(group, point);
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, const BIGNUM *z,
BN_CTX *ctx)
{
if (group->meth->field_type != NID_X9_62_prime_field) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point,
x, y, z, ctx);
}
int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x,
BIGNUM *y, BIGNUM *z,
BN_CTX *ctx)
{
if (group->meth->field_type != NID_X9_62_prime_field) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(group, point,
x, y, z, ctx);
}
#endif
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx)
{
if (group->meth->point_set_affine_coordinates == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
return 0;
if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, BN_CTX *ctx)
{
return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
}
# ifndef OPENSSL_NO_EC2M
int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, BN_CTX *ctx)
{
return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
}
# endif
#endif
int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x, BIGNUM *y,
BN_CTX *ctx)
{
if (group->meth->point_get_affine_coordinates == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (EC_POINT_is_at_infinity(group, point)) {
ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
return 0;
}
return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x,
BIGNUM *y, BN_CTX *ctx)
{
return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
}
# ifndef OPENSSL_NO_EC2M
int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x,
BIGNUM *y, BN_CTX *ctx)
{
return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
}
# endif
#endif
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
if (group->meth->add == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)
|| !ec_point_is_compat(b, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->add(group, r, a, b, ctx);
}
int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
BN_CTX *ctx)
{
if (group->meth->dbl == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->dbl(group, r, a, ctx);
}
int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
{
if (group->meth->invert == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(a, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->invert(group, a, ctx);
}
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
{
if (group->meth->is_at_infinity == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->is_at_infinity(group, point);
}
/*
* Check whether an EC_POINT is on the curve or not. Note that the return
* value for this function should NOT be treated as a boolean. Return values:
* 1: The point is on the curve
* 0: The point is not on the curve
* -1: An error occurred
*/
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BN_CTX *ctx)
{
if (group->meth->is_on_curve == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->is_on_curve(group, point, ctx);
}
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
BN_CTX *ctx)
{
if (group->meth->point_cmp == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return -1;
}
if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return -1;
}
return group->meth->point_cmp(group, a, b, ctx);
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
{
if (group->meth->make_affine == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->make_affine(group, point, ctx);
}
int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
EC_POINT *points[], BN_CTX *ctx)
{
size_t i;
if (group->meth->points_make_affine == 0) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
for (i = 0; i < num; i++) {
if (!ec_point_is_compat(points[i], group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
}
return group->meth->points_make_affine(group, num, points, ctx);
}
#endif
/*
* Functions for point multiplication. If group->meth->mul is 0, we use the
* wNAF-based implementations in ec_mult.c; otherwise we dispatch through
* methods.
*/
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t num, const EC_POINT *points[],
const BIGNUM *scalars[], BN_CTX *ctx)
{
int ret = 0;
size_t i = 0;
#ifndef FIPS_MODULE
BN_CTX *new_ctx = NULL;
#endif
if (!ec_point_is_compat(r, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (scalar == NULL && num == 0)
return EC_POINT_set_to_infinity(group, r);
for (i = 0; i < num; i++) {
if (!ec_point_is_compat(points[i], group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
}
#ifndef FIPS_MODULE
if (ctx == NULL)
ctx = new_ctx = BN_CTX_secure_new();
#endif
if (ctx == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
return 0;
}
if (group->meth->mul != NULL)
ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
else
/* use default */
ret = ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
#endif
return ret;
}
#endif
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
{
int ret = 0;
size_t num;
#ifndef FIPS_MODULE
BN_CTX *new_ctx = NULL;
#endif
if (!ec_point_is_compat(r, group)
|| (point != NULL && !ec_point_is_compat(point, group))) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (g_scalar == NULL && p_scalar == NULL)
return EC_POINT_set_to_infinity(group, r);
#ifndef FIPS_MODULE
if (ctx == NULL)
ctx = new_ctx = BN_CTX_secure_new();
#endif
if (ctx == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
return 0;
}
num = (point != NULL && p_scalar != NULL) ? 1 : 0;
if (group->meth->mul != NULL)
ret = group->meth->mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
else
/* use default */
ret = ossl_ec_wNAF_mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
#endif
return ret;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
if (group->meth->mul == 0)
/* use default */
return ossl_ec_wNAF_precompute_mult(group, ctx);
if (group->meth->precompute_mult != 0)
return group->meth->precompute_mult(group, ctx);
else
return 1; /* nothing to do, so report success */
}
int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
{
if (group->meth->mul == 0)
/* use default */
return ossl_ec_wNAF_have_precompute_mult(group);
if (group->meth->have_precompute_mult != 0)
return group->meth->have_precompute_mult(group);
else
return 0; /* cannot tell whether precomputation has
* been performed */
}
#endif
/*
* ec_precompute_mont_data sets |group->mont_data| from |group->order| and
* returns one on success. On error it returns zero.
*/
static int ec_precompute_mont_data(EC_GROUP *group)
{
BN_CTX *ctx = BN_CTX_new_ex(group->libctx);
int ret = 0;
BN_MONT_CTX_free(group->mont_data);
group->mont_data = NULL;
if (ctx == NULL)
goto err;
group->mont_data = BN_MONT_CTX_new();
if (group->mont_data == NULL)
goto err;
if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
BN_MONT_CTX_free(group->mont_data);
group->mont_data = NULL;
goto err;
}
ret = 1;
err:
BN_CTX_free(ctx);
return ret;
}
#ifndef FIPS_MODULE
int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
{
return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
}
void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
{
return CRYPTO_get_ex_data(&key->ex_data, idx);
}
#endif
int ossl_ec_group_simple_order_bits(const EC_GROUP *group)
{
if (group->order == NULL)
return 0;
return BN_num_bits(group->order);
}
static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *x, BN_CTX *ctx)
{
BIGNUM *e = NULL;
int ret = 0;
#ifndef FIPS_MODULE
BN_CTX *new_ctx = NULL;
#endif
if (group->mont_data == NULL)
return 0;
#ifndef FIPS_MODULE
if (ctx == NULL)
ctx = new_ctx = BN_CTX_secure_new();
#endif
if (ctx == NULL)
return 0;
BN_CTX_start(ctx);
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
/*-
* We want inverse in constant time, therefore we utilize the fact
* order must be prime and use Fermats Little Theorem instead.
*/
if (!BN_set_word(e, 2))
goto err;
if (!BN_sub(e, group->order, e))
goto err;
/*-
- * Exponent e is public.
- * No need for scatter-gather or BN_FLG_CONSTTIME.
+ * Although the exponent is public we want the result to be
+ * fixed top.
*/
- if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
+ if (!bn_mod_exp_mont_fixed_top(r, x, e, group->order, ctx, group->mont_data))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
#endif
return ret;
}
/*-
* Default behavior, if group->meth->field_inverse_mod_ord is NULL:
* - When group->order is even, this function returns an error.
* - When group->order is otherwise composite, the correctness
* of the output is not guaranteed.
* - When x is outside the range [1, group->order), the correctness
* of the output is not guaranteed.
* - Otherwise, this function returns the multiplicative inverse in the
* range [1, group->order).
*
* EC_METHODs must implement their own field_inverse_mod_ord for
* other functionality.
*/
int ossl_ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
const BIGNUM *x, BN_CTX *ctx)
{
if (group->meth->field_inverse_mod_ord != NULL)
return group->meth->field_inverse_mod_ord(group, res, x, ctx);
else
return ec_field_inverse_mod_ord(group, res, x, ctx);
}
/*-
* Coordinate blinding for EC_POINT.
*
* The underlying EC_METHOD can optionally implement this function:
* underlying implementations should return 0 on errors, or 1 on
* success.
*
* This wrapper returns 1 in case the underlying EC_METHOD does not
* support coordinate blinding.
*/
int ossl_ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
BN_CTX *ctx)
{
if (group->meth->blind_coordinates == NULL)
return 1; /* ignore if not implemented */
return group->meth->blind_coordinates(group, p, ctx);
}
int EC_GROUP_get_basis_type(const EC_GROUP *group)
{
int i;
if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field)
/* everything else is currently not supported */
return 0;
/* Find the last non-zero element of group->poly[] */
for (i = 0;
i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0;
i++)
continue;
if (i == 4)
return NID_X9_62_ppBasis;
else if (i == 2)
return NID_X9_62_tpBasis;
else
/* everything else is currently not supported */
return 0;
}
#ifndef OPENSSL_NO_EC2M
int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
{
if (group == NULL)
return 0;
if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field
|| !((group->poly[0] != 0) && (group->poly[1] != 0)
&& (group->poly[2] == 0))) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (k)
*k = group->poly[1];
return 1;
}
int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
unsigned int *k2, unsigned int *k3)
{
if (group == NULL)
return 0;
if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field
|| !((group->poly[0] != 0) && (group->poly[1] != 0)
&& (group->poly[2] != 0) && (group->poly[3] != 0)
&& (group->poly[4] == 0))) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (k1)
*k1 = group->poly[3];
if (k2)
*k2 = group->poly[2];
if (k3)
*k3 = group->poly[1];
return 1;
}
#endif
#ifndef FIPS_MODULE
/*
* Check if the explicit parameters group matches any built-in curves.
*
* We create a copy of the group just built, so that we can remove optional
* fields for the lookup: we do this to avoid the possibility that one of
* the optional parameters is used to force the library into using a less
* performant and less secure EC_METHOD instead of the specialized one.
* In any case, `seed` is not really used in any computation, while a
* cofactor different from the one in the built-in table is just
* mathematically wrong anyway and should not be used.
*/
static EC_GROUP *ec_group_explicit_to_named(const EC_GROUP *group,
OSSL_LIB_CTX *libctx,
const char *propq,
BN_CTX *ctx)
{
EC_GROUP *ret_group = NULL, *dup = NULL;
int curve_name_nid;
const EC_POINT *point = EC_GROUP_get0_generator(group);
const BIGNUM *order = EC_GROUP_get0_order(group);
int no_seed = (EC_GROUP_get0_seed(group) == NULL);
if ((dup = EC_GROUP_dup(group)) == NULL
|| EC_GROUP_set_seed(dup, NULL, 0) != 1
|| !EC_GROUP_set_generator(dup, point, order, NULL))
goto err;
if ((curve_name_nid = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) {
/*
* The input explicit parameters successfully matched one of the
* built-in curves: often for built-in curves we have specialized
* methods with better performance and hardening.
*
* In this case we replace the `EC_GROUP` created through explicit
* parameters with one created from a named group.
*/
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
/*
* NID_wap_wsg_idm_ecid_wtls12 and NID_secp224r1 are both aliases for
* the same curve, we prefer the SECP nid when matching explicit
* parameters as that is associated with a specialized EC_METHOD.
*/
if (curve_name_nid == NID_wap_wsg_idm_ecid_wtls12)
curve_name_nid = NID_secp224r1;
# endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
ret_group = EC_GROUP_new_by_curve_name_ex(libctx, propq, curve_name_nid);
if (ret_group == NULL)
goto err;
/*
* Set the flag so that EC_GROUPs created from explicit parameters are
* serialized using explicit parameters by default.
*/
EC_GROUP_set_asn1_flag(ret_group, OPENSSL_EC_EXPLICIT_CURVE);
/*
* If the input params do not contain the optional seed field we make
* sure it is not added to the returned group.
*
* The seed field is not really used inside libcrypto anyway, and
* adding it to parsed explicit parameter keys would alter their DER
* encoding output (because of the extra field) which could impact
* applications fingerprinting keys by their DER encoding.
*/
if (no_seed) {
if (EC_GROUP_set_seed(ret_group, NULL, 0) != 1)
goto err;
}
} else {
ret_group = (EC_GROUP *)group;
}
EC_GROUP_free(dup);
return ret_group;
err:
EC_GROUP_free(dup);
EC_GROUP_free(ret_group);
return NULL;
}
#endif /* FIPS_MODULE */
static EC_GROUP *group_new_from_name(const OSSL_PARAM *p,
OSSL_LIB_CTX *libctx, const char *propq)
{
int ok = 0, nid;
const char *curve_name = NULL;
switch (p->data_type) {
case OSSL_PARAM_UTF8_STRING:
/* The OSSL_PARAM functions have no support for this */
curve_name = p->data;
ok = (curve_name != NULL);
break;
case OSSL_PARAM_UTF8_PTR:
ok = OSSL_PARAM_get_utf8_ptr(p, &curve_name);
break;
}
if (ok) {
nid = ossl_ec_curve_name2nid(curve_name);
if (nid == NID_undef) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
return NULL;
} else {
return EC_GROUP_new_by_curve_name_ex(libctx, propq, nid);
}
}
return NULL;
}
/* These parameters can be set directly into an EC_GROUP */
int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[])
{
int encoding_flag = -1, format = -1;
const OSSL_PARAM *p;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
if (p != NULL) {
if (!ossl_ec_pt_format_param2id(p, &format)) {
ECerr(0, EC_R_INVALID_FORM);
return 0;
}
EC_GROUP_set_point_conversion_form(group, format);
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
if (p != NULL) {
if (!ossl_ec_encoding_param2id(p, &encoding_flag)) {
ECerr(0, EC_R_INVALID_FORM);
return 0;
}
EC_GROUP_set_asn1_flag(group, encoding_flag);
}
/* Optional seed */
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
if (p != NULL) {
/* The seed is allowed to be NULL */
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| !EC_GROUP_set_seed(group, p->data, p->data_size)) {
ECerr(0, EC_R_INVALID_SEED);
return 0;
}
}
return 1;
}
EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
OSSL_LIB_CTX *libctx, const char *propq)
{
const OSSL_PARAM *ptmp;
EC_GROUP *group = NULL;
#ifndef FIPS_MODULE
const OSSL_PARAM *pa, *pb;
int ok = 0;
EC_GROUP *named_group = NULL;
BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *cofactor = NULL;
EC_POINT *point = NULL;
int field_bits = 0;
int is_prime_field = 1;
BN_CTX *bnctx = NULL;
const unsigned char *buf = NULL;
int encoding_flag = -1;
#endif
/* This is the simple named group case */
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
if (ptmp != NULL) {
int decoded = 0;
if ((group = group_new_from_name(ptmp, libctx, propq)) == NULL)
return NULL;
if (!ossl_ec_group_set_params(group, params)) {
EC_GROUP_free(group);
return NULL;
}
ptmp = OSSL_PARAM_locate_const(params,
OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS);
if (ptmp != NULL && !OSSL_PARAM_get_int(ptmp, &decoded)) {
ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS);
EC_GROUP_free(group);
return NULL;
}
group->decoded_from_explicit_params = decoded > 0;
return group;
}
#ifdef FIPS_MODULE
ERR_raise(ERR_LIB_EC, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED);
return NULL;
#else
/* If it gets here then we are trying explicit parameters */
bnctx = BN_CTX_new_ex(libctx);
if (bnctx == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
BN_CTX_start(bnctx);
p = BN_CTX_get(bnctx);
a = BN_CTX_get(bnctx);
b = BN_CTX_get(bnctx);
order = BN_CTX_get(bnctx);
if (order == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE);
if (ptmp == NULL || ptmp->data_type != OSSL_PARAM_UTF8_STRING) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
goto err;
}
if (OPENSSL_strcasecmp(ptmp->data, SN_X9_62_prime_field) == 0) {
is_prime_field = 1;
} else if (OPENSSL_strcasecmp(ptmp->data,
SN_X9_62_characteristic_two_field) == 0) {
is_prime_field = 0;
} else {
/* Invalid field */
ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD);
goto err;
}
pa = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A);
if (!OSSL_PARAM_get_BN(pa, &a)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_A);
goto err;
}
pb = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B);
if (!OSSL_PARAM_get_BN(pb, &b)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_B);
goto err;
}
/* extract the prime number or irreducible polynomial */
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P);
if (!OSSL_PARAM_get_BN(ptmp, &p)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_P);
goto err;
}
if (is_prime_field) {
if (BN_is_negative(p) || BN_is_zero(p)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_P);
goto err;
}
field_bits = BN_num_bits(p);
if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
goto err;
}
/* create the EC_GROUP structure */
group = EC_GROUP_new_curve_GFp(p, a, b, bnctx);
} else {
# ifdef OPENSSL_NO_EC2M
ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
goto err;
# else
/* create the EC_GROUP structure */
group = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
if (group != NULL) {
field_bits = EC_GROUP_get_degree(group);
if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
goto err;
}
}
# endif /* OPENSSL_NO_EC2M */
}
if (group == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* Optional seed */
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
if (ptmp != NULL) {
if (ptmp->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_SEED);
goto err;
}
if (!EC_GROUP_set_seed(group, ptmp->data, ptmp->data_size))
goto err;
}
/* generator base point */
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR);
if (ptmp == NULL
|| ptmp->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
goto err;
}
buf = (const unsigned char *)(ptmp->data);
if ((point = EC_POINT_new(group)) == NULL)
goto err;
EC_GROUP_set_point_conversion_form(group,
(point_conversion_form_t)buf[0] & ~0x01);
if (!EC_POINT_oct2point(group, point, buf, ptmp->data_size, bnctx)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
goto err;
}
/* order */
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER);
if (!OSSL_PARAM_get_BN(ptmp, &order)
|| (BN_is_negative(order) || BN_is_zero(order))
|| (BN_num_bits(order) > (int)field_bits + 1)) { /* Hasse bound */
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
/* Optional cofactor */
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR);
if (ptmp != NULL) {
cofactor = BN_CTX_get(bnctx);
if (cofactor == NULL || !OSSL_PARAM_get_BN(ptmp, &cofactor)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_COFACTOR);
goto err;
}
}
/* set the generator, order and cofactor (if present) */
if (!EC_GROUP_set_generator(group, point, order, cofactor)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
goto err;
}
named_group = ec_group_explicit_to_named(group, libctx, propq, bnctx);
if (named_group == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION);
goto err;
}
if (named_group == group) {
/*
* If we did not find a named group then the encoding should be explicit
* if it was specified
*/
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
if (ptmp != NULL
&& !ossl_ec_encoding_param2id(ptmp, &encoding_flag)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
if (encoding_flag == OPENSSL_EC_NAMED_CURVE) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
} else {
EC_GROUP_free(group);
group = named_group;
}
/* We've imported the group from explicit parameters, set it so. */
group->decoded_from_explicit_params = 1;
ok = 1;
err:
if (!ok) {
EC_GROUP_free(group);
group = NULL;
}
EC_POINT_free(point);
BN_CTX_end(bnctx);
BN_CTX_free(bnctx);
return group;
#endif /* FIPS_MODULE */
}
diff --git a/crypto/openssl/crypto/ec/ec_oct.c b/crypto/openssl/crypto/ec/ec_oct.c
index 790a0b290771..2b77e9738883 100644
--- a/crypto/openssl/crypto/ec/ec_oct.c
+++ b/crypto/openssl/crypto/ec/ec_oct.c
@@ -1,154 +1,158 @@
/*
* Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* ECDSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <string.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
#include "ec_local.h"
int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
const BIGNUM *x, int y_bit, BN_CTX *ctx)
{
if (group->meth->point_set_compressed_coordinates == NULL
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
if (group->meth->field_type == NID_X9_62_prime_field)
return ossl_ec_GFp_simple_set_compressed_coordinates(group, point, x,
y_bit, ctx);
else
#ifdef OPENSSL_NO_EC2M
{
ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
return 0;
}
#else
return ossl_ec_GF2m_simple_set_compressed_coordinates(group, point,
x, y_bit, ctx);
#endif
}
return group->meth->point_set_compressed_coordinates(group, point, x,
y_bit, ctx);
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
int y_bit, BN_CTX *ctx)
{
return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx);
}
# ifndef OPENSSL_NO_EC2M
int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
int y_bit, BN_CTX *ctx)
{
return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx);
}
# endif
#endif
size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form, unsigned char *buf,
size_t len, BN_CTX *ctx)
{
+ if (point == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
if (group->meth->point2oct == 0
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
if (group->meth->field_type == NID_X9_62_prime_field)
return ossl_ec_GFp_simple_point2oct(group, point, form, buf, len,
ctx);
else
#ifdef OPENSSL_NO_EC2M
{
ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
return 0;
}
#else
return ossl_ec_GF2m_simple_point2oct(group, point,
form, buf, len, ctx);
#endif
}
return group->meth->point2oct(group, point, form, buf, len, ctx);
}
int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
const unsigned char *buf, size_t len, BN_CTX *ctx)
{
if (group->meth->oct2point == 0
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
if (group->meth->field_type == NID_X9_62_prime_field)
return ossl_ec_GFp_simple_oct2point(group, point, buf, len, ctx);
else
#ifdef OPENSSL_NO_EC2M
{
ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
return 0;
}
#else
return ossl_ec_GF2m_simple_oct2point(group, point, buf, len, ctx);
#endif
}
return group->meth->oct2point(group, point, buf, len, ctx);
}
size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form,
unsigned char **pbuf, BN_CTX *ctx)
{
size_t len;
unsigned char *buf;
len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL);
if (len == 0)
return 0;
if ((buf = OPENSSL_malloc(len)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
len = EC_POINT_point2oct(group, point, form, buf, len, ctx);
if (len == 0) {
OPENSSL_free(buf);
return 0;
}
*pbuf = buf;
return len;
}
diff --git a/crypto/openssl/crypto/encode_decode/encoder_pkey.c b/crypto/openssl/crypto/encode_decode/encoder_pkey.c
index 3a24317cf4d6..39266a95309d 100644
--- a/crypto/openssl/crypto/encode_decode/encoder_pkey.c
+++ b/crypto/openssl/crypto/encode_decode/encoder_pkey.c
@@ -1,379 +1,383 @@
/*
* Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/ui.h>
#include <openssl/params.h>
#include <openssl/encoder.h>
#include <openssl/core_names.h>
#include <openssl/provider.h>
#include <openssl/safestack.h>
#include <openssl/trace.h>
#include "internal/provider.h"
#include "internal/property.h"
#include "crypto/evp.h"
#include "encoder_local.h"
DEFINE_STACK_OF(OSSL_ENCODER)
int OSSL_ENCODER_CTX_set_cipher(OSSL_ENCODER_CTX *ctx,
const char *cipher_name,
const char *propquery)
{
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
params[0] =
OSSL_PARAM_construct_utf8_string(OSSL_ENCODER_PARAM_CIPHER,
(void *)cipher_name, 0);
params[1] =
OSSL_PARAM_construct_utf8_string(OSSL_ENCODER_PARAM_PROPERTIES,
(void *)propquery, 0);
return OSSL_ENCODER_CTX_set_params(ctx, params);
}
int OSSL_ENCODER_CTX_set_passphrase(OSSL_ENCODER_CTX *ctx,
const unsigned char *kstr,
size_t klen)
{
return ossl_pw_set_passphrase(&ctx->pwdata, kstr, klen);
}
int OSSL_ENCODER_CTX_set_passphrase_ui(OSSL_ENCODER_CTX *ctx,
const UI_METHOD *ui_method,
void *ui_data)
{
return ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data);
}
int OSSL_ENCODER_CTX_set_pem_password_cb(OSSL_ENCODER_CTX *ctx,
pem_password_cb *cb, void *cbarg)
{
return ossl_pw_set_pem_password_cb(&ctx->pwdata, cb, cbarg);
}
int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx,
OSSL_PASSPHRASE_CALLBACK *cb,
void *cbarg)
{
return ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, cb, cbarg);
}
/*
* Support for OSSL_ENCODER_CTX_new_for_type:
* finding a suitable encoder
*/
struct collected_encoder_st {
STACK_OF(OPENSSL_CSTRING) *names;
const char *output_structure;
const char *output_type;
const OSSL_PROVIDER *keymgmt_prov;
OSSL_ENCODER_CTX *ctx;
unsigned int flag_find_same_provider:1;
int error_occurred;
};
static void collect_encoder(OSSL_ENCODER *encoder, void *arg)
{
struct collected_encoder_st *data = arg;
size_t i, end_i;
if (data->error_occurred)
return;
data->error_occurred = 1; /* Assume the worst */
if (data->names == NULL)
return;
end_i = sk_OPENSSL_CSTRING_num(data->names);
for (i = 0; i < end_i; i++) {
const char *name = sk_OPENSSL_CSTRING_value(data->names, i);
const OSSL_PROVIDER *prov = OSSL_ENCODER_get0_provider(encoder);
void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
/*
* collect_encoder() is called in two passes, one where the encoders
* from the same provider as the keymgmt are looked up, and one where
* the other encoders are looked up. |data->flag_find_same_provider|
* tells us which pass we're in.
*/
if ((data->keymgmt_prov == prov) != data->flag_find_same_provider)
continue;
if (!OSSL_ENCODER_is_a(encoder, name)
|| (encoder->does_selection != NULL
&& !encoder->does_selection(provctx, data->ctx->selection))
|| (data->keymgmt_prov != prov
&& encoder->import_object == NULL))
continue;
/* Only add each encoder implementation once */
if (OSSL_ENCODER_CTX_add_encoder(data->ctx, encoder))
break;
}
data->error_occurred = 0; /* All is good now */
}
struct collected_names_st {
STACK_OF(OPENSSL_CSTRING) *names;
unsigned int error_occurred:1;
};
static void collect_name(const char *name, void *arg)
{
struct collected_names_st *data = arg;
if (data->error_occurred)
return;
data->error_occurred = 1; /* Assume the worst */
if (sk_OPENSSL_CSTRING_push(data->names, name) <= 0)
return;
data->error_occurred = 0; /* All is good now */
}
/*
* Support for OSSL_ENCODER_to_bio:
* writing callback for the OSSL_PARAM (the implementation doesn't have
* intimate knowledge of the provider side object)
*/
struct construct_data_st {
const EVP_PKEY *pk;
int selection;
OSSL_ENCODER_INSTANCE *encoder_inst;
const void *obj;
void *constructed_obj;
};
static int encoder_import_cb(const OSSL_PARAM params[], void *arg)
{
struct construct_data_st *construct_data = arg;
OSSL_ENCODER_INSTANCE *encoder_inst = construct_data->encoder_inst;
OSSL_ENCODER *encoder = OSSL_ENCODER_INSTANCE_get_encoder(encoder_inst);
void *encoderctx = OSSL_ENCODER_INSTANCE_get_encoder_ctx(encoder_inst);
construct_data->constructed_obj =
encoder->import_object(encoderctx, construct_data->selection, params);
return (construct_data->constructed_obj != NULL);
}
static const void *
encoder_construct_pkey(OSSL_ENCODER_INSTANCE *encoder_inst, void *arg)
{
struct construct_data_st *data = arg;
if (data->obj == NULL) {
OSSL_ENCODER *encoder =
OSSL_ENCODER_INSTANCE_get_encoder(encoder_inst);
const EVP_PKEY *pk = data->pk;
const OSSL_PROVIDER *k_prov = EVP_KEYMGMT_get0_provider(pk->keymgmt);
const OSSL_PROVIDER *e_prov = OSSL_ENCODER_get0_provider(encoder);
if (k_prov != e_prov) {
+ int selection = data->selection;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
data->encoder_inst = encoder_inst;
- if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, data->selection,
+ if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, selection,
&encoder_import_cb, data))
return NULL;
data->obj = data->constructed_obj;
} else {
data->obj = pk->keydata;
}
}
return data->obj;
}
static void encoder_destruct_pkey(void *arg)
{
struct construct_data_st *data = arg;
if (data->encoder_inst != NULL) {
OSSL_ENCODER *encoder =
OSSL_ENCODER_INSTANCE_get_encoder(data->encoder_inst);
encoder->free_object(data->constructed_obj);
}
data->constructed_obj = NULL;
}
/*
* OSSL_ENCODER_CTX_new_for_pkey() returns a ctx with no encoder if
* it couldn't find a suitable encoder. This allows a caller to detect if
* a suitable encoder was found, with OSSL_ENCODER_CTX_get_num_encoder(),
* and to use fallback methods if the result is NULL.
*/
static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx,
const EVP_PKEY *pkey,
int selection,
const char *propquery)
{
struct construct_data_st *data = NULL;
const OSSL_PROVIDER *prov = NULL;
OSSL_LIB_CTX *libctx = NULL;
int ok = 0;
if (!ossl_assert(ctx != NULL) || !ossl_assert(pkey != NULL)) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (evp_pkey_is_provided(pkey)) {
prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt);
libctx = ossl_provider_libctx(prov);
}
if (pkey->keymgmt != NULL) {
struct collected_encoder_st encoder_data;
struct collected_names_st keymgmt_data;
if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* Select the first encoder implementations in two steps.
* First, collect the keymgmt names, then the encoders that match.
*/
keymgmt_data.names = sk_OPENSSL_CSTRING_new_null();
if (keymgmt_data.names == NULL) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
goto err;
}
keymgmt_data.error_occurred = 0;
EVP_KEYMGMT_names_do_all(pkey->keymgmt, collect_name, &keymgmt_data);
if (keymgmt_data.error_occurred) {
sk_OPENSSL_CSTRING_free(keymgmt_data.names);
goto err;
}
encoder_data.names = keymgmt_data.names;
encoder_data.output_type = ctx->output_type;
encoder_data.output_structure = ctx->output_structure;
encoder_data.error_occurred = 0;
encoder_data.keymgmt_prov = prov;
encoder_data.ctx = ctx;
/*
* Place the encoders with the a different provider as the keymgmt
* last (the chain is processed in reverse order)
*/
encoder_data.flag_find_same_provider = 0;
OSSL_ENCODER_do_all_provided(libctx, collect_encoder, &encoder_data);
/*
* Place the encoders with the same provider as the keymgmt first
* (the chain is processed in reverse order)
*/
encoder_data.flag_find_same_provider = 1;
OSSL_ENCODER_do_all_provided(libctx, collect_encoder, &encoder_data);
sk_OPENSSL_CSTRING_free(keymgmt_data.names);
if (encoder_data.error_occurred) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (data != NULL && OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0) {
if (!OSSL_ENCODER_CTX_set_construct(ctx, encoder_construct_pkey)
|| !OSSL_ENCODER_CTX_set_construct_data(ctx, data)
|| !OSSL_ENCODER_CTX_set_cleanup(ctx, encoder_destruct_pkey))
goto err;
data->pk = pkey;
data->selection = selection;
data = NULL; /* Avoid it being freed */
}
ok = 1;
err:
if (data != NULL) {
OSSL_ENCODER_CTX_set_construct_data(ctx, NULL);
OPENSSL_free(data);
}
return ok;
}
OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_for_pkey(const EVP_PKEY *pkey,
int selection,
const char *output_type,
const char *output_struct,
const char *propquery)
{
OSSL_ENCODER_CTX *ctx = NULL;
OSSL_LIB_CTX *libctx = NULL;
if (pkey == NULL) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (!evp_pkey_is_assigned(pkey)) {
ERR_raise_data(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT,
"The passed EVP_PKEY must be assigned a key");
return NULL;
}
if ((ctx = OSSL_ENCODER_CTX_new()) == NULL) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (evp_pkey_is_provided(pkey)) {
const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt);
libctx = ossl_provider_libctx(prov);
}
OSSL_TRACE_BEGIN(ENCODER) {
BIO_printf(trc_out,
"(ctx %p) Looking for %s encoders with selection %d\n",
(void *)ctx, EVP_PKEY_get0_type_name(pkey), selection);
BIO_printf(trc_out, " output type: %s, output structure: %s\n",
output_type, output_struct);
} OSSL_TRACE_END(ENCODER);
if (OSSL_ENCODER_CTX_set_output_type(ctx, output_type)
&& (output_struct == NULL
|| OSSL_ENCODER_CTX_set_output_structure(ctx, output_struct))
&& OSSL_ENCODER_CTX_set_selection(ctx, selection)
&& ossl_encoder_ctx_setup_for_pkey(ctx, pkey, selection, propquery)
&& OSSL_ENCODER_CTX_add_extra(ctx, libctx, propquery)) {
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
int save_parameters = pkey->save_parameters;
params[0] = OSSL_PARAM_construct_int(OSSL_ENCODER_PARAM_SAVE_PARAMETERS,
&save_parameters);
/* ignoring error as this is only auxiliary parameter */
(void)OSSL_ENCODER_CTX_set_params(ctx, params);
OSSL_TRACE_BEGIN(ENCODER) {
BIO_printf(trc_out, "(ctx %p) Got %d encoders\n",
(void *)ctx, OSSL_ENCODER_CTX_get_num_encoders(ctx));
} OSSL_TRACE_END(ENCODER);
return ctx;
}
OSSL_ENCODER_CTX_free(ctx);
return NULL;
}
diff --git a/crypto/openssl/crypto/err/openssl.txt b/crypto/openssl/crypto/err/openssl.txt
index 36fe318baf7d..756fafdfa24a 100644
--- a/crypto/openssl/crypto/err/openssl.txt
+++ b/crypto/openssl/crypto/err/openssl.txt
@@ -1,1715 +1,1717 @@
-# Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
#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_BAD_TEMPLATE:230:bad template
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_LENGTH_TOO_LONG:231:length too long
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_DIGEST:229:unknown digest
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_CONNECT_TIMEOUT:147:connect timeout
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_TRANSFER_ERROR:104:transfer error
BIO_R_TRANSFER_TIMEOUT:105:transfer timeout
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_PRIME_CANDIDATE:121:no prime candidate
BN_R_NO_SOLUTION:116:no solution
BN_R_NO_SUITABLE_DIGEST:120:no suitable digest
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
CMP_R_ALGORITHM_NOT_SUPPORTED:139:algorithm not supported
CMP_R_BAD_CHECKAFTER_IN_POLLREP:167:bad checkafter in pollrep
CMP_R_BAD_REQUEST_ID:108:bad request id
CMP_R_CERTHASH_UNMATCHED:156:certhash unmatched
CMP_R_CERTID_NOT_FOUND:109:certid not found
CMP_R_CERTIFICATE_NOT_ACCEPTED:169:certificate not accepted
CMP_R_CERTIFICATE_NOT_FOUND:112:certificate not found
CMP_R_CERTREQMSG_NOT_FOUND:157:certreqmsg not found
CMP_R_CERTRESPONSE_NOT_FOUND:113:certresponse not found
CMP_R_CERT_AND_KEY_DO_NOT_MATCH:114:cert and key do not match
CMP_R_CHECKAFTER_OUT_OF_RANGE:181:checkafter out of range
CMP_R_ENCOUNTERED_KEYUPDATEWARNING:176:encountered keyupdatewarning
CMP_R_ENCOUNTERED_WAITING:162:encountered waiting
CMP_R_ERROR_CALCULATING_PROTECTION:115:error calculating protection
CMP_R_ERROR_CREATING_CERTCONF:116:error creating certconf
CMP_R_ERROR_CREATING_CERTREP:117:error creating certrep
CMP_R_ERROR_CREATING_CERTREQ:163:error creating certreq
CMP_R_ERROR_CREATING_ERROR:118:error creating error
CMP_R_ERROR_CREATING_GENM:119:error creating genm
CMP_R_ERROR_CREATING_GENP:120:error creating genp
CMP_R_ERROR_CREATING_PKICONF:122:error creating pkiconf
CMP_R_ERROR_CREATING_POLLREP:123:error creating pollrep
CMP_R_ERROR_CREATING_POLLREQ:124:error creating pollreq
CMP_R_ERROR_CREATING_RP:125:error creating rp
CMP_R_ERROR_CREATING_RR:126:error creating rr
CMP_R_ERROR_PARSING_PKISTATUS:107:error parsing pkistatus
CMP_R_ERROR_PROCESSING_MESSAGE:158:error processing message
CMP_R_ERROR_PROTECTING_MESSAGE:127:error protecting message
CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash
CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf
CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
CMP_R_ERROR_VALIDATING_SIGNATURE:171:error validating signature
CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain
CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
CMP_R_FAIL_INFO_OUT_OF_RANGE:129:fail info out of range
CMP_R_INVALID_ARGS:100:invalid args
CMP_R_INVALID_OPTION:174:invalid option
CMP_R_MISSING_CERTID:165:missing certid
CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION:130:\
missing key input for creating protection
CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE:142:missing key usage digitalsignature
CMP_R_MISSING_P10CSR:121:missing p10csr
CMP_R_MISSING_PBM_SECRET:166:missing pbm secret
CMP_R_MISSING_PRIVATE_KEY:131:missing private key
CMP_R_MISSING_PRIVATE_KEY_FOR_POPO:190:missing private key for popo
CMP_R_MISSING_PROTECTION:143:missing protection
CMP_R_MISSING_PUBLIC_KEY:183:missing public key
CMP_R_MISSING_REFERENCE_CERT:168:missing reference cert
CMP_R_MISSING_SECRET:178:missing secret
CMP_R_MISSING_SENDER_IDENTIFICATION:111:missing sender identification
CMP_R_MISSING_TRUST_ANCHOR:179:missing trust anchor
CMP_R_MISSING_TRUST_STORE:144:missing trust store
CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED:161:multiple requests not supported
CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED:170:multiple responses not supported
CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources
CMP_R_NO_STDIO:194:no stdio
CMP_R_NO_SUITABLE_SENDER_CERT:145:no suitable sender cert
CMP_R_NULL_ARGUMENT:103:null argument
CMP_R_PKIBODY_ERROR:146:pkibody error
CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found
CMP_R_POLLING_FAILED:172:polling failed
CMP_R_POTENTIALLY_INVALID_CERTIFICATE:147:potentially invalid certificate
CMP_R_RECEIVED_ERROR:180:received error
CMP_R_RECIPNONCE_UNMATCHED:148:recipnonce unmatched
CMP_R_REQUEST_NOT_ACCEPTED:149:request not accepted
CMP_R_REQUEST_REJECTED_BY_SERVER:182:request rejected by server
CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED:150:\
sender generalname type not supported
CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg
CMP_R_TOTAL_TIMEOUT:184:total timeout
CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
CMP_R_TRANSFER_ERROR:159:transfer error
CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
CMP_R_UNEXPECTED_PVNO:153:unexpected pvno
CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus
CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\
unsupported protection alg dhbasedmac
CMP_R_VALUE_TOO_LARGE:175:value too large
CMP_R_VALUE_TOO_SMALL:177:value too small
CMP_R_WRONG_ALGORITHM_OID:138:wrong algorithm oid
CMP_R_WRONG_CERTID:189:wrong certid
CMP_R_WRONG_CERTID_IN_RP:187:wrong certid in rp
CMP_R_WRONG_PBM_VALUE:155:wrong pbm value
CMP_R_WRONG_RP_COMPONENT_COUNT:188:wrong rp component count
CMP_R_WRONG_SERIAL_IN_RP:173:wrong serial in rp
CMS_R_ADD_SIGNER_ERROR:99:add signer error
CMS_R_ATTRIBUTE_ERROR:161:attribute 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_AEAD_SET_TAG_ERROR:184:cipher aead set tag error
CMS_R_CIPHER_GET_TAG:185:cipher get tag
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_DECODE_ERROR:187:decode error
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_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT:196:\
+ error unsupported static key agreement
CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR:183:ess signing certid mismatch error
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_INVALID_LABEL:190:invalid label
CMS_R_INVALID_OAEP_PARAMETERS:191:invalid oaep parameters
CMS_R_KDF_PARAMETER_ERROR:186:kdf parameter error
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_PEER_KEY_ERROR:188:peer key error
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_SHARED_INFO_ERROR:189:shared info 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_ENCRYPTION_ALGORITHM:194:\
unsupported content encryption algorithm
CMS_R_UNSUPPORTED_CONTENT_TYPE:152:unsupported content type
CMS_R_UNSUPPORTED_ENCRYPTION_TYPE:192:unsupported encryption type
CMS_R_UNSUPPORTED_KEK_ALGORITHM:153:unsupported kek algorithm
CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM:179:\
unsupported key encryption algorithm
CMS_R_UNSUPPORTED_LABEL_SOURCE:193:unsupported label source
CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE:155:unsupported recipientinfo type
CMS_R_UNSUPPORTED_RECIPIENT_TYPE:154:unsupported recipient type
CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM:195:unsupported signature algorithm
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_INVALID_PRAGMA:122:invalid pragma
CONF_R_LIST_CANNOT_BE_NULL:115:list cannot be null
CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION:123:\
mandatory braces in variable expansion
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_OPENSSL_CONF_REFERENCES_MISSING_SECTION:124:\
openssl conf references missing section
CONF_R_RECURSIVE_DIRECTORY_INCLUDE:111:recursive directory include
CONF_R_RECURSIVE_SECTION_REFERENCE:126:recursive section reference
CONF_R_RELATIVE_PATH:125:relative path
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
CRMF_R_BAD_PBM_ITERATIONCOUNT:100:bad pbm iterationcount
CRMF_R_CRMFERROR:102:crmferror
CRMF_R_ERROR:103:error
CRMF_R_ERROR_DECODING_CERTIFICATE:104:error decoding certificate
CRMF_R_ERROR_DECRYPTING_CERTIFICATE:105:error decrypting certificate
CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY:106:error decrypting symmetric key
CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random
CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100
CRMF_R_MALFORMED_IV:101:malformed iv
CRMF_R_NULL_ARGUMENT:109:null argument
CRMF_R_POPOSKINPUT_NOT_SUPPORTED:113:poposkinput not supported
CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY:117:popo inconsistent public key
CRMF_R_POPO_MISSING:121:popo missing
CRMF_R_POPO_MISSING_PUBLIC_KEY:118:popo missing public key
CRMF_R_POPO_MISSING_SUBJECT:119:popo missing subject
CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED:120:popo raverified not accepted
CRMF_R_SETTING_MAC_ALGOR_FAILURE:110:setting mac algor failure
CRMF_R_SETTING_OWF_ALGOR_FAILURE:111:setting owf algor failure
CRMF_R_UNSUPPORTED_ALGORITHM:112:unsupported algorithm
CRMF_R_UNSUPPORTED_CIPHER:114:unsupported cipher
CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO:115:\
unsupported method for creating popo
CRMF_R_UNSUPPORTED_POPO_METHOD:116:unsupported popo method
CRYPTO_R_BAD_ALGORITHM_NAME:117:bad algorithm name
CRYPTO_R_CONFLICTING_NAMES:118:conflicting names
CRYPTO_R_HEX_STRING_TOO_SHORT:121:hex string too short
CRYPTO_R_ILLEGAL_HEX_DIGIT:102:illegal hex digit
CRYPTO_R_INSUFFICIENT_DATA_SPACE:106:insufficient data space
CRYPTO_R_INSUFFICIENT_PARAM_SIZE:107:insufficient param size
CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE:108:insufficient secure data space
CRYPTO_R_INVALID_NEGATIVE_VALUE:122:invalid negative value
CRYPTO_R_INVALID_NULL_ARGUMENT:109:invalid null argument
CRYPTO_R_INVALID_OSSL_PARAM_TYPE:110:invalid ossl param type
CRYPTO_R_ODD_NUMBER_OF_DIGITS:103:odd number of digits
CRYPTO_R_PROVIDER_ALREADY_EXISTS:104:provider already exists
CRYPTO_R_PROVIDER_SECTION_ERROR:105:provider section error
CRYPTO_R_RANDOM_SECTION_ERROR:119:random section error
CRYPTO_R_SECURE_MALLOC_FAILURE:111:secure malloc failure
CRYPTO_R_STRING_TOO_LONG:112:string too long
CRYPTO_R_TOO_MANY_BYTES:113:too many bytes
CRYPTO_R_TOO_MANY_RECORDS:114:too many records
CRYPTO_R_TOO_SMALL_BUFFER:116:too small buffer
CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION:120:unknown name in random section
CRYPTO_R_ZERO_LENGTH_NUMBER:115:zero length number
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_FFC_PARAMETERS:127:bad ffc parameters
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_INVALID_SECRET:128:invalid secret
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_MODULUS_TOO_SMALL:126:modulus too small
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_Q_TOO_LARGE:130:q too large
DH_R_SHARED_INFO_ERROR:113:shared info error
DH_R_UNABLE_TO_CHECK_GENERATOR:121:unable to check generator
DSA_R_BAD_FFC_PARAMETERS:114:bad ffc parameters
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_MISSING_PRIVATE_KEY:111:missing private key
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_P_NOT_PRIME:115:p not prime
DSA_R_Q_NOT_PRIME:113:q not prime
DSA_R_SEED_LEN_SMALL:110:seed_len is less than the length of q
DSA_R_TOO_MANY_RETRIES:116:too many retries
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_CANNOT_INVERT:165:cannot invert
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_ECDSA:170:curve does not support ecdsa
EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING:159:curve does not support signing
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_EXPLICIT_PARAMS_NOT_SUPPORTED:127:explicit params not supported
EC_R_FAILED_MAKING_PUBLIC_KEY:166:failed making public key
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_A:168:invalid a
EC_R_INVALID_ARGUMENT:112:invalid argument
EC_R_INVALID_B:169:invalid b
EC_R_INVALID_COFACTOR:171:invalid cofactor
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_GENERATOR:173:invalid generator
EC_R_INVALID_GROUP_ORDER:122:invalid group order
EC_R_INVALID_KEY:116:invalid key
EC_R_INVALID_LENGTH:117:invalid length
EC_R_INVALID_NAMED_GROUP_CONVERSION:174:invalid named group conversion
EC_R_INVALID_OUTPUT_LENGTH:161:invalid output length
EC_R_INVALID_P:172:invalid p
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_SEED:175:invalid seed
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_OID:167:missing OID
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_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_TOO_MANY_RETRIES:176:too many retries
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
ESS_R_EMPTY_ESS_CERT_ID_LIST:107:empty ess cert id list
ESS_R_ESS_CERT_DIGEST_ERROR:103:ess cert digest error
ESS_R_ESS_CERT_ID_NOT_FOUND:104:ess cert id not found
ESS_R_ESS_CERT_ID_WRONG_ORDER:105:ess cert id wrong order
ESS_R_ESS_DIGEST_ALG_UNKNOWN:106:ess digest alg unknown
ESS_R_ESS_SIGNING_CERTIFICATE_ERROR:102:ess signing certificate error
ESS_R_ESS_SIGNING_CERT_ADD_ERROR:100:ess signing cert add error
ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR:101:ess signing cert v2 add error
ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE:108:\
missing signing certificate attribute
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_ALGORITHM_NAME:200:bad algorithm name
EVP_R_BAD_DECRYPT:100:bad decrypt
EVP_R_BAD_KEY_LENGTH:195:bad key length
EVP_R_BUFFER_TOO_SMALL:155:buffer too small
EVP_R_CACHE_CONSTANTS_FAILED:225:cache constants failed
EVP_R_CAMELLIA_KEY_SETUP_FAILED:157:camellia key setup failed
EVP_R_CANNOT_GET_PARAMETERS:197:cannot get parameters
EVP_R_CANNOT_SET_PARAMETERS:198:cannot set parameters
EVP_R_CIPHER_NOT_GCM_MODE:184:cipher not gcm mode
EVP_R_CIPHER_PARAMETER_ERROR:122:cipher parameter error
EVP_R_COMMAND_NOT_SUPPORTED:147:command not supported
EVP_R_CONFLICTING_ALGORITHM_NAME:201:conflicting algorithm name
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_DEFAULT_QUERY_PARSE_ERROR:210:default query parse 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_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_ECX_KEY:219:expecting an ecx key
EVP_R_EXPECTING_A_EC_KEY:142:expecting an 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_FINAL_ERROR:188:final error
EVP_R_GENERATE_ERROR:214:generate error
EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS:204:inaccessible domain parameters
EVP_R_INACCESSIBLE_KEY:203:inaccessible key
EVP_R_INITIALIZATION_ERROR:134:initialization error
EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized
EVP_R_INVALID_CUSTOM_LENGTH:185:invalid custom length
EVP_R_INVALID_DIGEST:152:invalid digest
EVP_R_INVALID_IV_LENGTH:194:invalid iv length
EVP_R_INVALID_KEY:163:invalid key
EVP_R_INVALID_KEY_LENGTH:130:invalid key length
EVP_R_INVALID_LENGTH:221:invalid length
EVP_R_INVALID_NULL_ALGORITHM:218:invalid null algorithm
EVP_R_INVALID_OPERATION:148:invalid operation
EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions
EVP_R_INVALID_SALT_LENGTH:186:invalid salt length
EVP_R_INVALID_SECRET_LENGTH:223:invalid secret length
EVP_R_INVALID_SEED_LENGTH:220:invalid seed length
EVP_R_INVALID_VALUE:222:invalid value
EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure
EVP_R_KEY_SETUP_FAILED:180:key setup failed
EVP_R_LOCKING_NOT_SUPPORTED:213:locking not supported
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_ABLE_TO_COPY_CTX:190:not able to copy ctx
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_IMPORT_FUNCTION:206:no import function
EVP_R_NO_KEYMGMT_AVAILABLE:199:no keymgmt available
EVP_R_NO_KEYMGMT_PRESENT:196:no keymgmt present
EVP_R_NO_KEY_SET:154:no key set
EVP_R_NO_OPERATION_SET:149:no operation set
EVP_R_NULL_MAC_PKEY_CTX:208:null mac pkey ctx
EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported
EVP_R_OPERATION_NOT_INITIALIZED:151:operation not initialized
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\
operation not supported for this keytype
EVP_R_OUTPUT_WOULD_OVERFLOW:202:output would overflow
EVP_R_PARAMETER_TOO_LARGE:187:parameter too large
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_SETTING_XOF_FAILED:227:setting xof failed
EVP_R_SET_DEFAULT_PROPERTY_FAILURE:209:set default property failure
EVP_R_TOO_MANY_RECORDS:183:too many records
EVP_R_UNABLE_TO_ENABLE_LOCKING:212:unable to enable locking
EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE:215:unable to get maximum request size
EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH:216:unable to get random strength
EVP_R_UNABLE_TO_LOCK_CONTEXT:211:unable to lock context
EVP_R_UNABLE_TO_SET_CALLBACKS:217:unable to set callbacks
EVP_R_UNKNOWN_CIPHER:160:unknown cipher
EVP_R_UNKNOWN_DIGEST:161:unknown digest
EVP_R_UNKNOWN_KEY_TYPE:207:unknown key type
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_KEY_TYPE:224:unsupported key type
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_UPDATE_ERROR:189:update error
EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed
EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length
EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE:191:xts data unit is too large
EVP_R_XTS_DUPLICATED_KEYS:192:xts duplicated keys
HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN:108:asn1 len exceeds max resp len
HTTP_R_CONNECT_FAILURE:100:connect failure
HTTP_R_ERROR_PARSING_ASN1_LENGTH:109:error parsing asn1 length
HTTP_R_ERROR_PARSING_CONTENT_LENGTH:119:error parsing content length
HTTP_R_ERROR_PARSING_URL:101:error parsing url
HTTP_R_ERROR_RECEIVING:103:error receiving
HTTP_R_ERROR_SENDING:102:error sending
HTTP_R_FAILED_READING_DATA:128:failed reading data
HTTP_R_HEADER_PARSE_ERROR:126:header parse error
HTTP_R_INCONSISTENT_CONTENT_LENGTH:120:inconsistent content length
HTTP_R_INVALID_PORT_NUMBER:123:invalid port number
HTTP_R_INVALID_URL_PATH:125:invalid url path
HTTP_R_INVALID_URL_SCHEME:124:invalid url scheme
HTTP_R_MAX_RESP_LEN_EXCEEDED:117:max resp len exceeded
HTTP_R_MISSING_ASN1_ENCODING:110:missing asn1 encoding
HTTP_R_MISSING_CONTENT_TYPE:121:missing content type
HTTP_R_MISSING_REDIRECT_LOCATION:111:missing redirect location
HTTP_R_RECEIVED_ERROR:105:received error
HTTP_R_RECEIVED_WRONG_HTTP_VERSION:106:received wrong http version
HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http
HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled
HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long
HTTP_R_RESPONSE_PARSE_ERROR:104:response parse error
HTTP_R_RETRY_TIMEOUT:129:retry timeout
HTTP_R_SERVER_CANCELED_CONNECTION:127:server canceled connection
HTTP_R_SOCK_NOT_SUPPORTED:122:sock not supported
HTTP_R_STATUS_CODE_UNSUPPORTED:114:status code unsupported
HTTP_R_TLS_NOT_ENABLED:107:tls not enabled
HTTP_R_TOO_MANY_REDIRECTIONS:115:too many redirections
HTTP_R_UNEXPECTED_CONTENT_TYPE:118:unexpected content type
OBJ_R_OID_EXISTS:102:oid exists
OBJ_R_UNKNOWN_NID:101:unknown nid
OBJ_R_UNKNOWN_OBJECT_NAME:103:unknown object name
OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error
OCSP_R_DIGEST_ERR:102:digest err
OCSP_R_DIGEST_NAME_ERR:106:digest name err
OCSP_R_DIGEST_SIZE_ERR:107:digest size 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_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_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_DECODER_R_COULD_NOT_DECODE_OBJECT:101:could not decode object
OSSL_DECODER_R_DECODER_NOT_FOUND:102:decoder not found
OSSL_DECODER_R_MISSING_GET_PARAMS:100:missing get params
OSSL_ENCODER_R_ENCODER_NOT_FOUND:101:encoder not found
OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY:100:incorrect property query
OSSL_ENCODER_R_MISSING_GET_PARAMS:102:missing get params
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_NAME:103:not a name
OSSL_STORE_R_NOT_A_PRIVATE_KEY:102:not a private key
OSSL_STORE_R_NOT_A_PUBLIC_KEY:122:not a public key
OSSL_STORE_R_NOT_PARAMETERS:104:not parameters
OSSL_STORE_R_NO_LOADERS_FOUND:123:no loaders found
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_DSS_KEY_BLOB:131:expecting dss key blob
PEM_R_EXPECTING_PRIVATE_KEY_BLOB:119:expecting private key blob
PEM_R_EXPECTING_PUBLIC_KEY_BLOB:120:expecting public key blob
PEM_R_EXPECTING_RSA_KEY_BLOB:132:expecting rsa 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
PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE:110:unsupported public key type
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_INVALID_TYPE:112:invalid type
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_CIPHERFINAL_ERROR:116:pkcs12 cipherfinal 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
PROP_R_NAME_TOO_LONG:100:name too long
PROP_R_NOT_AN_ASCII_CHARACTER:101:not an ascii character
PROP_R_NOT_AN_HEXADECIMAL_DIGIT:102:not an hexadecimal digit
PROP_R_NOT_AN_IDENTIFIER:103:not an identifier
PROP_R_NOT_AN_OCTAL_DIGIT:104:not an octal digit
PROP_R_NOT_A_DECIMAL_DIGIT:105:not a decimal digit
PROP_R_NO_MATCHING_STRING_DELIMITER:106:no matching string delimiter
PROP_R_NO_VALUE:107:no value
PROP_R_PARSE_FAILED:108:parse failed
PROP_R_STRING_TOO_LONG:109:string too long
PROP_R_TRAILING_CHARACTERS:110:trailing characters
PROV_R_ADDITIONAL_INPUT_TOO_LONG:184:additional input too long
PROV_R_ALGORITHM_MISMATCH:173:algorithm mismatch
PROV_R_ALREADY_INSTANTIATED:185:already instantiated
PROV_R_BAD_DECRYPT:100:bad decrypt
PROV_R_BAD_ENCODING:141:bad encoding
PROV_R_BAD_LENGTH:142:bad length
PROV_R_BAD_TLS_CLIENT_VERSION:161:bad tls client version
PROV_R_BN_ERROR:160:bn error
PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
PROV_R_DERIVATION_FUNCTION_INIT_FAILED:205:derivation function init failed
PROV_R_DIGEST_NOT_ALLOWED:174:digest not allowed
PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK:186:entropy source strength too weak
PROV_R_ERROR_INSTANTIATING_DRBG:188:error instantiating drbg
PROV_R_ERROR_RETRIEVING_ENTROPY:189:error retrieving entropy
PROV_R_ERROR_RETRIEVING_NONCE:190:error retrieving nonce
PROV_R_FAILED_DURING_DERIVATION:164:failed during derivation
PROV_R_FAILED_TO_CREATE_LOCK:180:failed to create lock
PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt
PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key
PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
PROV_R_FAILED_TO_SIGN:175:failed to sign
PROV_R_FIPS_MODULE_CONDITIONAL_ERROR:227:fips module conditional error
PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE:224:fips module entering error state
PROV_R_FIPS_MODULE_IN_ERROR_STATE:225:fips module in error state
PROV_R_GENERATE_ERROR:191:generate error
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\
illegal or unsupported padding mode
PROV_R_INDICATOR_INTEGRITY_FAILURE:210:indicator integrity failure
PROV_R_INSUFFICIENT_DRBG_STRENGTH:181:insufficient drbg strength
PROV_R_INVALID_AAD:108:invalid aad
PROV_R_INVALID_CONFIG_DATA:211:invalid config data
PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length
PROV_R_INVALID_CURVE:176:invalid curve
PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length
PROV_R_INVALID_DATA:115:invalid data
PROV_R_INVALID_DIGEST:122:invalid digest
PROV_R_INVALID_DIGEST_LENGTH:166:invalid digest length
PROV_R_INVALID_DIGEST_SIZE:218:invalid digest size
PROV_R_INVALID_INPUT_LENGTH:230:invalid input length
PROV_R_INVALID_ITERATION_COUNT:123:invalid iteration count
PROV_R_INVALID_IV_LENGTH:109:invalid iv length
PROV_R_INVALID_KEY:158:invalid key
PROV_R_INVALID_KEY_LENGTH:105:invalid key length
PROV_R_INVALID_MAC:151:invalid mac
PROV_R_INVALID_MGF1_MD:167:invalid mgf1 md
PROV_R_INVALID_MODE:125:invalid mode
PROV_R_INVALID_OUTPUT_LENGTH:217:invalid output length
PROV_R_INVALID_PADDING_MODE:168:invalid padding mode
PROV_R_INVALID_PUBINFO:198:invalid pubinfo
PROV_R_INVALID_SALT_LENGTH:112:invalid salt length
PROV_R_INVALID_SEED_LENGTH:154:invalid seed length
PROV_R_INVALID_SIGNATURE_SIZE:179:invalid signature size
PROV_R_INVALID_STATE:212:invalid state
PROV_R_INVALID_TAG:110:invalid tag
PROV_R_INVALID_TAG_LENGTH:118:invalid tag length
PROV_R_INVALID_UKM_LENGTH:200:invalid ukm length
PROV_R_INVALID_X931_DIGEST:170:invalid x931 digest
PROV_R_IN_ERROR_STATE:192:in error state
PROV_R_KEY_SETUP_FAILED:101:key setup failed
PROV_R_KEY_SIZE_TOO_SMALL:171:key size too small
PROV_R_LENGTH_TOO_LARGE:202:length too large
PROV_R_MISMATCHING_DOMAIN_PARAMETERS:203:mismatching domain parameters
PROV_R_MISSING_CEK_ALG:144:missing cek alg
PROV_R_MISSING_CIPHER:155:missing cipher
PROV_R_MISSING_CONFIG_DATA:213:missing config data
PROV_R_MISSING_CONSTANT:156:missing constant
PROV_R_MISSING_KEY:128:missing key
PROV_R_MISSING_MAC:150:missing mac
PROV_R_MISSING_MESSAGE_DIGEST:129:missing message digest
PROV_R_MISSING_OID:209:missing OID
PROV_R_MISSING_PASS:130:missing pass
PROV_R_MISSING_SALT:131:missing salt
PROV_R_MISSING_SECRET:132:missing secret
PROV_R_MISSING_SEED:140:missing seed
PROV_R_MISSING_SESSION_ID:133:missing session id
PROV_R_MISSING_TYPE:134:missing type
PROV_R_MISSING_XCGHASH:135:missing xcghash
PROV_R_MODULE_INTEGRITY_FAILURE:214:module integrity failure
PROV_R_NOT_A_PRIVATE_KEY:221:not a private key
PROV_R_NOT_A_PUBLIC_KEY:220:not a public key
PROV_R_NOT_INSTANTIATED:193:not instantiated
PROV_R_NOT_PARAMETERS:226:not parameters
PROV_R_NOT_SUPPORTED:136:not supported
PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
PROV_R_NO_KEY_SET:114:no key set
PROV_R_NO_PARAMETERS_SET:177:no parameters set
PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:178:\
operation not supported for this keytype
PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS:228:\
parent cannot generate random numbers
PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED:187:parent cannot supply entropy seed
PROV_R_PARENT_LOCKING_NOT_ENABLED:182:parent locking not enabled
PROV_R_PARENT_STRENGTH_TOO_WEAK:194:parent strength too weak
PROV_R_PATH_MUST_BE_ABSOLUTE:219:path must be absolute
PROV_R_PERSONALISATION_STRING_TOO_LONG:195:personalisation string too long
PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small
PROV_R_REQUEST_TOO_LARGE_FOR_DRBG:196:request too large for drbg
PROV_R_REQUIRE_CTR_MODE_CIPHER:206:require ctr mode cipher
PROV_R_RESEED_ERROR:197:reseed error
PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:222:\
search only supported for directories
PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT:229:\
seed sources must not have a parent
PROV_R_SELF_TEST_KAT_FAILURE:215:self test kat failure
PROV_R_SELF_TEST_POST_FAILURE:216:self test post failure
PROV_R_TAG_NOT_NEEDED:120:tag not needed
PROV_R_TAG_NOT_SET:119:tag not set
PROV_R_TOO_MANY_RECORDS:126:too many records
PROV_R_UNABLE_TO_FIND_CIPHERS:207:unable to find ciphers
PROV_R_UNABLE_TO_GET_PARENT_STRENGTH:199:unable to get parent strength
PROV_R_UNABLE_TO_GET_PASSPHRASE:159:unable to get passphrase
PROV_R_UNABLE_TO_INITIALISE_CIPHERS:208:unable to initialise ciphers
PROV_R_UNABLE_TO_LOAD_SHA256:147:unable to load sha256
PROV_R_UNABLE_TO_LOCK_PARENT:201:unable to lock parent
PROV_R_UNABLE_TO_RESEED:204:unable to reseed
PROV_R_UNSUPPORTED_CEK_ALG:145:unsupported cek alg
PROV_R_UNSUPPORTED_KEY_SIZE:153:unsupported key size
PROV_R_UNSUPPORTED_MAC_TYPE:137:unsupported mac type
PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS:152:unsupported number of rounds
PROV_R_URI_AUTHORITY_UNSUPPORTED:223:uri authority unsupported
PROV_R_VALUE_ERROR:138:value error
PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
PROV_R_WRONG_OUTPUT_BUFFER_SIZE:139:wrong output buffer size
PROV_R_XOF_DIGESTS_NOT_ALLOWED:183:xof digests not allowed
PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE:148:xts data unit is too large
PROV_R_XTS_DUPLICATED_KEYS:149:xts duplicated keys
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_INSUFFICIENT_DRBG_STRENGTH:139:insufficient drbg strength
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_UNABLE_TO_CREATE_DRBG:143:unable to create drbg
RAND_R_UNABLE_TO_FETCH_DRBG:144:unable to fetch drbg
RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER:141:\
unable to get parent reseed prop counter
RAND_R_UNABLE_TO_GET_PARENT_STRENGTH:138:unable to get parent strength
RAND_R_UNABLE_TO_LOCK_PARENT:140:unable to lock parent
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_KEYPAIR:171:invalid keypair
RSA_R_INVALID_KEY_LENGTH:173:invalid key length
RSA_R_INVALID_LABEL:160:invalid label
RSA_R_INVALID_LENGTH:181:invalid length
RSA_R_INVALID_MESSAGE_LENGTH:131:invalid message length
RSA_R_INVALID_MGF1_MD:156:invalid mgf1 md
RSA_R_INVALID_MODULUS:174:invalid modulus
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_REQUEST:175:invalid request
RSA_R_INVALID_SALT_LENGTH:150:invalid salt length
RSA_R_INVALID_STRENGTH:176:invalid strength
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_MISSING_PRIVATE_KEY:179:missing private key
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_PAIRWISE_TEST_FAILURE:177:pairwise test failure
RSA_R_PKCS_DECODING_ERROR:159:pkcs decoding error
RSA_R_PSS_SALTLEN_TOO_SMALL:164:pss saltlen too small
RSA_R_PUB_EXPONENT_OUT_OF_RANGE:178:pub exponent out of range
RSA_R_P_NOT_PRIME:128:p not prime
RSA_R_Q_NOT_PRIME:129:q not prime
RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT:180:\
randomness source strength insufficient
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_INVALID_PRIVATE_KEY:113:invalid private key
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_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_CANNOT_GET_GROUP_NAME:299:cannot get group name
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_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_COPY_PARAMETERS_FAILED:296:copy parameters failed
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_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED:333:\
legacy sigalg disallowed or unsupported
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_PSK_KEX_MODES_EXTENSION:310:missing psk kex modes extension
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_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA:293:\
mixed handshake and non handshake data
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_DIGEST_ALGORITHM:297:no suitable digest algorithm
SSL_R_NO_SUITABLE_GROUPS:295:no suitable groups
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_OCSP_CALLBACK_FAILURE:305:ocsp callback failure
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_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_EOF_WHILE_READING:294:unexpected eof while reading
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_EMPTY_KEY_USAGE:169:empty key usage
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_CERTIFICATE:158:invalid certificate
X509V3_R_INVALID_EMPTY_NAME:108:invalid empty name
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_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_NEGATIVE_PATHLEN:168:negative pathlen
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_CERTIFICATE_VERIFICATION_FAILED:139:certificate verification failed
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_DUPLICATE_ATTRIBUTE:140:duplicate attribute
X509_R_ERROR_GETTING_MD_BY_NID:141:error getting md by nid
X509_R_ERROR_USING_SIGINF_SET:142:error using siginf set
X509_R_IDP_MISMATCH:128:idp mismatch
X509_R_INVALID_ATTRIBUTES:138:invalid attributes
X509_R_INVALID_DIRECTORY:113:invalid directory
X509_R_INVALID_DISTPOINT:143:invalid distpoint
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_SIGID_ALGS:144:unknown sigid algs
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/openssl/crypto/evp/ctrl_params_translate.c b/crypto/openssl/crypto/evp/ctrl_params_translate.c
index de6c215e205a..44d0895bcf14 100644
--- a/crypto/openssl/crypto/evp/ctrl_params_translate.c
+++ b/crypto/openssl/crypto/evp/ctrl_params_translate.c
@@ -1,2874 +1,2884 @@
/*
* Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* Some ctrls depend on deprecated functionality. We trust that this is
* functionality that remains internally even when 'no-deprecated' is
* configured. When we drop #legacy EVP_PKEYs, this source should be
* possible to drop as well.
*/
#include "internal/deprecated.h"
#include <string.h>
/* The following includes get us all the EVP_PKEY_CTRL macros */
#include <openssl/dh.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include <openssl/rsa.h>
#include <openssl/kdf.h>
/* This include gets us all the OSSL_PARAM key string macros */
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/evperr.h>
#include <openssl/params.h>
#include "internal/nelem.h"
#include "internal/cryptlib.h"
#include "internal/ffc.h"
#include "crypto/evp.h"
#include "crypto/dh.h"
#include "crypto/ec.h"
struct translation_ctx_st; /* Forwarding */
struct translation_st; /* Forwarding */
/*
* The fixup_args functions are called with the following parameters:
*
* |state| The state we're called in, explained further at the
* end of this comment.
* |translation| The translation item, to be pilfered for data as
* necessary.
* |ctx| The translation context, which contains copies of
* the following arguments, applicable according to
* the caller. All of the attributes in this context
* may be freely modified by the fixup_args function.
* For cleanup, call cleanup_translation_ctx().
*
* The |state| tells the fixup_args function something about the caller and
* what they may expect:
*
* PKEY The fixup_args function has been called
* from an EVP_PKEY payload getter / setter,
* and is fully responsible for getting or
* setting the requested data. With this
* state, the fixup_args function is expected
* to use or modify |*params|, depending on
* |action_type|.
*
* PRE_CTRL_TO_PARAMS The fixup_args function has been called
* POST_CTRL_TO_PARAMS from EVP_PKEY_CTX_ctrl(), to help with
* translating the ctrl data to an OSSL_PARAM
* element or back. The calling sequence is
* as follows:
*
* 1. fixup_args(PRE_CTRL_TO_PARAMS, ...)
* 2. EVP_PKEY_CTX_set_params() or
* EVP_PKEY_CTX_get_params()
* 3. fixup_args(POST_CTRL_TO_PARAMS, ...)
*
* With the PRE_CTRL_TO_PARAMS state, the
* fixup_args function is expected to modify
* the passed |*params| in whatever way
* necessary, when |action_type == SET|.
* With the POST_CTRL_TO_PARAMS state, the
* fixup_args function is expected to modify
* the passed |p2| in whatever way necessary,
* when |action_type == GET|.
*
* The return value from the fixup_args call
* with the POST_CTRL_TO_PARAMS state becomes
* the return value back to EVP_PKEY_CTX_ctrl().
*
* CLEANUP_CTRL_TO_PARAMS The cleanup_args functions has been called
* from EVP_PKEY_CTX_ctrl(), to clean up what
* the fixup_args function has done, if needed.
*
*
* PRE_CTRL_STR_TO_PARAMS The fixup_args function has been called
* POST_CTRL_STR_TO_PARAMS from EVP_PKEY_CTX_ctrl_str(), to help with
* translating the ctrl_str data to an
* OSSL_PARAM element or back. The calling
* sequence is as follows:
*
* 1. fixup_args(PRE_CTRL_STR_TO_PARAMS, ...)
* 2. EVP_PKEY_CTX_set_params() or
* EVP_PKEY_CTX_get_params()
* 3. fixup_args(POST_CTRL_STR_TO_PARAMS, ...)
*
* With the PRE_CTRL_STR_TO_PARAMS state,
* the fixup_args function is expected to
* modify the passed |*params| in whatever
* way necessary, when |action_type == SET|.
* With the POST_CTRL_STR_TO_PARAMS state,
* the fixup_args function is only expected
* to return a value.
*
* CLEANUP_CTRL_STR_TO_PARAMS The cleanup_args functions has been called
* from EVP_PKEY_CTX_ctrl_str(), to clean up
* what the fixup_args function has done, if
* needed.
*
* PRE_PARAMS_TO_CTRL The fixup_args function has been called
* POST_PARAMS_TO_CTRL from EVP_PKEY_CTX_get_params() or
* EVP_PKEY_CTX_set_params(), to help with
* translating the OSSL_PARAM data to the
* corresponding EVP_PKEY_CTX_ctrl() arguments
* or the other way around. The calling
* sequence is as follows:
*
* 1. fixup_args(PRE_PARAMS_TO_CTRL, ...)
* 2. EVP_PKEY_CTX_ctrl()
* 3. fixup_args(POST_PARAMS_TO_CTRL, ...)
*
* With the PRE_PARAMS_TO_CTRL state, the
* fixup_args function is expected to modify
* the passed |p1| and |p2| in whatever way
* necessary, when |action_type == SET|.
* With the POST_PARAMS_TO_CTRL state, the
* fixup_args function is expected to
* modify the passed |*params| in whatever
* way necessary, when |action_type == GET|.
*
* CLEANUP_PARAMS_TO_CTRL The cleanup_args functions has been called
* from EVP_PKEY_CTX_get_params() or
* EVP_PKEY_CTX_set_params(), to clean up what
* the fixup_args function has done, if needed.
*/
enum state {
PKEY,
PRE_CTRL_TO_PARAMS, POST_CTRL_TO_PARAMS, CLEANUP_CTRL_TO_PARAMS,
PRE_CTRL_STR_TO_PARAMS, POST_CTRL_STR_TO_PARAMS, CLEANUP_CTRL_STR_TO_PARAMS,
PRE_PARAMS_TO_CTRL, POST_PARAMS_TO_CTRL, CLEANUP_PARAMS_TO_CTRL
};
enum action {
NONE = 0, GET = 1, SET = 2
};
typedef int fixup_args_fn(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx);
typedef int cleanup_args_fn(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx);
struct translation_ctx_st {
/*
* The EVP_PKEY_CTX, for calls on that structure, to be pilfered for data
* as necessary.
*/
EVP_PKEY_CTX *pctx;
/*
* The action type (GET or SET). This may be 0 in some cases, and should
* be modified by the fixup_args function in the PRE states. It should
* otherwise remain untouched once set.
*/
enum action action_type;
/*
* For ctrl to params translation, the actual ctrl command number used.
* For params to ctrl translation, 0.
*/
int ctrl_cmd;
/*
* For ctrl_str to params translation, the actual ctrl command string
* used. In this case, the (string) value is always passed as |p2|.
* For params to ctrl translation, this is NULL. Along with it is also
* and indicator whether it matched |ctrl_str| or |ctrl_hexstr| in the
* translation item.
*/
const char *ctrl_str;
int ishex;
/* the ctrl-style int argument. */
int p1;
/* the ctrl-style void* argument. */
void *p2;
/* a size, for passing back the |p2| size where applicable */
size_t sz;
/* pointer to the OSSL_PARAM-style params array. */
OSSL_PARAM *params;
/*-
* The following are used entirely internally by the fixup_args functions
* and should not be touched by the callers, at all.
*/
/*
* Copy of the ctrl-style void* argument, if the fixup_args function
* needs to manipulate |p2| but wants to remember original.
*/
void *orig_p2;
/* Diverse types of storage for the needy. */
char name_buf[OSSL_MAX_NAME_SIZE];
void *allocated_buf;
void *bufp;
size_t buflen;
};
struct translation_st {
/*-
* What this table item does.
*
* If the item has this set to 0, it means that both GET and SET are
* supported, and |fixup_args| will determine which it is. This is to
* support translations of ctrls where the action type depends on the
* value of |p1| or |p2| (ctrls are really bi-directional, but are
* seldom used that way).
*
* This can be also used in the lookup template when it looks up by
* OSSL_PARAM key, to indicate if a setter or a getter called.
*/
enum action action_type;
/*-
* Conditions, for params->ctrl translations.
*
* In table item, |keytype1| and |keytype2| can be set to -1 to indicate
* that this item supports all key types (or rather, that |fixup_args|
* will check and return an error if it's not supported).
* Any of these may be set to 0 to indicate that they are unset.
*/
int keytype1; /* The EVP_PKEY_XXX type, i.e. NIDs. #legacy */
int keytype2; /* Another EVP_PKEY_XXX type, used for aliases */
int optype; /* The operation type */
/*
* Lookup and translation attributes
*
* |ctrl_num|, |ctrl_str|, |ctrl_hexstr| and |param_key| are lookup
* attributes.
*
* |ctrl_num| may be 0 or that |param_key| may be NULL in the table item,
* but not at the same time. If they are, they are simply not used for
* lookup.
* When |ctrl_num| == 0, no ctrl will be called. Likewise, when
* |param_key| == NULL, no OSSL_PARAM setter/getter will be called.
* In that case the treatment of the translation item relies entirely on
* |fixup_args|, which is then assumed to have side effects.
*
* As a special case, it's possible to set |ctrl_hexstr| and assign NULL
* to |ctrl_str|. That will signal to default_fixup_args() that the
* value must always be interpreted as hex.
*/
int ctrl_num; /* EVP_PKEY_CTRL_xxx */
const char *ctrl_str; /* The corresponding ctrl string */
const char *ctrl_hexstr; /* The alternative "hex{str}" ctrl string */
const char *param_key; /* The corresponding OSSL_PARAM key */
/*
* The appropriate OSSL_PARAM data type. This may be 0 to indicate that
* this OSSL_PARAM may have more than one data type, depending on input
* material. In this case, |fixup_args| is expected to check and handle
* it.
*/
unsigned int param_data_type;
/*
* Fixer functions
*
* |fixup_args| is always called before (for SET) or after (for GET)
* the actual ctrl / OSSL_PARAM function.
*/
fixup_args_fn *fixup_args;
};
/*-
* Fixer function implementations
* ==============================
*/
/*
* default_check isn't a fixer per se, but rather a helper function to
* perform certain standard checks.
*/
static int default_check(enum state state,
const struct translation_st *translation,
const struct translation_ctx_st *ctx)
{
switch (state) {
default:
break;
case PRE_CTRL_TO_PARAMS:
if (!ossl_assert(translation != NULL)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (!ossl_assert(translation->param_key != 0)
|| !ossl_assert(translation->param_data_type != 0)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return -1;
}
break;
case PRE_CTRL_STR_TO_PARAMS:
/*
* For ctrl_str to params translation, we allow direct use of
* OSSL_PARAM keys as ctrl_str keys. Therefore, it's possible that
* we end up with |translation == NULL|, which is fine. The fixup
* function will have to deal with it carefully.
*/
if (translation != NULL) {
if (!ossl_assert(translation->action_type != GET)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (!ossl_assert(translation->param_key != NULL)
|| !ossl_assert(translation->param_data_type != 0)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
}
break;
case PRE_PARAMS_TO_CTRL:
case POST_PARAMS_TO_CTRL:
if (!ossl_assert(translation != NULL)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (!ossl_assert(translation->ctrl_num != 0)
|| !ossl_assert(translation->param_data_type != 0)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return -1;
}
}
/* Nothing else to check */
return 1;
}
/*-
* default_fixup_args fixes up all sorts of arguments, governed by the
* diverse attributes in the translation item. It covers all "standard"
* base ctrl functionality, meaning it can handle basic conversion of
* data between p1+p2 (SET) or return value+p2 (GET) as long as the values
* don't have extra semantics (such as NIDs, OIDs, that sort of stuff).
* Extra semantics must be handled via specific fixup_args functions.
*
* The following states and action type combinations have standard handling
* done in this function:
*
* PRE_CTRL_TO_PARAMS, 0 - ERROR. action type must be
* determined by a fixup function.
* PRE_CTRL_TO_PARAMS, SET | GET - |p1| and |p2| are converted to an
* OSSL_PARAM according to the data
* type given in |translattion|.
* For OSSL_PARAM_UNSIGNED_INTEGER,
* a BIGNUM passed as |p2| is accepted.
* POST_CTRL_TO_PARAMS, GET - If the OSSL_PARAM data type is a
* STRING or PTR type, |p1| is set
* to the OSSL_PARAM return size, and
* |p2| is set to the string.
* PRE_CTRL_STR_TO_PARAMS, !SET - ERROR. That combination is not
* supported.
* PRE_CTRL_STR_TO_PARAMS, SET - |p2| is taken as a string, and is
* converted to an OSSL_PARAM in a
* standard manner, guided by the
* param key and data type from
* |translation|.
* PRE_PARAMS_TO_CTRL, SET - the OSSL_PARAM is converted to
* |p1| and |p2| according to the
* data type given in |translation|
* For OSSL_PARAM_UNSIGNED_INTEGER,
* if |p2| is non-NULL, then |*p2|
* is assigned a BIGNUM, otherwise
* |p1| is assigned an unsigned int.
* POST_PARAMS_TO_CTRL, GET - |p1| and |p2| are converted to
* an OSSL_PARAM, in the same manner
* as for the combination of
* PRE_CTRL_TO_PARAMS, SET.
*/
static int default_fixup_args(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
switch (state) {
default:
/* For states this function should never have been called with */
ERR_raise_data(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
"[action:%d, state:%d]", ctx->action_type, state);
return 0;
/*
* PRE_CTRL_TO_PARAMS and POST_CTRL_TO_PARAMS handle ctrl to params
* translations. PRE_CTRL_TO_PARAMS is responsible for preparing
* |*params|, and POST_CTRL_TO_PARAMS is responsible for bringing the
* result back to |*p2| and the return value.
*/
case PRE_CTRL_TO_PARAMS:
/* This is ctrl to params translation, so we need an OSSL_PARAM key */
if (ctx->action_type == NONE) {
/*
* No action type is an error here. That's a case for a
* special fixup function.
*/
ERR_raise_data(ERR_LIB_EVP, ERR_R_UNSUPPORTED,
"[action:%d, state:%d]", ctx->action_type, state);
return 0;
}
if (translation->optype != 0) {
if ((EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
&& ctx->pctx->op.sig.algctx == NULL)
|| (EVP_PKEY_CTX_IS_DERIVE_OP(ctx->pctx)
&& ctx->pctx->op.kex.algctx == NULL)
|| (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx->pctx)
&& ctx->pctx->op.ciph.algctx == NULL)
|| (EVP_PKEY_CTX_IS_KEM_OP(ctx->pctx)
&& ctx->pctx->op.encap.algctx == NULL)
/*
* The following may be unnecessary, but we have them
* for good measure...
*/
|| (EVP_PKEY_CTX_IS_GEN_OP(ctx->pctx)
&& ctx->pctx->op.keymgmt.genctx == NULL)
|| (EVP_PKEY_CTX_IS_FROMDATA_OP(ctx->pctx)
&& ctx->pctx->op.keymgmt.genctx == NULL)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
}
/*
* OSSL_PARAM_construct_TYPE() works equally well for both SET and GET.
*/
switch (translation->param_data_type) {
case OSSL_PARAM_INTEGER:
*ctx->params = OSSL_PARAM_construct_int(translation->param_key,
&ctx->p1);
break;
case OSSL_PARAM_UNSIGNED_INTEGER:
/*
* BIGNUMs are passed via |p2|. For all ctrl's that just want
* to pass a simple integer via |p1|, |p2| is expected to be
* NULL.
*
* Note that this allocates a buffer, which the cleanup function
* must deallocate.
*/
if (ctx->p2 != NULL) {
if (ctx->action_type == SET) {
ctx->buflen = BN_num_bytes(ctx->p2);
if ((ctx->allocated_buf =
OPENSSL_malloc(ctx->buflen)) == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
if (BN_bn2nativepad(ctx->p2,
ctx->allocated_buf, ctx->buflen) < 0) {
OPENSSL_free(ctx->allocated_buf);
ctx->allocated_buf = NULL;
return 0;
}
*ctx->params =
OSSL_PARAM_construct_BN(translation->param_key,
ctx->allocated_buf,
ctx->buflen);
} else {
/*
* No support for getting a BIGNUM by ctrl, this needs
* fixup_args function support.
*/
ERR_raise_data(ERR_LIB_EVP, ERR_R_UNSUPPORTED,
"[action:%d, state:%d] trying to get a "
"BIGNUM via ctrl call",
ctx->action_type, state);
return 0;
}
} else {
*ctx->params =
OSSL_PARAM_construct_uint(translation->param_key,
(unsigned int *)&ctx->p1);
}
break;
case OSSL_PARAM_UTF8_STRING:
*ctx->params =
OSSL_PARAM_construct_utf8_string(translation->param_key,
ctx->p2, (size_t)ctx->p1);
break;
case OSSL_PARAM_UTF8_PTR:
*ctx->params =
OSSL_PARAM_construct_utf8_ptr(translation->param_key,
ctx->p2, (size_t)ctx->p1);
break;
case OSSL_PARAM_OCTET_STRING:
*ctx->params =
OSSL_PARAM_construct_octet_string(translation->param_key,
ctx->p2, (size_t)ctx->p1);
break;
case OSSL_PARAM_OCTET_PTR:
*ctx->params =
OSSL_PARAM_construct_octet_ptr(translation->param_key,
ctx->p2, (size_t)ctx->p1);
break;
}
break;
case POST_CTRL_TO_PARAMS:
/*
* Because EVP_PKEY_CTX_ctrl() returns the length of certain objects
* as its return value, we need to ensure that we do it here as well,
* for the OSSL_PARAM data types where this makes sense.
*/
if (ctx->action_type == GET) {
switch (translation->param_data_type) {
case OSSL_PARAM_UTF8_STRING:
case OSSL_PARAM_UTF8_PTR:
case OSSL_PARAM_OCTET_STRING:
case OSSL_PARAM_OCTET_PTR:
ctx->p1 = (int)ctx->params[0].return_size;
break;
}
}
break;
/*
* PRE_CTRL_STR_TO_PARAMS and POST_CTRL_STR_TO_PARAMS handle ctrl_str to
* params translations. PRE_CTRL_TO_PARAMS is responsible for preparing
* |*params|, and POST_CTRL_TO_PARAMS currently has nothing to do, since
* there's no support for getting data via ctrl_str calls.
*/
case PRE_CTRL_STR_TO_PARAMS:
{
/* This is ctrl_str to params translation */
const char *tmp_ctrl_str = ctx->ctrl_str;
const char *orig_ctrl_str = ctx->ctrl_str;
const char *orig_value = ctx->p2;
const OSSL_PARAM *settable = NULL;
int exists = 0;
/* Only setting is supported here */
if (ctx->action_type != SET) {
ERR_raise_data(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED,
"[action:%d, state:%d] only setting allowed",
ctx->action_type, state);
return 0;
}
/*
* If no translation exists, we simply pass the control string
* unmodified.
*/
if (translation != NULL) {
tmp_ctrl_str = ctx->ctrl_str = translation->param_key;
if (ctx->ishex) {
strcpy(ctx->name_buf, "hex");
if (OPENSSL_strlcat(ctx->name_buf, tmp_ctrl_str,
sizeof(ctx->name_buf)) <= 3) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return -1;
}
tmp_ctrl_str = ctx->name_buf;
}
}
settable = EVP_PKEY_CTX_settable_params(ctx->pctx);
if (!OSSL_PARAM_allocate_from_text(ctx->params, settable,
tmp_ctrl_str,
ctx->p2, strlen(ctx->p2),
&exists)) {
if (!exists) {
ERR_raise_data(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED,
"[action:%d, state:%d] name=%s, value=%s",
ctx->action_type, state,
orig_ctrl_str, orig_value);
return -2;
}
return 0;
}
ctx->allocated_buf = ctx->params->data;
ctx->buflen = ctx->params->data_size;
}
break;
case POST_CTRL_STR_TO_PARAMS:
/* Nothing to be done */
break;
/*
* PRE_PARAMS_TO_CTRL and POST_PARAMS_TO_CTRL handle params to ctrl
* translations. PRE_PARAMS_TO_CTRL is responsible for preparing
* |p1| and |p2|, and POST_PARAMS_TO_CTRL is responsible for bringing
* the EVP_PKEY_CTX_ctrl() return value (passed as |p1|) and |p2| back
* to |*params|.
*
* PKEY is treated just like POST_PARAMS_TO_CTRL, making it easy
* for the related fixup_args functions to just set |p1| and |p2|
* appropriately and leave it to this section of code to fix up
* |ctx->params| accordingly.
*/
case PKEY:
case POST_PARAMS_TO_CTRL:
ret = ctx->p1;
/* FALLTHRU */
case PRE_PARAMS_TO_CTRL:
{
/* This is params to ctrl translation */
if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == SET) {
/* For the PRE state, only setting needs some work to be done */
/* When setting, we populate |p1| and |p2| from |*params| */
switch (translation->param_data_type) {
case OSSL_PARAM_INTEGER:
return OSSL_PARAM_get_int(ctx->params, &ctx->p1);
case OSSL_PARAM_UNSIGNED_INTEGER:
if (ctx->p2 != NULL) {
/* BIGNUM passed down with p2 */
if (!OSSL_PARAM_get_BN(ctx->params, ctx->p2))
return 0;
} else {
/* Normal C unsigned int passed down */
if (!OSSL_PARAM_get_uint(ctx->params,
(unsigned int *)&ctx->p1))
return 0;
}
return 1;
case OSSL_PARAM_UTF8_STRING:
return OSSL_PARAM_get_utf8_string(ctx->params,
ctx->p2, ctx->sz);
case OSSL_PARAM_OCTET_STRING:
return OSSL_PARAM_get_octet_string(ctx->params,
&ctx->p2, ctx->sz,
(size_t *)&ctx->p1);
case OSSL_PARAM_OCTET_PTR:
return OSSL_PARAM_get_octet_ptr(ctx->params,
ctx->p2, &ctx->sz);
default:
ERR_raise_data(ERR_LIB_EVP, ERR_R_UNSUPPORTED,
"[action:%d, state:%d] "
"unknown OSSL_PARAM data type %d",
ctx->action_type, state,
translation->param_data_type);
return 0;
}
} else if ((state == POST_PARAMS_TO_CTRL || state == PKEY)
&& ctx->action_type == GET) {
/* For the POST state, only getting needs some work to be done */
unsigned int param_data_type = translation->param_data_type;
size_t size = (size_t)ctx->p1;
if (state == PKEY)
size = ctx->sz;
if (param_data_type == 0) {
/* we must have a fixup_args function to work */
if (!ossl_assert(translation->fixup_args != NULL)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
param_data_type = ctx->params->data_type;
}
/* When getting, we populate |*params| from |p1| and |p2| */
switch (param_data_type) {
case OSSL_PARAM_INTEGER:
return OSSL_PARAM_set_int(ctx->params, ctx->p1);
case OSSL_PARAM_UNSIGNED_INTEGER:
if (ctx->p2 != NULL) {
/* BIGNUM passed back */
return OSSL_PARAM_set_BN(ctx->params, ctx->p2);
} else {
/* Normal C unsigned int passed back */
return OSSL_PARAM_set_uint(ctx->params,
(unsigned int)ctx->p1);
}
return 0;
case OSSL_PARAM_UTF8_STRING:
return OSSL_PARAM_set_utf8_string(ctx->params, ctx->p2);
case OSSL_PARAM_OCTET_STRING:
return OSSL_PARAM_set_octet_string(ctx->params, ctx->p2,
size);
case OSSL_PARAM_OCTET_PTR:
return OSSL_PARAM_set_octet_ptr(ctx->params, *(void **)ctx->p2,
size);
default:
ERR_raise_data(ERR_LIB_EVP, ERR_R_UNSUPPORTED,
"[action:%d, state:%d] "
"unsupported OSSL_PARAM data type %d",
ctx->action_type, state,
translation->param_data_type);
return 0;
}
} else if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == GET) {
if (translation->param_data_type == OSSL_PARAM_OCTET_PTR)
ctx->p2 = &ctx->bufp;
}
}
/* Any other combination is simply pass-through */
break;
}
return ret;
}
static int
cleanup_translation_ctx(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
if (ctx->allocated_buf != NULL)
OPENSSL_free(ctx->allocated_buf);
ctx->allocated_buf = NULL;
return 1;
}
/*
* fix_cipher_md fixes up an EVP_CIPHER / EVP_MD to its name on SET,
* and cipher / md name to EVP_MD on GET.
*/
static const char *get_cipher_name(void *cipher)
{
return EVP_CIPHER_get0_name(cipher);
}
static const char *get_md_name(void *md)
{
return EVP_MD_get0_name(md);
}
static const void *get_cipher_by_name(OSSL_LIB_CTX *libctx, const char *name)
{
return evp_get_cipherbyname_ex(libctx, name);
}
static const void *get_md_by_name(OSSL_LIB_CTX *libctx, const char *name)
{
return evp_get_digestbyname_ex(libctx, name);
}
static int fix_cipher_md(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx,
const char *(*get_name)(void *algo),
const void *(*get_algo_by_name)(OSSL_LIB_CTX *libctx,
const char *name))
{
int ret = 1;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == GET) {
/*
* |ctx->p2| contains the address to an EVP_CIPHER or EVP_MD pointer
* to be filled in. We need to remember it, then make |ctx->p2|
* point at a buffer to be filled in with the name, and |ctx->p1|
* with its size. default_fixup_args() will take care of the rest
* for us.
*/
ctx->orig_p2 = ctx->p2;
ctx->p2 = ctx->name_buf;
ctx->p1 = sizeof(ctx->name_buf);
} else if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET) {
/*
* In different parts of OpenSSL, this ctrl command is used
* differently. Some calls pass a NID as p1, others pass an
* EVP_CIPHER pointer as p2...
*/
ctx->p2 = (char *)(ctx->p2 == NULL
? OBJ_nid2sn(ctx->p1)
: get_name(ctx->p2));
ctx->p1 = strlen(ctx->p2);
} else if (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET) {
ctx->p2 = (ctx->p2 == NULL ? "" : (char *)get_name(ctx->p2));
ctx->p1 = strlen(ctx->p2);
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if (state == POST_CTRL_TO_PARAMS && ctx->action_type == GET) {
/*
* Here's how we re-use |ctx->orig_p2| that was set in the
* PRE_CTRL_TO_PARAMS state above.
*/
*(void **)ctx->orig_p2 =
(void *)get_algo_by_name(ctx->pctx->libctx, ctx->p2);
ctx->p1 = 1;
} else if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == SET) {
ctx->p2 = (void *)get_algo_by_name(ctx->pctx->libctx, ctx->p2);
ctx->p1 = 0;
}
return ret;
}
static int fix_cipher(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
return fix_cipher_md(state, translation, ctx,
get_cipher_name, get_cipher_by_name);
}
static int fix_md(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
return fix_cipher_md(state, translation, ctx,
get_md_name, get_md_by_name);
}
static int fix_distid_len(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
int ret = default_fixup_args(state, translation, ctx);
if (ret > 0) {
ret = 0;
if ((state == POST_CTRL_TO_PARAMS
|| state == POST_CTRL_STR_TO_PARAMS) && ctx->action_type == GET) {
*(size_t *)ctx->p2 = ctx->sz;
ret = 1;
}
}
return ret;
}
struct kdf_type_map_st {
int kdf_type_num;
const char *kdf_type_str;
};
static int fix_kdf_type(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx,
const struct kdf_type_map_st *kdf_type_map)
{
/*
* The EVP_PKEY_CTRL_DH_KDF_TYPE ctrl command is a bit special, in
* that it's used both for setting a value, and for getting it, all
* depending on the value if |p1|; if |p1| is -2, the backend is
* supposed to place the current kdf type in |p2|, and if not, |p1|
* is interpreted as the new kdf type.
*/
int ret = 0;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
if (state == PRE_CTRL_TO_PARAMS) {
/*
* In |translations|, the initial value for |ctx->action_type| must
* be NONE.
*/
if (!ossl_assert(ctx->action_type == NONE))
return 0;
/* The action type depends on the value of *p1 */
if (ctx->p1 == -2) {
/*
* The OSSL_PARAMS getter needs space to store a copy of the kdf
* type string. We use |ctx->name_buf|, which has enough space
* allocated.
*
* (this wouldn't be needed if the OSSL_xxx_PARAM_KDF_TYPE
* had the data type OSSL_PARAM_UTF8_PTR)
*/
ctx->p2 = ctx->name_buf;
ctx->p1 = sizeof(ctx->name_buf);
ctx->action_type = GET;
} else {
ctx->action_type = SET;
}
}
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
if ((state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET)
|| (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET)) {
ret = -2;
/* Convert KDF type numbers to strings */
for (; kdf_type_map->kdf_type_str != NULL; kdf_type_map++)
if (ctx->p1 == kdf_type_map->kdf_type_num) {
ctx->p2 = (char *)kdf_type_map->kdf_type_str;
ret = 1;
break;
}
if (ret <= 0)
goto end;
ctx->p1 = strlen(ctx->p2);
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if ((state == POST_CTRL_TO_PARAMS && ctx->action_type == GET)
|| (state == PRE_PARAMS_TO_CTRL && ctx->action_type == SET)) {
ctx->p1 = ret = -1;
/* Convert KDF type strings to numbers */
for (; kdf_type_map->kdf_type_str != NULL; kdf_type_map++)
if (OPENSSL_strcasecmp(ctx->p2, kdf_type_map->kdf_type_str) == 0) {
ctx->p1 = kdf_type_map->kdf_type_num;
ret = 1;
break;
}
ctx->p2 = NULL;
} else if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == GET) {
ctx->p1 = -2;
}
end:
return ret;
}
/* EVP_PKEY_CTRL_DH_KDF_TYPE */
static int fix_dh_kdf_type(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
static const struct kdf_type_map_st kdf_type_map[] = {
{ EVP_PKEY_DH_KDF_NONE, "" },
{ EVP_PKEY_DH_KDF_X9_42, OSSL_KDF_NAME_X942KDF_ASN1 },
{ 0, NULL }
};
return fix_kdf_type(state, translation, ctx, kdf_type_map);
}
/* EVP_PKEY_CTRL_EC_KDF_TYPE */
static int fix_ec_kdf_type(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
static const struct kdf_type_map_st kdf_type_map[] = {
{ EVP_PKEY_ECDH_KDF_NONE, "" },
{ EVP_PKEY_ECDH_KDF_X9_63, OSSL_KDF_NAME_X963KDF },
{ 0, NULL }
};
return fix_kdf_type(state, translation, ctx, kdf_type_map);
}
/* EVP_PKEY_CTRL_DH_KDF_OID, EVP_PKEY_CTRL_GET_DH_KDF_OID, ...??? */
static int fix_oid(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
if ((state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET)
|| (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET)) {
/*
* We're translating from ctrl to params and setting the OID, or
* we're translating from params to ctrl and getting the OID.
* Either way, |ctx->p2| points at an ASN1_OBJECT, and needs to have
* that replaced with the corresponding name.
* default_fixup_args() will then be able to convert that to the
* corresponding OSSL_PARAM.
*/
OBJ_obj2txt(ctx->name_buf, sizeof(ctx->name_buf), ctx->p2, 0);
ctx->p2 = (char *)ctx->name_buf;
ctx->p1 = 0; /* let default_fixup_args() figure out the length */
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if ((state == PRE_PARAMS_TO_CTRL && ctx->action_type == SET)
|| (state == POST_CTRL_TO_PARAMS && ctx->action_type == GET)) {
/*
* We're translating from ctrl to params and setting the OID name,
* or we're translating from params to ctrl and getting the OID
* name. Either way, default_fixup_args() has placed the OID name
* in |ctx->p2|, all we need to do now is to replace that with the
* corresponding ASN1_OBJECT.
*/
ctx->p2 = (ASN1_OBJECT *)OBJ_txt2obj(ctx->p2, 0);
}
return ret;
}
/* EVP_PKEY_CTRL_DH_NID */
static int fix_dh_nid(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
/* This is only settable */
if (ctx->action_type != SET)
return 0;
if (state == PRE_CTRL_TO_PARAMS) {
if ((ctx->p2 = (char *)ossl_ffc_named_group_get_name
(ossl_ffc_uid_to_dh_named_group(ctx->p1))) == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
return 0;
}
ctx->p1 = 0;
}
return default_fixup_args(state, translation, ctx);
}
/* EVP_PKEY_CTRL_DH_RFC5114 */
static int fix_dh_nid5114(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
/* This is only settable */
if (ctx->action_type != SET)
return 0;
switch (state) {
case PRE_CTRL_TO_PARAMS:
if ((ctx->p2 = (char *)ossl_ffc_named_group_get_name
(ossl_ffc_uid_to_dh_named_group(ctx->p1))) == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
return 0;
}
ctx->p1 = 0;
break;
case PRE_CTRL_STR_TO_PARAMS:
if (ctx->p2 == NULL)
return 0;
if ((ctx->p2 = (char *)ossl_ffc_named_group_get_name
(ossl_ffc_uid_to_dh_named_group(atoi(ctx->p2)))) == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
return 0;
}
ctx->p1 = 0;
break;
default:
break;
}
return default_fixup_args(state, translation, ctx);
}
/* EVP_PKEY_CTRL_DH_PARAMGEN_TYPE */
static int fix_dh_paramgen_type(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
/* This is only settable */
if (ctx->action_type != SET)
return 0;
if (state == PRE_CTRL_STR_TO_PARAMS) {
if ((ctx->p2 = (char *)ossl_dh_gen_type_id2name(atoi(ctx->p2)))
== NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
return 0;
}
ctx->p1 = strlen(ctx->p2);
}
return default_fixup_args(state, translation, ctx);
}
/* EVP_PKEY_CTRL_EC_PARAM_ENC */
static int fix_ec_param_enc(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
/* This is currently only settable */
if (ctx->action_type != SET)
return 0;
if (state == PRE_CTRL_TO_PARAMS) {
switch (ctx->p1) {
case OPENSSL_EC_EXPLICIT_CURVE:
ctx->p2 = OSSL_PKEY_EC_ENCODING_EXPLICIT;
break;
case OPENSSL_EC_NAMED_CURVE:
ctx->p2 = OSSL_PKEY_EC_ENCODING_GROUP;
break;
default:
ret = -2;
goto end;
}
ctx->p1 = 0;
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if (state == PRE_PARAMS_TO_CTRL) {
if (strcmp(ctx->p2, OSSL_PKEY_EC_ENCODING_EXPLICIT) == 0)
ctx->p1 = OPENSSL_EC_EXPLICIT_CURVE;
else if (strcmp(ctx->p2, OSSL_PKEY_EC_ENCODING_GROUP) == 0)
ctx->p1 = OPENSSL_EC_NAMED_CURVE;
else
ctx->p1 = ret = -2;
ctx->p2 = NULL;
}
end:
if (ret == -2)
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
/* EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID */
static int fix_ec_paramgen_curve_nid(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
char *p2 = NULL;
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
/* This is currently only settable */
if (ctx->action_type != SET)
return 0;
if (state == PRE_CTRL_TO_PARAMS) {
ctx->p2 = (char *)OBJ_nid2sn(ctx->p1);
ctx->p1 = 0;
} else if (state == PRE_PARAMS_TO_CTRL) {
/*
* We're translating from params to ctrl and setting the curve name.
* The ctrl function needs it to be a NID, but meanwhile, we need
* space to get the curve name from the param. |ctx->name_buf| is
* sufficient for that.
* The double indirection is necessary for default_fixup_args()'s
* call of OSSL_PARAM_get_utf8_string() to be done correctly.
*/
p2 = ctx->name_buf;
ctx->p2 = &p2;
ctx->sz = sizeof(ctx->name_buf);
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if (state == PRE_PARAMS_TO_CTRL) {
ctx->p1 = OBJ_sn2nid(p2);
ctx->p2 = NULL;
}
return ret;
}
/* EVP_PKEY_CTRL_EC_ECDH_COFACTOR */
static int fix_ecdh_cofactor(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
/*
* The EVP_PKEY_CTRL_EC_ECDH_COFACTOR ctrl command is a bit special, in
* that it's used both for setting a value, and for getting it, all
* depending on the value if |ctx->p1|; if |ctx->p1| is -2, the backend is
* supposed to place the current cofactor mode in |ctx->p2|, and if not,
* |ctx->p1| is interpreted as the new cofactor mode.
*/
int ret = 0;
if (state == PRE_CTRL_TO_PARAMS) {
/*
* The initial value for |ctx->action_type| must be zero.
* evp_pkey_ctrl_to_params() takes it from the translation item.
*/
if (!ossl_assert(ctx->action_type == NONE))
return 0;
/* The action type depends on the value of ctx->p1 */
if (ctx->p1 == -2)
ctx->action_type = GET;
else
ctx->action_type = SET;
} else if (state == PRE_CTRL_STR_TO_PARAMS) {
ctx->action_type = SET;
} else if (state == PRE_PARAMS_TO_CTRL) {
/* The initial value for |ctx->action_type| must not be zero. */
if (!ossl_assert(ctx->action_type != NONE))
return 0;
+ } else if (state == POST_PARAMS_TO_CTRL && ctx->action_type == NONE) {
+ ctx->action_type = GET;
}
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET) {
if (ctx->p1 < -1 || ctx->p1 > 1) {
/* Uses the same return value of pkey_ec_ctrl() */
return -2;
}
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if (state == POST_CTRL_TO_PARAMS && ctx->action_type == GET) {
if (ctx->p1 < 0 || ctx->p1 > 1) {
/*
* The provider should return either 0 or 1, any other value is a
* provider error.
*/
ctx->p1 = ret = -1;
}
} else if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == GET) {
ctx->p1 = -2;
+ } else if (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET) {
+ ctx->p1 = ret;
}
return ret;
}
/* EVP_PKEY_CTRL_RSA_PADDING, EVP_PKEY_CTRL_GET_RSA_PADDING */
static int fix_rsa_padding_mode(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
static const OSSL_ITEM str_value_map[] = {
{ RSA_PKCS1_PADDING, "pkcs1" },
{ RSA_NO_PADDING, "none" },
{ RSA_PKCS1_OAEP_PADDING, "oaep" },
{ RSA_PKCS1_OAEP_PADDING, "oeap" },
{ RSA_X931_PADDING, "x931" },
{ RSA_PKCS1_PSS_PADDING, "pss" },
/* Special case, will pass directly as an integer */
{ RSA_PKCS1_WITH_TLS_PADDING, NULL }
};
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == GET) {
/*
* EVP_PKEY_CTRL_GET_RSA_PADDING returns the padding mode in the
* weirdest way for a ctrl. Instead of doing like all other ctrls
* that return a simple, i.e. just have that as a return value,
* this particular ctrl treats p2 as the address for the int to be
* returned. We must therefore remember |ctx->p2|, then make
* |ctx->p2| point at a buffer to be filled in with the name, and
* |ctx->p1| with its size. default_fixup_args() will take care
* of the rest for us, along with the POST_CTRL_TO_PARAMS && GET
* code section further down.
*/
ctx->orig_p2 = ctx->p2;
ctx->p2 = ctx->name_buf;
ctx->p1 = sizeof(ctx->name_buf);
} else if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET) {
/*
* Ideally, we should use utf8 strings for the diverse padding modes.
* We only came here because someone called EVP_PKEY_CTX_ctrl(),
* though, and since that can reasonably be seen as legacy code
* that uses the diverse RSA macros for the padding mode, and we
* know that at least our providers can handle the numeric modes,
* we take the cheap route for now.
*
* The other solution would be to match |ctx->p1| against entries
* in str_value_map and pass the corresponding string. However,
* since we don't have a string for RSA_PKCS1_WITH_TLS_PADDING,
* we have to do this same hack at least for that one.
*
* Since the "official" data type for the RSA padding mode is utf8
* string, we cannot count on default_fixup_args(). Instead, we
* build the OSSL_PARAM item ourselves and return immediately.
*/
ctx->params[0] = OSSL_PARAM_construct_int(translation->param_key,
&ctx->p1);
return 1;
} else if (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET) {
size_t i;
/*
* The EVP_PKEY_CTX_get_params() caller may have asked for a utf8
* string, or may have asked for an integer of some sort. If they
* ask for an integer, we respond directly. If not, we translate
* the response from the ctrl function into a string.
*/
switch (ctx->params->data_type) {
case OSSL_PARAM_INTEGER:
return OSSL_PARAM_get_int(ctx->params, &ctx->p1);
case OSSL_PARAM_UNSIGNED_INTEGER:
return OSSL_PARAM_get_uint(ctx->params, (unsigned int *)&ctx->p1);
default:
break;
}
for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
if (ctx->p1 == (int)str_value_map[i].id)
break;
}
if (i == OSSL_NELEM(str_value_map)) {
ERR_raise_data(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE,
"[action:%d, state:%d] padding number %d",
ctx->action_type, state, ctx->p1);
return -2;
}
/*
* If we don't have a string, we can't do anything. The caller
* should have asked for a number...
*/
if (str_value_map[i].ptr == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
ctx->p2 = str_value_map[i].ptr;
ctx->p1 = strlen(ctx->p2);
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if ((ctx->action_type == SET && state == PRE_PARAMS_TO_CTRL)
|| (ctx->action_type == GET && state == POST_CTRL_TO_PARAMS)) {
size_t i;
for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
if (strcmp(ctx->p2, str_value_map[i].ptr) == 0)
break;
}
if (i == OSSL_NELEM(str_value_map)) {
ERR_raise_data(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE,
"[action:%d, state:%d] padding name %s",
ctx->action_type, state, ctx->p1);
ctx->p1 = ret = -2;
} else if (state == POST_CTRL_TO_PARAMS) {
/* EVP_PKEY_CTRL_GET_RSA_PADDING weirdness explained further up */
*(int *)ctx->orig_p2 = str_value_map[i].id;
} else {
ctx->p1 = str_value_map[i].id;
}
ctx->p2 = NULL;
}
return ret;
}
/* EVP_PKEY_CTRL_RSA_PSS_SALTLEN, EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN */
static int fix_rsa_pss_saltlen(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
static const OSSL_ITEM str_value_map[] = {
{ (unsigned int)RSA_PSS_SALTLEN_DIGEST, "digest" },
{ (unsigned int)RSA_PSS_SALTLEN_MAX, "max" },
{ (unsigned int)RSA_PSS_SALTLEN_AUTO, "auto" }
};
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == GET) {
/*
* EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN returns the saltlen by filling
* in the int pointed at by p2. This is potentially as weird as
* the way EVP_PKEY_CTRL_GET_RSA_PADDING works, except that saltlen
* might be a negative value, so it wouldn't work as a legitimate
* return value.
* In any case, we must therefore remember |ctx->p2|, then make
* |ctx->p2| point at a buffer to be filled in with the name, and
* |ctx->p1| with its size. default_fixup_args() will take care
* of the rest for us, along with the POST_CTRL_TO_PARAMS && GET
* code section further down.
*/
ctx->orig_p2 = ctx->p2;
ctx->p2 = ctx->name_buf;
ctx->p1 = sizeof(ctx->name_buf);
} else if ((ctx->action_type == SET && state == PRE_CTRL_TO_PARAMS)
|| (ctx->action_type == GET && state == POST_PARAMS_TO_CTRL)) {
size_t i;
for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
if (ctx->p1 == (int)str_value_map[i].id)
break;
}
if (i == OSSL_NELEM(str_value_map)) {
BIO_snprintf(ctx->name_buf, sizeof(ctx->name_buf), "%d", ctx->p1);
} else {
/* This won't truncate but it will quiet static analysers */
strncpy(ctx->name_buf, str_value_map[i].ptr, sizeof(ctx->name_buf) - 1);
ctx->name_buf[sizeof(ctx->name_buf) - 1] = '\0';
}
ctx->p2 = ctx->name_buf;
ctx->p1 = strlen(ctx->p2);
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if ((ctx->action_type == SET && state == PRE_PARAMS_TO_CTRL)
|| (ctx->action_type == GET && state == POST_CTRL_TO_PARAMS)) {
size_t i;
int val;
for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
if (strcmp(ctx->p2, str_value_map[i].ptr) == 0)
break;
}
val = i == OSSL_NELEM(str_value_map) ? atoi(ctx->p2)
: (int)str_value_map[i].id;
if (state == POST_CTRL_TO_PARAMS) {
/*
* EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN weirdness explained further
* up
*/
*(int *)ctx->orig_p2 = val;
} else {
ctx->p1 = val;
}
ctx->p2 = NULL;
}
return ret;
}
/* EVP_PKEY_CTRL_HKDF_MODE */
static int fix_hkdf_mode(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
static const OSSL_ITEM str_value_map[] = {
{ EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND, "EXTRACT_AND_EXPAND" },
{ EVP_KDF_HKDF_MODE_EXTRACT_ONLY, "EXTRACT_ONLY" },
{ EVP_KDF_HKDF_MODE_EXPAND_ONLY, "EXPAND_ONLY" }
};
int ret;
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
if ((ctx->action_type == SET && state == PRE_CTRL_TO_PARAMS)
|| (ctx->action_type == GET && state == POST_PARAMS_TO_CTRL)) {
size_t i;
for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
if (ctx->p1 == (int)str_value_map[i].id)
break;
}
if (i == OSSL_NELEM(str_value_map))
return 0;
ctx->p2 = str_value_map[i].ptr;
ctx->p1 = strlen(ctx->p2);
}
if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
return ret;
if ((ctx->action_type == SET && state == PRE_PARAMS_TO_CTRL)
|| (ctx->action_type == GET && state == POST_CTRL_TO_PARAMS)) {
size_t i;
for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
if (strcmp(ctx->p2, str_value_map[i].ptr) == 0)
break;
}
if (i == OSSL_NELEM(str_value_map))
return 0;
if (state == POST_CTRL_TO_PARAMS)
ret = str_value_map[i].id;
else
ctx->p1 = str_value_map[i].id;
ctx->p2 = NULL;
}
return 1;
}
/*-
* Payload getters
* ===============
*
* These all get the data they want, then call default_fixup_args() as
* a post-ctrl GET fixup. They all get NULL ctx, ctrl_cmd, ctrl_str,
* p1, sz
*/
/* Pilfering DH, DSA and EC_KEY */
static int get_payload_group_name(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
EVP_PKEY *pkey = ctx->p2;
ctx->p2 = NULL;
switch (EVP_PKEY_get_base_id(pkey)) {
#ifndef OPENSSL_NO_DH
case EVP_PKEY_DH:
{
const DH *dh = EVP_PKEY_get0_DH(pkey);
int uid = DH_get_nid(dh);
if (uid != NID_undef) {
const DH_NAMED_GROUP *dh_group =
ossl_ffc_uid_to_dh_named_group(uid);
ctx->p2 = (char *)ossl_ffc_named_group_get_name(dh_group);
}
}
break;
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
{
const EC_GROUP *grp =
EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey));
int nid = NID_undef;
if (grp != NULL)
nid = EC_GROUP_get_curve_name(grp);
if (nid != NID_undef)
ctx->p2 = (char *)OSSL_EC_curve_nid2name(nid);
}
break;
#endif
default:
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
return 0;
}
/*
* Quietly ignoring unknown groups matches the behaviour on the provider
* side.
*/
if (ctx->p2 == NULL)
return 1;
ctx->p1 = strlen(ctx->p2);
return default_fixup_args(state, translation, ctx);
}
static int get_payload_private_key(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
EVP_PKEY *pkey = ctx->p2;
ctx->p2 = NULL;
if (ctx->params->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
return 0;
switch (EVP_PKEY_get_base_id(pkey)) {
#ifndef OPENSSL_NO_DH
case EVP_PKEY_DH:
{
const DH *dh = EVP_PKEY_get0_DH(pkey);
ctx->p2 = (BIGNUM *)DH_get0_priv_key(dh);
}
break;
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
{
const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
ctx->p2 = (BIGNUM *)EC_KEY_get0_private_key(ec);
}
break;
#endif
default:
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
return 0;
}
return default_fixup_args(state, translation, ctx);
}
static int get_payload_public_key(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
EVP_PKEY *pkey = ctx->p2;
unsigned char *buf = NULL;
int ret;
ctx->p2 = NULL;
switch (EVP_PKEY_get_base_id(pkey)) {
#ifndef OPENSSL_NO_DH
case EVP_PKEY_DHX:
case EVP_PKEY_DH:
switch (ctx->params->data_type) {
case OSSL_PARAM_OCTET_STRING:
ctx->sz = ossl_dh_key2buf(EVP_PKEY_get0_DH(pkey), &buf, 0, 1);
ctx->p2 = buf;
break;
case OSSL_PARAM_UNSIGNED_INTEGER:
ctx->p2 = (void *)DH_get0_pub_key(EVP_PKEY_get0_DH(pkey));
break;
default:
return 0;
}
break;
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
if (ctx->params->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
ctx->p2 = (void *)DSA_get0_pub_key(EVP_PKEY_get0_DSA(pkey));
break;
}
return 0;
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
if (ctx->params->data_type == OSSL_PARAM_OCTET_STRING) {
const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
BN_CTX *bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey));
const EC_GROUP *ecg = EC_KEY_get0_group(eckey);
const EC_POINT *point = EC_KEY_get0_public_key(eckey);
if (bnctx == NULL)
return 0;
ctx->sz = EC_POINT_point2buf(ecg, point,
POINT_CONVERSION_COMPRESSED,
&buf, bnctx);
ctx->p2 = buf;
BN_CTX_free(bnctx);
break;
}
return 0;
#endif
default:
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
return 0;
}
ret = default_fixup_args(state, translation, ctx);
OPENSSL_free(buf);
return ret;
}
static int get_payload_bn(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx, const BIGNUM *bn)
{
if (bn == NULL)
return 0;
if (ctx->params->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
return 0;
ctx->p2 = (BIGNUM *)bn;
return default_fixup_args(state, translation, ctx);
}
static int get_dh_dsa_payload_p(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
const BIGNUM *bn = NULL;
EVP_PKEY *pkey = ctx->p2;
switch (EVP_PKEY_get_base_id(pkey)) {
#ifndef OPENSSL_NO_DH
case EVP_PKEY_DH:
bn = DH_get0_p(EVP_PKEY_get0_DH(pkey));
break;
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
bn = DSA_get0_p(EVP_PKEY_get0_DSA(pkey));
break;
#endif
default:
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
}
return get_payload_bn(state, translation, ctx, bn);
}
static int get_dh_dsa_payload_q(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
const BIGNUM *bn = NULL;
switch (EVP_PKEY_get_base_id(ctx->p2)) {
#ifndef OPENSSL_NO_DH
case EVP_PKEY_DH:
bn = DH_get0_q(EVP_PKEY_get0_DH(ctx->p2));
break;
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
bn = DSA_get0_q(EVP_PKEY_get0_DSA(ctx->p2));
break;
#endif
}
return get_payload_bn(state, translation, ctx, bn);
}
static int get_dh_dsa_payload_g(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
const BIGNUM *bn = NULL;
switch (EVP_PKEY_get_base_id(ctx->p2)) {
#ifndef OPENSSL_NO_DH
case EVP_PKEY_DH:
bn = DH_get0_g(EVP_PKEY_get0_DH(ctx->p2));
break;
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
bn = DSA_get0_g(EVP_PKEY_get0_DSA(ctx->p2));
break;
#endif
}
return get_payload_bn(state, translation, ctx, bn);
}
static int get_payload_int(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx,
const int val)
{
if (ctx->params->data_type != OSSL_PARAM_INTEGER)
return 0;
ctx->p1 = val;
ctx->p2 = NULL;
return default_fixup_args(state, translation, ctx);
}
static int get_ec_decoded_from_explicit_params(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
int val = 0;
EVP_PKEY *pkey = ctx->p2;
switch (EVP_PKEY_base_id(pkey)) {
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
val = EC_KEY_decoded_from_explicit_params(EVP_PKEY_get0_EC_KEY(pkey));
if (val < 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
return 0;
}
break;
#endif
default:
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
return 0;
}
return get_payload_int(state, translation, ctx, val);
}
static int get_rsa_payload_n(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
const BIGNUM *bn = NULL;
if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA
&& EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
return 0;
bn = RSA_get0_n(EVP_PKEY_get0_RSA(ctx->p2));
return get_payload_bn(state, translation, ctx, bn);
}
static int get_rsa_payload_e(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
const BIGNUM *bn = NULL;
if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA
&& EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
return 0;
bn = RSA_get0_e(EVP_PKEY_get0_RSA(ctx->p2));
return get_payload_bn(state, translation, ctx, bn);
}
static int get_rsa_payload_d(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
const BIGNUM *bn = NULL;
if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA
&& EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
return 0;
bn = RSA_get0_d(EVP_PKEY_get0_RSA(ctx->p2));
return get_payload_bn(state, translation, ctx, bn);
}
static int get_rsa_payload_factor(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx,
size_t factornum)
{
const RSA *r = EVP_PKEY_get0_RSA(ctx->p2);
const BIGNUM *bn = NULL;
switch (factornum) {
case 0:
bn = RSA_get0_p(r);
break;
case 1:
bn = RSA_get0_q(r);
break;
default:
{
size_t pnum = RSA_get_multi_prime_extra_count(r);
const BIGNUM *factors[10];
if (factornum - 2 < pnum
&& RSA_get0_multi_prime_factors(r, factors))
bn = factors[factornum - 2];
}
break;
}
return get_payload_bn(state, translation, ctx, bn);
}
static int get_rsa_payload_exponent(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx,
size_t exponentnum)
{
const RSA *r = EVP_PKEY_get0_RSA(ctx->p2);
const BIGNUM *bn = NULL;
switch (exponentnum) {
case 0:
bn = RSA_get0_dmp1(r);
break;
case 1:
bn = RSA_get0_dmq1(r);
break;
default:
{
size_t pnum = RSA_get_multi_prime_extra_count(r);
const BIGNUM *exps[10], *coeffs[10];
if (exponentnum - 2 < pnum
&& RSA_get0_multi_prime_crt_params(r, exps, coeffs))
bn = exps[exponentnum - 2];
}
break;
}
return get_payload_bn(state, translation, ctx, bn);
}
static int get_rsa_payload_coefficient(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx,
size_t coefficientnum)
{
const RSA *r = EVP_PKEY_get0_RSA(ctx->p2);
const BIGNUM *bn = NULL;
switch (coefficientnum) {
case 0:
bn = RSA_get0_iqmp(r);
break;
default:
{
size_t pnum = RSA_get_multi_prime_extra_count(r);
const BIGNUM *exps[10], *coeffs[10];
if (coefficientnum - 1 < pnum
&& RSA_get0_multi_prime_crt_params(r, exps, coeffs))
bn = coeffs[coefficientnum - 1];
}
break;
}
return get_payload_bn(state, translation, ctx, bn);
}
#define IMPL_GET_RSA_PAYLOAD_FACTOR(n) \
static int \
get_rsa_payload_f##n(enum state state, \
const struct translation_st *translation, \
struct translation_ctx_st *ctx) \
{ \
if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA \
&& EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS) \
return 0; \
return get_rsa_payload_factor(state, translation, ctx, n - 1); \
}
#define IMPL_GET_RSA_PAYLOAD_EXPONENT(n) \
static int \
get_rsa_payload_e##n(enum state state, \
const struct translation_st *translation, \
struct translation_ctx_st *ctx) \
{ \
if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA \
&& EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS) \
return 0; \
return get_rsa_payload_exponent(state, translation, ctx, \
n - 1); \
}
#define IMPL_GET_RSA_PAYLOAD_COEFFICIENT(n) \
static int \
get_rsa_payload_c##n(enum state state, \
const struct translation_st *translation, \
struct translation_ctx_st *ctx) \
{ \
if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA \
&& EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS) \
return 0; \
return get_rsa_payload_coefficient(state, translation, ctx, \
n - 1); \
}
IMPL_GET_RSA_PAYLOAD_FACTOR(1)
IMPL_GET_RSA_PAYLOAD_FACTOR(2)
IMPL_GET_RSA_PAYLOAD_FACTOR(3)
IMPL_GET_RSA_PAYLOAD_FACTOR(4)
IMPL_GET_RSA_PAYLOAD_FACTOR(5)
IMPL_GET_RSA_PAYLOAD_FACTOR(6)
IMPL_GET_RSA_PAYLOAD_FACTOR(7)
IMPL_GET_RSA_PAYLOAD_FACTOR(8)
IMPL_GET_RSA_PAYLOAD_FACTOR(9)
IMPL_GET_RSA_PAYLOAD_FACTOR(10)
IMPL_GET_RSA_PAYLOAD_EXPONENT(1)
IMPL_GET_RSA_PAYLOAD_EXPONENT(2)
IMPL_GET_RSA_PAYLOAD_EXPONENT(3)
IMPL_GET_RSA_PAYLOAD_EXPONENT(4)
IMPL_GET_RSA_PAYLOAD_EXPONENT(5)
IMPL_GET_RSA_PAYLOAD_EXPONENT(6)
IMPL_GET_RSA_PAYLOAD_EXPONENT(7)
IMPL_GET_RSA_PAYLOAD_EXPONENT(8)
IMPL_GET_RSA_PAYLOAD_EXPONENT(9)
IMPL_GET_RSA_PAYLOAD_EXPONENT(10)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(1)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(2)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(3)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(4)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(5)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(6)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(7)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(8)
IMPL_GET_RSA_PAYLOAD_COEFFICIENT(9)
static int fix_group_ecx(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{
const char *value = NULL;
switch (state) {
case PRE_PARAMS_TO_CTRL:
if (!EVP_PKEY_CTX_IS_GEN_OP(ctx->pctx))
return 0;
ctx->action_type = NONE;
return 1;
case POST_PARAMS_TO_CTRL:
if (OSSL_PARAM_get_utf8_string_ptr(ctx->params, &value) == 0 ||
OPENSSL_strcasecmp(ctx->pctx->keytype, value) != 0) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
ctx->p1 = 0;
return 0;
}
ctx->p1 = 1;
return 1;
default:
return 0;
}
}
/*-
* The translation table itself
* ============================
*/
static const struct translation_st evp_pkey_ctx_translations[] = {
/*
* DistID: we pass it to the backend as an octet string,
* but get it back as a pointer to an octet string.
*
* Note that the EVP_PKEY_CTRL_GET1_ID_LEN is purely for legacy purposes
* that has no separate counterpart in OSSL_PARAM terms, since we get
* the length of the DistID automatically when getting the DistID itself.
*/
{ SET, -1, -1, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_SET1_ID, "distid", "hexdistid",
OSSL_PKEY_PARAM_DIST_ID, OSSL_PARAM_OCTET_STRING, NULL },
{ GET, -1, -1, -1,
EVP_PKEY_CTRL_GET1_ID, "distid", "hexdistid",
OSSL_PKEY_PARAM_DIST_ID, OSSL_PARAM_OCTET_PTR, NULL },
{ GET, -1, -1, -1,
EVP_PKEY_CTRL_GET1_ID_LEN, NULL, NULL,
OSSL_PKEY_PARAM_DIST_ID, OSSL_PARAM_OCTET_PTR, fix_distid_len },
/*-
* DH & DHX
* ========
*/
/*
* EVP_PKEY_CTRL_DH_KDF_TYPE is used both for setting and getting. The
* fixup function has to handle this...
*/
{ NONE, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_DH_KDF_TYPE, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_TYPE, OSSL_PARAM_UTF8_STRING,
fix_dh_kdf_type },
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_DH_KDF_MD, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ GET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_DH_KDF_MD, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_DH_KDF_OUTLEN, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ GET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_DH_KDF_UKM, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_STRING, NULL },
{ GET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_DH_KDF_UKM, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL },
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_DH_KDF_OID, NULL, NULL,
OSSL_KDF_PARAM_CEK_ALG, OSSL_PARAM_UTF8_STRING, fix_oid },
{ GET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_DH_KDF_OID, NULL, NULL,
OSSL_KDF_PARAM_CEK_ALG, OSSL_PARAM_UTF8_STRING, fix_oid },
/* DHX Keygen Parameters that are shared with DH */
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, "dh_paramgen_type", NULL,
OSSL_PKEY_PARAM_FFC_TYPE, OSSL_PARAM_UTF8_STRING, fix_dh_paramgen_type },
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, "dh_paramgen_prime_len", NULL,
OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_DH_NID, "dh_param", NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, NULL },
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_DH_RFC5114, "dh_rfc5114", NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid5114 },
/* DH Keygen Parameters that are shared with DHX */
{ SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, "dh_paramgen_type", NULL,
OSSL_PKEY_PARAM_FFC_TYPE, OSSL_PARAM_UTF8_STRING, fix_dh_paramgen_type },
{ SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, "dh_paramgen_prime_len", NULL,
OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_DH_NID, "dh_param", NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid },
{ SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_DH_RFC5114, "dh_rfc5114", NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid5114 },
/* DH specific Keygen Parameters */
{ SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, "dh_paramgen_generator", NULL,
OSSL_PKEY_PARAM_DH_GENERATOR, OSSL_PARAM_INTEGER, NULL },
/* DHX specific Keygen Parameters */
{ SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, "dh_paramgen_subprime_len", NULL,
OSSL_PKEY_PARAM_FFC_QBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_DH_PAD, "dh_pad", NULL,
OSSL_EXCHANGE_PARAM_PAD, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
/*-
* DSA
* ===
*/
{ SET, EVP_PKEY_DSA, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, "dsa_paramgen_bits", NULL,
OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_DSA, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, "dsa_paramgen_q_bits", NULL,
OSSL_PKEY_PARAM_FFC_QBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_DSA, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_MD, "dsa_paramgen_md", NULL,
OSSL_PKEY_PARAM_FFC_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
/*-
* EC
* ==
*/
{ SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_EC_PARAM_ENC, "ec_param_enc", NULL,
OSSL_PKEY_PARAM_EC_ENCODING, OSSL_PARAM_UTF8_STRING, fix_ec_param_enc },
{ SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, "ec_paramgen_curve", NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING,
fix_ec_paramgen_curve_nid },
/*
* EVP_PKEY_CTRL_EC_ECDH_COFACTOR and EVP_PKEY_CTRL_EC_KDF_TYPE are used
* both for setting and getting. The fixup function has to handle this...
*/
{ NONE, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_ECDH_COFACTOR, "ecdh_cofactor_mode", NULL,
OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, OSSL_PARAM_INTEGER,
fix_ecdh_cofactor },
{ NONE, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_TYPE, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_TYPE, OSSL_PARAM_UTF8_STRING, fix_ec_kdf_type },
{ SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_MD, "ecdh_kdf_md", NULL,
OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ GET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_EC_KDF_MD, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_OUTLEN, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ GET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_UKM, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_STRING, NULL },
{ GET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_EC_KDF_UKM, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL },
/*-
* SM2
* ==
*/
{ SET, EVP_PKEY_SM2, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_EC_PARAM_ENC, "ec_param_enc", NULL,
OSSL_PKEY_PARAM_EC_ENCODING, OSSL_PARAM_UTF8_STRING, fix_ec_param_enc },
{ SET, EVP_PKEY_SM2, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, "ec_paramgen_curve", NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING,
fix_ec_paramgen_curve_nid },
/*
* EVP_PKEY_CTRL_EC_ECDH_COFACTOR and EVP_PKEY_CTRL_EC_KDF_TYPE are used
* both for setting and getting. The fixup function has to handle this...
*/
{ NONE, EVP_PKEY_SM2, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_ECDH_COFACTOR, "ecdh_cofactor_mode", NULL,
OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, OSSL_PARAM_INTEGER,
fix_ecdh_cofactor },
{ NONE, EVP_PKEY_SM2, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_TYPE, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_TYPE, OSSL_PARAM_UTF8_STRING, fix_ec_kdf_type },
{ SET, EVP_PKEY_SM2, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_MD, "ecdh_kdf_md", NULL,
OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ GET, EVP_PKEY_SM2, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_EC_KDF_MD, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ SET, EVP_PKEY_SM2, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_OUTLEN, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ GET, EVP_PKEY_SM2, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_SM2, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_UKM, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_STRING, NULL },
{ GET, EVP_PKEY_SM2, 0, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_EC_KDF_UKM, NULL, NULL,
OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL },
/*-
* RSA
* ===
*/
/*
* RSA padding modes are numeric with ctrls, strings with ctrl_strs,
* and can be both with OSSL_PARAM. We standardise on strings here,
* fix_rsa_padding_mode() does the work when the caller has a different
* idea.
*/
{ SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS,
EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_RSA_PADDING, "rsa_padding_mode", NULL,
OSSL_PKEY_PARAM_PAD_MODE, OSSL_PARAM_UTF8_STRING, fix_rsa_padding_mode },
{ GET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS,
EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_GET_RSA_PADDING, NULL, NULL,
OSSL_PKEY_PARAM_PAD_MODE, OSSL_PARAM_UTF8_STRING, fix_rsa_padding_mode },
{ SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS,
EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_RSA_MGF1_MD, "rsa_mgf1_md", NULL,
OSSL_PKEY_PARAM_MGF1_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ GET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS,
EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_GET_RSA_MGF1_MD, NULL, NULL,
OSSL_PKEY_PARAM_MGF1_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
/*
* RSA-PSS saltlen is essentially numeric, but certain values can be
* expressed as keywords (strings) with ctrl_str. The corresponding
* OSSL_PARAM allows both forms.
* fix_rsa_pss_saltlen() takes care of the distinction.
*/
{ SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_RSA_PSS_SALTLEN, "rsa_pss_saltlen", NULL,
OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, OSSL_PARAM_UTF8_STRING,
fix_rsa_pss_saltlen },
{ GET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, NULL, NULL,
OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, OSSL_PARAM_UTF8_STRING,
fix_rsa_pss_saltlen },
{ SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_RSA_OAEP_MD, "rsa_oaep_md", NULL,
OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ GET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_GET_RSA_OAEP_MD, NULL, NULL,
OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
/*
* The "rsa_oaep_label" ctrl_str expects the value to always be hex.
* This is accomodated by default_fixup_args() above, which mimics that
* expectation for any translation item where |ctrl_str| is NULL and
* |ctrl_hexstr| is non-NULL.
*/
{ SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_RSA_OAEP_LABEL, NULL, "rsa_oaep_label",
OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_STRING, NULL },
{ GET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, NULL, NULL,
OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_PTR, NULL },
{ SET, EVP_PKEY_RSA_PSS, 0, EVP_PKEY_OP_TYPE_GEN,
EVP_PKEY_CTRL_MD, "rsa_pss_keygen_md", NULL,
OSSL_ALG_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ SET, EVP_PKEY_RSA_PSS, 0, EVP_PKEY_OP_TYPE_GEN,
EVP_PKEY_CTRL_RSA_MGF1_MD, "rsa_pss_keygen_mgf1_md", NULL,
OSSL_PKEY_PARAM_MGF1_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ SET, EVP_PKEY_RSA_PSS, 0, EVP_PKEY_OP_TYPE_GEN,
EVP_PKEY_CTRL_RSA_PSS_SALTLEN, "rsa_pss_keygen_saltlen", NULL,
OSSL_SIGNATURE_PARAM_PSS_SALTLEN, OSSL_PARAM_INTEGER, NULL },
{ SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_RSA_KEYGEN_BITS, "rsa_keygen_bits", NULL,
OSSL_PKEY_PARAM_RSA_BITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, "rsa_keygen_pubexp", NULL,
OSSL_PKEY_PARAM_RSA_E, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, "rsa_keygen_primes", NULL,
OSSL_PKEY_PARAM_RSA_PRIMES, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
/*-
* SipHash
* ======
*/
{ SET, -1, -1, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_SET_DIGEST_SIZE, "digestsize", NULL,
OSSL_MAC_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
/*-
* TLS1-PRF
* ========
*/
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_TLS_MD, "md", NULL,
OSSL_KDF_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_TLS_SECRET, "secret", "hexsecret",
OSSL_KDF_PARAM_SECRET, OSSL_PARAM_OCTET_STRING, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_TLS_SEED, "seed", "hexseed",
OSSL_KDF_PARAM_SEED, OSSL_PARAM_OCTET_STRING, NULL },
/*-
* HKDF
* ====
*/
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_MD, "md", NULL,
OSSL_KDF_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_SALT, "salt", "hexsalt",
OSSL_KDF_PARAM_SALT, OSSL_PARAM_OCTET_STRING, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_KEY, "key", "hexkey",
OSSL_KDF_PARAM_KEY, OSSL_PARAM_OCTET_STRING, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_INFO, "info", "hexinfo",
OSSL_KDF_PARAM_INFO, OSSL_PARAM_OCTET_STRING, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_MODE, "mode", NULL,
OSSL_KDF_PARAM_MODE, OSSL_PARAM_INTEGER, fix_hkdf_mode },
/*-
* Scrypt
* ======
*/
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_PASS, "pass", "hexpass",
OSSL_KDF_PARAM_PASSWORD, OSSL_PARAM_OCTET_STRING, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_SCRYPT_SALT, "salt", "hexsalt",
OSSL_KDF_PARAM_SALT, OSSL_PARAM_OCTET_STRING, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_SCRYPT_N, "N", NULL,
OSSL_KDF_PARAM_SCRYPT_N, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_SCRYPT_R, "r", NULL,
OSSL_KDF_PARAM_SCRYPT_R, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_SCRYPT_P, "p", NULL,
OSSL_KDF_PARAM_SCRYPT_P, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, -1, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, "maxmem_bytes", NULL,
OSSL_KDF_PARAM_SCRYPT_MAXMEM, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, -1, -1, EVP_PKEY_OP_KEYGEN | EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_CIPHER, NULL, NULL,
OSSL_PKEY_PARAM_CIPHER, OSSL_PARAM_UTF8_STRING, fix_cipher },
{ SET, -1, -1, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_SET_MAC_KEY, "key", "hexkey",
OSSL_PKEY_PARAM_PRIV_KEY, OSSL_PARAM_OCTET_STRING, NULL },
{ SET, -1, -1, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_MD, NULL, NULL,
OSSL_SIGNATURE_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
{ GET, -1, -1, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_GET_MD, NULL, NULL,
OSSL_SIGNATURE_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
/*-
* ECX
* ===
*/
{ SET, EVP_PKEY_X25519, EVP_PKEY_X25519, EVP_PKEY_OP_KEYGEN, -1, NULL, NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_group_ecx },
{ SET, EVP_PKEY_X25519, EVP_PKEY_X25519, EVP_PKEY_OP_PARAMGEN, -1, NULL, NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_group_ecx },
{ SET, EVP_PKEY_X448, EVP_PKEY_X448, EVP_PKEY_OP_KEYGEN, -1, NULL, NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_group_ecx },
{ SET, EVP_PKEY_X448, EVP_PKEY_X448, EVP_PKEY_OP_PARAMGEN, -1, NULL, NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_group_ecx },
};
static const struct translation_st evp_pkey_translations[] = {
/*
* The following contain no ctrls, they are exclusively here to extract
* key payloads from legacy keys, using OSSL_PARAMs, and rely entirely
* on |fixup_args| to pass the actual data. The |fixup_args| should
* expect to get the EVP_PKEY pointer through |ctx->p2|.
*/
/* DH, DSA & EC */
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING,
get_payload_group_name },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_PRIV_KEY, OSSL_PARAM_UNSIGNED_INTEGER,
get_payload_private_key },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_PUB_KEY,
0 /* no data type, let get_payload_public_key() handle that */,
get_payload_public_key },
/* DH and DSA */
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_FFC_P, OSSL_PARAM_UNSIGNED_INTEGER,
get_dh_dsa_payload_p },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_FFC_G, OSSL_PARAM_UNSIGNED_INTEGER,
get_dh_dsa_payload_g },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_FFC_Q, OSSL_PARAM_UNSIGNED_INTEGER,
get_dh_dsa_payload_q },
/* RSA */
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_N, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_n },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_E, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_D, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_d },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR1, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f1 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR2, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f2 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR3, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f3 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR4, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f4 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR5, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f5 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR6, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f6 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR7, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f7 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR8, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f8 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR9, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f9 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_FACTOR10, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_f10 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT1, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e1 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT2, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e2 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT3, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e3 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT4, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e4 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT5, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e5 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT6, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e6 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT7, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e7 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT8, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e8 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT9, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e9 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_EXPONENT10, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_e10 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT1, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c1 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT2, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c2 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT3, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c3 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT4, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c4 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT5, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c5 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT6, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c6 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT7, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c7 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT8, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c8 },
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_RSA_COEFFICIENT9, OSSL_PARAM_UNSIGNED_INTEGER,
get_rsa_payload_c9 },
/* EC */
{ GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, OSSL_PARAM_INTEGER,
get_ec_decoded_from_explicit_params },
};
static const struct translation_st *
lookup_translation(struct translation_st *tmpl,
const struct translation_st *translations,
size_t translations_num)
{
size_t i;
for (i = 0; i < translations_num; i++) {
const struct translation_st *item = &translations[i];
/*
* Sanity check the translation table item.
*
* 1. Either both keytypes are -1, or neither of them are.
* 2. TBA...
*/
if (!ossl_assert((item->keytype1 == -1) == (item->keytype2 == -1)))
continue;
/*
* Base search criteria: check that the optype and keytypes match,
* if relevant. All callers must synthesise these bits somehow.
*/
if (item->optype != -1 && (tmpl->optype & item->optype) == 0)
continue;
/*
* This expression is stunningly simple thanks to the sanity check
* above.
*/
if (item->keytype1 != -1
&& tmpl->keytype1 != item->keytype1
&& tmpl->keytype2 != item->keytype2)
continue;
/*
* Done with the base search criteria, now we check the criteria for
* the individual types of translations:
* ctrl->params, ctrl_str->params, and params->ctrl
*/
if (tmpl->ctrl_num != 0) {
if (tmpl->ctrl_num != item->ctrl_num)
continue;
} else if (tmpl->ctrl_str != NULL) {
const char *ctrl_str = NULL;
const char *ctrl_hexstr = NULL;
/*
* Search criteria that originates from a ctrl_str is only used
* for setting, never for getting. Therefore, we only look at
* the setter items.
*/
if (item->action_type != NONE
&& item->action_type != SET)
continue;
/*
* At least one of the ctrl cmd names must be match the ctrl
* cmd name in the template.
*/
if (item->ctrl_str != NULL
&& OPENSSL_strcasecmp(tmpl->ctrl_str, item->ctrl_str) == 0)
ctrl_str = tmpl->ctrl_str;
else if (item->ctrl_hexstr != NULL
&& OPENSSL_strcasecmp(tmpl->ctrl_hexstr,
item->ctrl_hexstr) == 0)
ctrl_hexstr = tmpl->ctrl_hexstr;
else
continue;
/* Modify the template to signal which string matched */
tmpl->ctrl_str = ctrl_str;
tmpl->ctrl_hexstr = ctrl_hexstr;
} else if (tmpl->param_key != NULL) {
/*
* Search criteria that originates from a OSSL_PARAM setter or
* getter.
*
* Ctrls were fundamentally bidirectional, with only the ctrl
* command macro name implying direction (if you're lucky).
* A few ctrl commands were even taking advantage of the
* bidirectional nature, making the direction depend in the
* value of the numeric argument.
*
* OSSL_PARAM functions are fundamentally different, in that
* setters and getters are separated, so the data direction is
* implied by the function that's used. The same OSSL_PARAM
* key name can therefore be used in both directions. We must
* therefore take the action type into account in this case.
*/
if ((item->action_type != NONE
&& tmpl->action_type != item->action_type)
|| (item->param_key != NULL
&& OPENSSL_strcasecmp(tmpl->param_key,
item->param_key) != 0))
continue;
} else {
return NULL;
}
return item;
}
return NULL;
}
static const struct translation_st *
lookup_evp_pkey_ctx_translation(struct translation_st *tmpl)
{
return lookup_translation(tmpl, evp_pkey_ctx_translations,
OSSL_NELEM(evp_pkey_ctx_translations));
}
static const struct translation_st *
lookup_evp_pkey_translation(struct translation_st *tmpl)
{
return lookup_translation(tmpl, evp_pkey_translations,
OSSL_NELEM(evp_pkey_translations));
}
/* This must ONLY be called for provider side operations */
int evp_pkey_ctx_ctrl_to_param(EVP_PKEY_CTX *pctx,
int keytype, int optype,
int cmd, int p1, void *p2)
{
struct translation_ctx_st ctx = { 0, };
struct translation_st tmpl = { 0, };
const struct translation_st *translation = NULL;
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
int ret;
fixup_args_fn *fixup = default_fixup_args;
if (keytype == -1)
keytype = pctx->legacy_keytype;
tmpl.ctrl_num = cmd;
tmpl.keytype1 = tmpl.keytype2 = keytype;
tmpl.optype = optype;
translation = lookup_evp_pkey_ctx_translation(&tmpl);
if (translation == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (pctx->pmeth != NULL
&& pctx->pmeth->pkey_id != translation->keytype1
&& pctx->pmeth->pkey_id != translation->keytype2)
return -1;
if (translation->fixup_args != NULL)
fixup = translation->fixup_args;
ctx.action_type = translation->action_type;
ctx.ctrl_cmd = cmd;
ctx.p1 = p1;
ctx.p2 = p2;
ctx.pctx = pctx;
ctx.params = params;
ret = fixup(PRE_CTRL_TO_PARAMS, translation, &ctx);
if (ret > 0) {
switch (ctx.action_type) {
default:
/* fixup_args is expected to make sure this is dead code */
break;
case GET:
ret = evp_pkey_ctx_get_params_strict(pctx, ctx.params);
break;
case SET:
ret = evp_pkey_ctx_set_params_strict(pctx, ctx.params);
break;
}
}
/*
* In POST, we pass the return value as p1, allowing the fixup_args
* function to affect it by changing its value.
*/
if (ret > 0) {
ctx.p1 = ret;
fixup(POST_CTRL_TO_PARAMS, translation, &ctx);
ret = ctx.p1;
}
cleanup_translation_ctx(POST_CTRL_TO_PARAMS, translation, &ctx);
return ret;
}
/* This must ONLY be called for provider side operations */
int evp_pkey_ctx_ctrl_str_to_param(EVP_PKEY_CTX *pctx,
const char *name, const char *value)
{
struct translation_ctx_st ctx = { 0, };
struct translation_st tmpl = { 0, };
const struct translation_st *translation = NULL;
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
int keytype = pctx->legacy_keytype;
int optype = pctx->operation == 0 ? -1 : pctx->operation;
int ret;
fixup_args_fn *fixup = default_fixup_args;
tmpl.action_type = SET;
tmpl.keytype1 = tmpl.keytype2 = keytype;
tmpl.optype = optype;
tmpl.ctrl_str = name;
tmpl.ctrl_hexstr = name;
translation = lookup_evp_pkey_ctx_translation(&tmpl);
if (translation != NULL) {
if (translation->fixup_args != NULL)
fixup = translation->fixup_args;
ctx.action_type = translation->action_type;
ctx.ishex = (tmpl.ctrl_hexstr != NULL);
} else {
/* String controls really only support setting */
ctx.action_type = SET;
}
ctx.ctrl_str = name;
ctx.p1 = (int)strlen(value);
ctx.p2 = (char *)value;
ctx.pctx = pctx;
ctx.params = params;
ret = fixup(PRE_CTRL_STR_TO_PARAMS, translation, &ctx);
if (ret > 0) {
switch (ctx.action_type) {
default:
/* fixup_args is expected to make sure this is dead code */
break;
case GET:
/*
* this is dead code, but must be present, or some compilers
* will complain
*/
break;
case SET:
ret = evp_pkey_ctx_set_params_strict(pctx, ctx.params);
break;
}
}
if (ret > 0)
ret = fixup(POST_CTRL_STR_TO_PARAMS, translation, &ctx);
cleanup_translation_ctx(CLEANUP_CTRL_STR_TO_PARAMS, translation, &ctx);
return ret;
}
/* This must ONLY be called for legacy operations */
static int evp_pkey_ctx_setget_params_to_ctrl(EVP_PKEY_CTX *pctx,
enum action action_type,
OSSL_PARAM *params)
{
int keytype = pctx->legacy_keytype;
int optype = pctx->operation == 0 ? -1 : pctx->operation;
for (; params != NULL && params->key != NULL; params++) {
struct translation_ctx_st ctx = { 0, };
struct translation_st tmpl = { 0, };
const struct translation_st *translation = NULL;
fixup_args_fn *fixup = default_fixup_args;
int ret;
ctx.action_type = tmpl.action_type = action_type;
tmpl.keytype1 = tmpl.keytype2 = keytype;
tmpl.optype = optype;
tmpl.param_key = params->key;
translation = lookup_evp_pkey_ctx_translation(&tmpl);
if (translation != NULL) {
if (translation->fixup_args != NULL)
fixup = translation->fixup_args;
ctx.ctrl_cmd = translation->ctrl_num;
}
ctx.pctx = pctx;
ctx.params = params;
ret = fixup(PRE_PARAMS_TO_CTRL, translation, &ctx);
if (ret > 0 && ctx.action_type != NONE)
ret = EVP_PKEY_CTX_ctrl(pctx, keytype, optype,
ctx.ctrl_cmd, ctx.p1, ctx.p2);
/*
* In POST, we pass the return value as p1, allowing the fixup_args
* function to put it to good use, or maybe affect it.
+ *
+ * NOTE: even though EVP_PKEY_CTX_ctrl return value is documented
+ * as return positive on Success and 0 or negative on falure. There
+ * maybe parameters (e.g. ecdh_cofactor), which actually return 0
+ * as success value. That is why we do POST_PARAMS_TO_CTRL for 0
+ * value as well
*/
- if (ret > 0) {
+ if (ret >= 0) {
ctx.p1 = ret;
fixup(POST_PARAMS_TO_CTRL, translation, &ctx);
ret = ctx.p1;
}
cleanup_translation_ctx(CLEANUP_PARAMS_TO_CTRL, translation, &ctx);
if (ret <= 0)
return 0;
}
return 1;
}
int evp_pkey_ctx_set_params_to_ctrl(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params)
{
return evp_pkey_ctx_setget_params_to_ctrl(ctx, SET, (OSSL_PARAM *)params);
}
int evp_pkey_ctx_get_params_to_ctrl(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
{
return evp_pkey_ctx_setget_params_to_ctrl(ctx, GET, params);
}
/* This must ONLY be called for legacy EVP_PKEYs */
static int evp_pkey_setget_params_to_ctrl(const EVP_PKEY *pkey,
enum action action_type,
OSSL_PARAM *params)
{
int ret = 1;
for (; params != NULL && params->key != NULL; params++) {
struct translation_ctx_st ctx = { 0, };
struct translation_st tmpl = { 0, };
const struct translation_st *translation = NULL;
fixup_args_fn *fixup = default_fixup_args;
tmpl.action_type = action_type;
tmpl.param_key = params->key;
translation = lookup_evp_pkey_translation(&tmpl);
if (translation != NULL) {
if (translation->fixup_args != NULL)
fixup = translation->fixup_args;
ctx.action_type = translation->action_type;
}
ctx.p2 = (void *)pkey;
ctx.params = params;
/*
* EVP_PKEY doesn't have any ctrl function, so we rely completely
* on fixup_args to do the whole work. Also, we currently only
* support getting.
*/
if (!ossl_assert(translation != NULL)
|| !ossl_assert(translation->action_type == GET)
|| !ossl_assert(translation->fixup_args != NULL)) {
return -2;
}
ret = fixup(PKEY, translation, &ctx);
cleanup_translation_ctx(PKEY, translation, &ctx);
}
return ret;
}
int evp_pkey_get_params_to_ctrl(const EVP_PKEY *pkey, OSSL_PARAM *params)
{
return evp_pkey_setget_params_to_ctrl(pkey, GET, params);
}
diff --git a/crypto/openssl/crypto/evp/m_sigver.c b/crypto/openssl/crypto/evp/m_sigver.c
index 76a6814b424b..efd2c05c85cf 100644
--- a/crypto/openssl/crypto/evp/m_sigver.c
+++ b/crypto/openssl/crypto/evp/m_sigver.c
@@ -1,683 +1,687 @@
/*
* Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/objects.h>
#include "crypto/evp.h"
#include "internal/provider.h"
#include "internal/numbers.h" /* includes SIZE_MAX */
#include "evp_local.h"
#ifndef FIPS_MODULE
static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen)
{
ERR_raise(ERR_LIB_EVP, EVP_R_ONLY_ONESHOT_SUPPORTED);
return 0;
}
/*
* If we get the "NULL" md then the name comes back as "UNDEF". We want to use
* NULL for this.
*/
static const char *canon_mdname(const char *mdname)
{
if (mdname != NULL && strcmp(mdname, "UNDEF") == 0)
return NULL;
return mdname;
}
static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, const char *mdname,
OSSL_LIB_CTX *libctx, const char *props,
ENGINE *e, EVP_PKEY *pkey, int ver,
const OSSL_PARAM params[])
{
EVP_PKEY_CTX *locpctx = NULL;
EVP_SIGNATURE *signature = NULL;
EVP_KEYMGMT *tmp_keymgmt = NULL;
const OSSL_PROVIDER *tmp_prov = NULL;
const char *supported_sig = NULL;
char locmdname[80] = ""; /* 80 chars should be enough */
void *provkey = NULL;
int ret, iter, reinit = 1;
if (ctx->algctx != NULL) {
if (!ossl_assert(ctx->digest != NULL)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
if (ctx->digest->freectx != NULL)
ctx->digest->freectx(ctx->algctx);
ctx->algctx = NULL;
}
if (ctx->pctx == NULL) {
reinit = 0;
if (e == NULL)
ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props);
else
ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
}
if (ctx->pctx == NULL)
return 0;
locpctx = ctx->pctx;
ERR_set_mark();
if (evp_pkey_ctx_is_legacy(locpctx))
goto legacy;
/* do not reinitialize if pkey is set or operation is different */
if (reinit
&& (pkey != NULL
|| locpctx->operation != (ver ? EVP_PKEY_OP_VERIFYCTX
: EVP_PKEY_OP_SIGNCTX)
|| (signature = locpctx->op.sig.signature) == NULL
|| locpctx->op.sig.algctx == NULL))
reinit = 0;
if (props == NULL)
props = locpctx->propquery;
if (locpctx->pkey == NULL) {
ERR_clear_last_mark();
ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
goto err;
}
if (!reinit) {
evp_pkey_ctx_free_old_ops(locpctx);
} else {
if (mdname == NULL && type == NULL)
mdname = canon_mdname(EVP_MD_get0_name(ctx->reqdigest));
goto reinitialize;
}
/*
* Try to derive the supported signature from |locpctx->keymgmt|.
*/
if (!ossl_assert(locpctx->pkey->keymgmt == NULL
|| locpctx->pkey->keymgmt == locpctx->keymgmt)) {
ERR_clear_last_mark();
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
goto err;
}
supported_sig = evp_keymgmt_util_query_operation_name(locpctx->keymgmt,
OSSL_OP_SIGNATURE);
if (supported_sig == NULL) {
ERR_clear_last_mark();
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
goto err;
}
/*
* We perform two iterations:
*
* 1. Do the normal signature fetch, using the fetching data given by
* the EVP_PKEY_CTX.
* 2. Do the provider specific signature fetch, from the same provider
* as |ctx->keymgmt|
*
* We then try to fetch the keymgmt from the same provider as the
* signature, and try to export |ctx->pkey| to that keymgmt (when
* this keymgmt happens to be the same as |ctx->keymgmt|, the export
* is a no-op, but we call it anyway to not complicate the code even
* more).
* If the export call succeeds (returns a non-NULL provider key pointer),
* we're done and can perform the operation itself. If not, we perform
* the second iteration, or jump to legacy.
*/
for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
/*
* If we're on the second iteration, free the results from the first.
* They are NULL on the first iteration, so no need to check what
* iteration we're on.
*/
EVP_SIGNATURE_free(signature);
EVP_KEYMGMT_free(tmp_keymgmt);
switch (iter) {
case 1:
signature = EVP_SIGNATURE_fetch(locpctx->libctx, supported_sig,
locpctx->propquery);
if (signature != NULL)
tmp_prov = EVP_SIGNATURE_get0_provider(signature);
break;
case 2:
tmp_prov = EVP_KEYMGMT_get0_provider(locpctx->keymgmt);
signature =
evp_signature_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
supported_sig, locpctx->propquery);
if (signature == NULL)
goto legacy;
break;
}
if (signature == NULL)
continue;
/*
* Ensure that the key is provided, either natively, or as a cached
* export. We start by fetching the keymgmt with the same name as
* |locpctx->pkey|, but from the provider of the signature method, using
* the same property query as when fetching the signature method.
* With the keymgmt we found (if we did), we try to export |locpctx->pkey|
* to it (evp_pkey_export_to_provider() is smart enough to only actually
* export it if |tmp_keymgmt| is different from |locpctx->pkey|'s keymgmt)
*/
tmp_keymgmt_tofree = tmp_keymgmt =
evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
EVP_KEYMGMT_get0_name(locpctx->keymgmt),
locpctx->propquery);
if (tmp_keymgmt != NULL)
provkey = evp_pkey_export_to_provider(locpctx->pkey, locpctx->libctx,
&tmp_keymgmt, locpctx->propquery);
if (tmp_keymgmt == NULL)
EVP_KEYMGMT_free(tmp_keymgmt_tofree);
}
if (provkey == NULL) {
EVP_SIGNATURE_free(signature);
ERR_clear_last_mark();
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
goto err;
}
ERR_pop_to_mark();
/* No more legacy from here down to legacy: */
locpctx->op.sig.signature = signature;
locpctx->operation = ver ? EVP_PKEY_OP_VERIFYCTX
: EVP_PKEY_OP_SIGNCTX;
locpctx->op.sig.algctx
= signature->newctx(ossl_provider_ctx(signature->prov), props);
if (locpctx->op.sig.algctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
goto err;
}
reinitialize:
if (pctx != NULL)
*pctx = locpctx;
if (type != NULL) {
ctx->reqdigest = type;
if (mdname == NULL)
mdname = canon_mdname(EVP_MD_get0_name(type));
} else {
if (mdname == NULL && !reinit) {
if (evp_keymgmt_util_get_deflt_digest_name(tmp_keymgmt, provkey,
locmdname,
sizeof(locmdname)) > 0) {
mdname = canon_mdname(locmdname);
}
}
if (mdname != NULL) {
/*
* We're about to get a new digest so clear anything associated with
* an old digest.
*/
evp_md_ctx_clear_digest(ctx, 1, 0);
/* legacy code support for engines */
ERR_set_mark();
/*
* This might be requested by a later call to EVP_MD_CTX_get0_md().
* In that case the "explicit fetch" rules apply for that
* function (as per man pages), i.e. the ref count is not updated
* so the EVP_MD should not be used beyound the lifetime of the
* EVP_MD_CTX.
*/
ctx->fetched_digest = EVP_MD_fetch(locpctx->libctx, mdname, props);
if (ctx->fetched_digest != NULL) {
ctx->digest = ctx->reqdigest = ctx->fetched_digest;
} else {
/* legacy engine support : remove the mark when this is deleted */
ctx->reqdigest = ctx->digest = EVP_get_digestbyname(mdname);
if (ctx->digest == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
goto err;
}
}
(void)ERR_pop_to_mark();
}
}
if (ver) {
if (signature->digest_verify_init == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
goto err;
}
ret = signature->digest_verify_init(locpctx->op.sig.algctx,
mdname, provkey, params);
} else {
if (signature->digest_sign_init == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
goto err;
}
ret = signature->digest_sign_init(locpctx->op.sig.algctx,
mdname, provkey, params);
}
/*
* If the operation was not a success and no digest was found, an error
* needs to be raised.
*/
if (ret > 0 || mdname != NULL)
goto end;
if (type == NULL) /* This check is redundant but clarifies matters */
ERR_raise(ERR_LIB_EVP, EVP_R_NO_DEFAULT_DIGEST);
err:
evp_pkey_ctx_free_old_ops(locpctx);
locpctx->operation = EVP_PKEY_OP_UNDEFINED;
EVP_KEYMGMT_free(tmp_keymgmt);
return 0;
legacy:
/*
* If we don't have the full support we need with provided methods,
* let's go see if legacy does.
*/
ERR_pop_to_mark();
EVP_KEYMGMT_free(tmp_keymgmt);
tmp_keymgmt = NULL;
if (type == NULL && mdname != NULL)
type = evp_get_digestbyname_ex(locpctx->libctx, mdname);
if (ctx->pctx->pmeth == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) {
if (type == NULL) {
int def_nid;
if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
type = EVP_get_digestbynid(def_nid);
}
if (type == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_NO_DEFAULT_DIGEST);
return 0;
}
}
if (ver) {
if (ctx->pctx->pmeth->verifyctx_init) {
if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <= 0)
return 0;
ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX;
} else if (ctx->pctx->pmeth->digestverify != 0) {
ctx->pctx->operation = EVP_PKEY_OP_VERIFY;
ctx->update = update;
} else if (EVP_PKEY_verify_init(ctx->pctx) <= 0) {
return 0;
}
} else {
if (ctx->pctx->pmeth->signctx_init) {
if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0)
return 0;
ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX;
} else if (ctx->pctx->pmeth->digestsign != 0) {
ctx->pctx->operation = EVP_PKEY_OP_SIGN;
ctx->update = update;
} else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) {
return 0;
}
}
if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0)
return 0;
if (pctx)
*pctx = ctx->pctx;
if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)
return 1;
if (!EVP_DigestInit_ex(ctx, type, e))
return 0;
/*
* This indicates the current algorithm requires
* special treatment before hashing the tbs-message.
*/
ctx->pctx->flag_call_digest_custom = 0;
if (ctx->pctx->pmeth->digest_custom != NULL)
ctx->pctx->flag_call_digest_custom = 1;
ret = 1;
end:
#ifndef FIPS_MODULE
if (ret > 0)
ret = evp_pkey_ctx_use_cached_data(locpctx);
#endif
EVP_KEYMGMT_free(tmp_keymgmt);
return ret > 0 ? 1 : 0;
}
int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const char *mdname, OSSL_LIB_CTX *libctx,
const char *props, EVP_PKEY *pkey,
const OSSL_PARAM params[])
{
return do_sigver_init(ctx, pctx, NULL, mdname, libctx, props, NULL, pkey, 0,
params);
}
int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
{
return do_sigver_init(ctx, pctx, type, NULL, NULL, NULL, e, pkey, 0,
NULL);
}
int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const char *mdname, OSSL_LIB_CTX *libctx,
const char *props, EVP_PKEY *pkey,
const OSSL_PARAM params[])
{
return do_sigver_init(ctx, pctx, NULL, mdname, libctx, props, NULL, pkey, 1,
params);
}
int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
{
return do_sigver_init(ctx, pctx, type, NULL, NULL, NULL, e, pkey, 1,
NULL);
}
#endif /* FIPS_MDOE */
int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
{
EVP_PKEY_CTX *pctx = ctx->pctx;
if (pctx == NULL
|| pctx->operation != EVP_PKEY_OP_SIGNCTX
|| pctx->op.sig.algctx == NULL
|| pctx->op.sig.signature == NULL)
goto legacy;
if (pctx->op.sig.signature->digest_sign_update == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return pctx->op.sig.signature->digest_sign_update(pctx->op.sig.algctx,
data, dsize);
legacy:
if (pctx != NULL) {
/* do_sigver_init() checked that |digest_custom| is non-NULL */
if (pctx->flag_call_digest_custom
&& !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
return 0;
pctx->flag_call_digest_custom = 0;
}
return EVP_DigestUpdate(ctx, data, dsize);
}
int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
{
EVP_PKEY_CTX *pctx = ctx->pctx;
if (pctx == NULL
|| pctx->operation != EVP_PKEY_OP_VERIFYCTX
|| pctx->op.sig.algctx == NULL
|| pctx->op.sig.signature == NULL)
goto legacy;
if (pctx->op.sig.signature->digest_verify_update == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return pctx->op.sig.signature->digest_verify_update(pctx->op.sig.algctx,
data, dsize);
legacy:
if (pctx != NULL) {
/* do_sigver_init() checked that |digest_custom| is non-NULL */
if (pctx->flag_call_digest_custom
&& !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
return 0;
pctx->flag_call_digest_custom = 0;
}
return EVP_DigestUpdate(ctx, data, dsize);
}
#ifndef FIPS_MODULE
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
size_t *siglen)
{
int sctx = 0, r = 0;
EVP_PKEY_CTX *dctx, *pctx = ctx->pctx;
if (pctx == NULL
|| pctx->operation != EVP_PKEY_OP_SIGNCTX
|| pctx->op.sig.algctx == NULL
|| pctx->op.sig.signature == NULL)
goto legacy;
if (sigret == NULL || (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0)
return pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx,
sigret, siglen,
sigret == NULL ? 0 : *siglen);
dctx = EVP_PKEY_CTX_dup(pctx);
if (dctx == NULL)
return 0;
r = dctx->op.sig.signature->digest_sign_final(dctx->op.sig.algctx,
sigret, siglen,
*siglen);
EVP_PKEY_CTX_free(dctx);
return r;
legacy:
if (pctx == NULL || pctx->pmeth == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
/* do_sigver_init() checked that |digest_custom| is non-NULL */
if (pctx->flag_call_digest_custom
&& !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
return 0;
pctx->flag_call_digest_custom = 0;
if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
if (sigret == NULL)
return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
else {
dctx = EVP_PKEY_CTX_dup(pctx);
if (dctx == NULL)
return 0;
r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
EVP_PKEY_CTX_free(dctx);
}
return r;
}
if (pctx->pmeth->signctx != NULL)
sctx = 1;
else
sctx = 0;
if (sigret != NULL) {
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen = 0;
if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
if (sctx)
r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
else
r = EVP_DigestFinal_ex(ctx, md, &mdlen);
} else {
EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
if (tmp_ctx == NULL)
return 0;
if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) {
EVP_MD_CTX_free(tmp_ctx);
return 0;
}
if (sctx)
r = tmp_ctx->pctx->pmeth->signctx(tmp_ctx->pctx,
sigret, siglen, tmp_ctx);
else
r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen);
EVP_MD_CTX_free(tmp_ctx);
}
if (sctx || !r)
return r;
if (EVP_PKEY_sign(pctx, sigret, siglen, md, mdlen) <= 0)
return 0;
} else {
if (sctx) {
if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0)
return 0;
} else {
int s = EVP_MD_get_size(ctx->digest);
if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0)
return 0;
}
}
return 1;
}
int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
const unsigned char *tbs, size_t tbslen)
{
EVP_PKEY_CTX *pctx = ctx->pctx;
if (pctx != NULL
&& pctx->operation == EVP_PKEY_OP_SIGNCTX
&& pctx->op.sig.algctx != NULL
&& pctx->op.sig.signature != NULL) {
if (pctx->op.sig.signature->digest_sign != NULL)
return pctx->op.sig.signature->digest_sign(pctx->op.sig.algctx,
sigret, siglen,
sigret == NULL ? 0 : *siglen,
tbs, tbslen);
} else {
/* legacy */
if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL)
return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen);
}
if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0)
return 0;
return EVP_DigestSignFinal(ctx, sigret, siglen);
}
int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen)
{
unsigned char md[EVP_MAX_MD_SIZE];
int r = 0;
unsigned int mdlen = 0;
int vctx = 0;
EVP_PKEY_CTX *dctx, *pctx = ctx->pctx;
if (pctx == NULL
|| pctx->operation != EVP_PKEY_OP_VERIFYCTX
|| pctx->op.sig.algctx == NULL
|| pctx->op.sig.signature == NULL)
goto legacy;
if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0)
return pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx,
sig, siglen);
dctx = EVP_PKEY_CTX_dup(pctx);
if (dctx == NULL)
return 0;
r = dctx->op.sig.signature->digest_verify_final(dctx->op.sig.algctx,
sig, siglen);
EVP_PKEY_CTX_free(dctx);
return r;
legacy:
if (pctx == NULL || pctx->pmeth == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
/* do_sigver_init() checked that |digest_custom| is non-NULL */
if (pctx->flag_call_digest_custom
&& !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
return 0;
pctx->flag_call_digest_custom = 0;
if (pctx->pmeth->verifyctx != NULL)
vctx = 1;
else
vctx = 0;
if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
if (vctx)
r = pctx->pmeth->verifyctx(pctx, sig, siglen, ctx);
else
r = EVP_DigestFinal_ex(ctx, md, &mdlen);
} else {
EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
if (tmp_ctx == NULL)
return -1;
if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) {
EVP_MD_CTX_free(tmp_ctx);
return -1;
}
if (vctx)
r = tmp_ctx->pctx->pmeth->verifyctx(tmp_ctx->pctx,
sig, siglen, tmp_ctx);
else
r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen);
EVP_MD_CTX_free(tmp_ctx);
}
if (vctx || !r)
return r;
return EVP_PKEY_verify(pctx, sig, siglen, md, mdlen);
}
int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
size_t siglen, const unsigned char *tbs, size_t tbslen)
{
EVP_PKEY_CTX *pctx = ctx->pctx;
- if (pctx != NULL
- && pctx->operation == EVP_PKEY_OP_VERIFYCTX
+ if (pctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return -1;
+ }
+
+ if (pctx->operation == EVP_PKEY_OP_VERIFYCTX
&& pctx->op.sig.algctx != NULL
&& pctx->op.sig.signature != NULL) {
if (pctx->op.sig.signature->digest_verify != NULL)
return pctx->op.sig.signature->digest_verify(pctx->op.sig.algctx,
sigret, siglen,
tbs, tbslen);
} else {
/* legacy */
- if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL)
- return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen);
+ if (pctx->pmeth != NULL && pctx->pmeth->digestverify != NULL)
+ return pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen);
}
if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0)
return -1;
return EVP_DigestVerifyFinal(ctx, sigret, siglen);
}
#endif /* FIPS_MODULE */
diff --git a/crypto/openssl/crypto/http/http_client.c b/crypto/openssl/crypto/http/http_client.c
index 4b96a6b9e9e2..c86db4405b8f 100644
--- a/crypto/openssl/crypto/http/http_client.c
+++ b/crypto/openssl/crypto/http/http_client.c
@@ -1,1438 +1,1449 @@
/*
* Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Siemens AG 2018-2020
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <stdlib.h>
#include "crypto/ctype.h"
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/httperr.h>
#include <openssl/cmperr.h>
#include <openssl/buffer.h>
#include <openssl/http.h>
#include "internal/sockets.h"
#include "internal/cryptlib.h" /* for ossl_assert() */
#define HAS_PREFIX(str, prefix) (strncmp(str, prefix, sizeof(prefix) - 1) == 0)
#define HTTP_PREFIX "HTTP/"
#define HTTP_VERSION_PATT "1." /* allow 1.x */
#define HTTP_VERSION_STR_LEN sizeof(HTTP_VERSION_PATT) /* == strlen("1.0") */
#define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT
#define HTTP_1_0 HTTP_PREFIX_VERSION"0" /* "HTTP/1.0" */
#define HTTP_LINE1_MINLEN (sizeof(HTTP_PREFIX_VERSION "x 200\n") - 1)
#define HTTP_VERSION_MAX_REDIRECTIONS 50
#define HTTP_STATUS_CODE_OK 200
#define HTTP_STATUS_CODE_MOVED_PERMANENTLY 301
#define HTTP_STATUS_CODE_FOUND 302
/* Stateful HTTP request code, supporting blocking and non-blocking I/O */
/* Opaque HTTP request status structure */
struct ossl_http_req_ctx_st {
int state; /* Current I/O state */
unsigned char *buf; /* Buffer to write request or read response */
int buf_size; /* Buffer size */
int free_wbio; /* wbio allocated internally, free with ctx */
BIO *wbio; /* BIO to write/send request to */
BIO *rbio; /* BIO to read/receive response from */
OSSL_HTTP_bio_cb_t upd_fn; /* Optional BIO update callback used for TLS */
void *upd_arg; /* Optional arg for update callback function */
int use_ssl; /* Use HTTPS */
char *proxy; /* Optional proxy name or URI */
char *server; /* Optional server host name */
char *port; /* Optional server port */
BIO *mem; /* Mem BIO holding request header or response */
BIO *req; /* BIO holding the request provided by caller */
int method_POST; /* HTTP method is POST (else GET) */
char *expected_ct; /* Optional expected Content-Type */
int expect_asn1; /* Response must be ASN.1-encoded */
unsigned char *pos; /* Current position sending data */
long len_to_send; /* Number of bytes still to send */
size_t resp_len; /* Length of response */
size_t max_resp_len; /* Maximum length of response, or 0 */
int keep_alive; /* Persistent conn. 0=no, 1=prefer, 2=require */
time_t max_time; /* Maximum end time of current transfer, or 0 */
time_t max_total_time; /* Maximum end time of total transfer, or 0 */
char *redirection_url; /* Location obtained from HTTP status 301/302 */
};
/* HTTP states */
#define OHS_NOREAD 0x1000 /* If set no reading should be performed */
#define OHS_ERROR (0 | OHS_NOREAD) /* Error condition */
#define OHS_ADD_HEADERS (1 | OHS_NOREAD) /* Adding header lines to request */
#define OHS_WRITE_INIT (2 | OHS_NOREAD) /* 1st call: ready to start send */
#define OHS_WRITE_HDR (3 | OHS_NOREAD) /* Request header being sent */
#define OHS_WRITE_REQ (4 | OHS_NOREAD) /* Request contents being sent */
#define OHS_FLUSH (5 | OHS_NOREAD) /* Request being flushed */
#define OHS_FIRSTLINE 1 /* First line of response being read */
#define OHS_HEADERS 2 /* MIME headers of response being read */
#define OHS_REDIRECT 3 /* MIME headers being read, expecting Location */
#define OHS_ASN1_HEADER 4 /* ASN1 sequence header (tag+length) being read */
#define OHS_ASN1_CONTENT 5 /* ASN1 content octets being read */
#define OHS_ASN1_DONE (6 | OHS_NOREAD) /* ASN1 content read completed */
#define OHS_STREAM (7 | OHS_NOREAD) /* HTTP content stream to be read */
/* Low-level HTTP API implementation */
OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size)
{
OSSL_HTTP_REQ_CTX *rctx;
if (wbio == NULL || rbio == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((rctx = OPENSSL_zalloc(sizeof(*rctx))) == NULL)
return NULL;
rctx->state = OHS_ERROR;
rctx->buf_size = buf_size > 0 ? buf_size : OSSL_HTTP_DEFAULT_MAX_LINE_LEN;
rctx->buf = OPENSSL_malloc(rctx->buf_size);
rctx->wbio = wbio;
rctx->rbio = rbio;
if (rctx->buf == NULL) {
OPENSSL_free(rctx);
return NULL;
}
rctx->max_resp_len = OSSL_HTTP_DEFAULT_MAX_RESP_LEN;
/* everything else is 0, e.g. rctx->len_to_send, or NULL, e.g. rctx->mem */
return rctx;
}
void OSSL_HTTP_REQ_CTX_free(OSSL_HTTP_REQ_CTX *rctx)
{
if (rctx == NULL)
return;
/*
* Use BIO_free_all() because bio_update_fn may prepend or append to cbio.
* This also frees any (e.g., SSL/TLS) BIOs linked with bio and,
* like BIO_reset(bio), calls SSL_shutdown() to notify/alert the peer.
*/
if (rctx->free_wbio)
BIO_free_all(rctx->wbio);
/* do not free rctx->rbio */
BIO_free(rctx->mem);
BIO_free(rctx->req);
OPENSSL_free(rctx->buf);
OPENSSL_free(rctx->proxy);
OPENSSL_free(rctx->server);
OPENSSL_free(rctx->port);
OPENSSL_free(rctx->expected_ct);
OPENSSL_free(rctx);
}
BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx)
{
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
return rctx->mem;
}
size_t OSSL_HTTP_REQ_CTX_get_resp_len(const OSSL_HTTP_REQ_CTX *rctx)
{
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
return rctx->resp_len;
}
void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx,
unsigned long len)
{
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return;
}
rctx->max_resp_len = len != 0 ? (size_t)len : OSSL_HTTP_DEFAULT_MAX_RESP_LEN;
}
/*
* Create request line using |rctx| and |path| (or "/" in case |path| is NULL).
* Server name (and optional port) must be given if and only if
* a plain HTTP proxy is used and |path| does not begin with 'http://'.
*/
int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx, int method_POST,
const char *server, const char *port,
const char *path)
{
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BIO_free(rctx->mem);
if ((rctx->mem = BIO_new(BIO_s_mem())) == NULL)
return 0;
rctx->method_POST = method_POST != 0;
if (BIO_printf(rctx->mem, "%s ", rctx->method_POST ? "POST" : "GET") <= 0)
return 0;
if (server != NULL) { /* HTTP (but not HTTPS) proxy is used */
/*
* Section 5.1.2 of RFC 1945 states that the absoluteURI form is only
* allowed when using a proxy
*/
if (BIO_printf(rctx->mem, OSSL_HTTP_PREFIX"%s", server) <= 0)
return 0;
if (port != NULL && BIO_printf(rctx->mem, ":%s", port) <= 0)
return 0;
}
/* Make sure path includes a forward slash (abs_path) */
if (path == NULL) {
path = "/";
} else if (HAS_PREFIX(path, "http://")) { /* absoluteURI for proxy use */
if (server != NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
} else if (path[0] != '/' && BIO_printf(rctx->mem, "/") <= 0) {
return 0;
}
/*
* Add (the rest of) the path and the HTTP version,
* which is fixed to 1.0 for straightforward implementation of keep-alive
*/
if (BIO_printf(rctx->mem, "%s "HTTP_1_0"\r\n", path) <= 0)
return 0;
rctx->resp_len = 0;
rctx->state = OHS_ADD_HEADERS;
return 1;
}
int OSSL_HTTP_REQ_CTX_add1_header(OSSL_HTTP_REQ_CTX *rctx,
const char *name, const char *value)
{
if (rctx == NULL || name == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (rctx->mem == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (BIO_puts(rctx->mem, name) <= 0)
return 0;
if (value != NULL) {
if (BIO_write(rctx->mem, ": ", 2) != 2)
return 0;
if (BIO_puts(rctx->mem, value) <= 0)
return 0;
}
return BIO_write(rctx->mem, "\r\n", 2) == 2;
}
int OSSL_HTTP_REQ_CTX_set_expected(OSSL_HTTP_REQ_CTX *rctx,
const char *content_type, int asn1,
int timeout, int keep_alive)
{
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (keep_alive != 0
&& rctx->state != OHS_ERROR && rctx->state != OHS_ADD_HEADERS) {
/* Cannot anymore set keep-alive in request header */
ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
OPENSSL_free(rctx->expected_ct);
rctx->expected_ct = NULL;
if (content_type != NULL
&& (rctx->expected_ct = OPENSSL_strdup(content_type)) == NULL)
return 0;
rctx->expect_asn1 = asn1;
if (timeout >= 0)
rctx->max_time = timeout > 0 ? time(NULL) + timeout : 0;
else /* take over any |overall_timeout| arg of OSSL_HTTP_open(), else 0 */
rctx->max_time = rctx->max_total_time;
rctx->keep_alive = keep_alive;
return 1;
}
static int set1_content(OSSL_HTTP_REQ_CTX *rctx,
const char *content_type, BIO *req)
{
long req_len = 0;
#ifndef OPENSSL_NO_STDIO
FILE *fp = NULL;
#endif
if (rctx == NULL || (req == NULL && content_type != NULL)) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (rctx->keep_alive != 0
&& !OSSL_HTTP_REQ_CTX_add1_header(rctx, "Connection", "keep-alive"))
return 0;
BIO_free(rctx->req);
rctx->req = NULL;
if (req == NULL)
return 1;
if (!rctx->method_POST) {
ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (content_type != NULL
&& BIO_printf(rctx->mem, "Content-Type: %s\r\n", content_type) <= 0)
return 0;
/*
* BIO_CTRL_INFO yields the data length at least for memory BIOs, but for
* file-based BIOs it gives the current position, which is not what we need.
*/
if (BIO_method_type(req) == BIO_TYPE_FILE) {
#ifndef OPENSSL_NO_STDIO
if (BIO_get_fp(req, &fp) == 1 && fseek(fp, 0, SEEK_END) == 0) {
req_len = ftell(fp);
(void)fseek(fp, 0, SEEK_SET);
} else {
fp = NULL;
}
#endif
} else {
req_len = BIO_ctrl(req, BIO_CTRL_INFO, 0, NULL);
/*
* Streaming BIOs likely will not support querying the size at all,
* and we assume we got a correct value if req_len > 0.
*/
}
if ((
#ifndef OPENSSL_NO_STDIO
fp != NULL /* definitely correct req_len */ ||
#endif
req_len > 0)
&& BIO_printf(rctx->mem, "Content-Length: %ld\r\n", req_len) < 0)
return 0;
if (!BIO_up_ref(req))
return 0;
rctx->req = req;
return 1;
}
int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type,
const ASN1_ITEM *it, const ASN1_VALUE *req)
{
BIO *mem = NULL;
int res = 1;
if (req != NULL)
res = (mem = ASN1_item_i2d_mem_bio(it, req)) != NULL;
res = res && set1_content(rctx, content_type, mem);
BIO_free(mem);
return res;
}
static int add1_headers(OSSL_HTTP_REQ_CTX *rctx,
const STACK_OF(CONF_VALUE) *headers, const char *host)
{
int i;
int add_host = host != NULL && *host != '\0';
CONF_VALUE *hdr;
for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
hdr = sk_CONF_VALUE_value(headers, i);
if (add_host && OPENSSL_strcasecmp("host", hdr->name) == 0)
add_host = 0;
if (!OSSL_HTTP_REQ_CTX_add1_header(rctx, hdr->name, hdr->value))
return 0;
}
if (add_host && !OSSL_HTTP_REQ_CTX_add1_header(rctx, "Host", host))
return 0;
return 1;
}
/* Create OSSL_HTTP_REQ_CTX structure using the values provided. */
static OSSL_HTTP_REQ_CTX *http_req_ctx_new(int free_wbio, BIO *wbio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn,
void *arg, int use_ssl,
const char *proxy,
const char *server, const char *port,
int buf_size, int overall_timeout)
{
OSSL_HTTP_REQ_CTX *rctx = OSSL_HTTP_REQ_CTX_new(wbio, rbio, buf_size);
if (rctx == NULL)
return NULL;
rctx->free_wbio = free_wbio;
rctx->upd_fn = bio_update_fn;
rctx->upd_arg = arg;
rctx->use_ssl = use_ssl;
if (proxy != NULL
&& (rctx->proxy = OPENSSL_strdup(proxy)) == NULL)
goto err;
if (server != NULL
&& (rctx->server = OPENSSL_strdup(server)) == NULL)
goto err;
if (port != NULL
&& (rctx->port = OPENSSL_strdup(port)) == NULL)
goto err;
rctx->max_total_time =
overall_timeout > 0 ? time(NULL) + overall_timeout : 0;
return rctx;
err:
OSSL_HTTP_REQ_CTX_free(rctx);
return NULL;
}
/*
* Parse first HTTP response line. This should be like this: "HTTP/1.0 200 OK".
* We need to obtain the status code and (optional) informational message.
* Return any received HTTP response status code, or 0 on fatal error.
*/
static int parse_http_line1(char *line, int *found_keep_alive)
{
int i, retcode, err;
char *code, *reason, *end;
if (!HAS_PREFIX(line, HTTP_PREFIX_VERSION))
goto err;
/* above HTTP 1.0, connection persistence is the default */
*found_keep_alive = line[strlen(HTTP_PREFIX_VERSION)] > '0';
/* Skip to first whitespace (past protocol info) */
for (code = line; *code != '\0' && !ossl_isspace(*code); code++)
continue;
if (*code == '\0')
goto err;
/* Skip past whitespace to start of response code */
while (*code != '\0' && ossl_isspace(*code))
code++;
if (*code == '\0')
goto err;
/* Find end of response code: first whitespace after start of code */
for (reason = code; *reason != '\0' && !ossl_isspace(*reason); reason++)
continue;
if (*reason == '\0')
goto err;
/* Set end of response code and start of message */
*reason++ = '\0';
/* Attempt to parse numeric code */
retcode = strtoul(code, &end, 10);
if (*end != '\0')
goto err;
/* Skip over any leading whitespace in message */
while (*reason != '\0' && ossl_isspace(*reason))
reason++;
if (*reason != '\0') {
/*
* Finally zap any trailing whitespace in message (include CRLF)
*/
/* chop any trailing whitespace from reason */
/* We know reason has a non-whitespace character so this is OK */
for (end = reason + strlen(reason) - 1; ossl_isspace(*end); end--)
*end = '\0';
}
switch (retcode) {
case HTTP_STATUS_CODE_OK:
case HTTP_STATUS_CODE_MOVED_PERMANENTLY:
case HTTP_STATUS_CODE_FOUND:
return retcode;
default:
err = HTTP_R_RECEIVED_ERROR;
if (retcode < 400)
err = HTTP_R_STATUS_CODE_UNSUPPORTED;
if (*reason == '\0')
ERR_raise_data(ERR_LIB_HTTP, err, "code=%s", code);
else
ERR_raise_data(ERR_LIB_HTTP, err, "code=%s, reason=%s", code,
reason);
return retcode;
}
err:
for (i = 0; i < 60 && line[i] != '\0'; i++)
if (!ossl_isprint(line[i]))
line[i] = ' ';
line[i] = '\0';
ERR_raise_data(ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR, "content=%s", line);
return 0;
}
static int check_set_resp_len(OSSL_HTTP_REQ_CTX *rctx, size_t len)
{
if (rctx->max_resp_len != 0 && len > rctx->max_resp_len) {
ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MAX_RESP_LEN_EXCEEDED,
"length=%zu, max=%zu", len, rctx->max_resp_len);
return 0;
}
if (rctx->resp_len != 0 && rctx->resp_len != len) {
ERR_raise_data(ERR_LIB_HTTP, HTTP_R_INCONSISTENT_CONTENT_LENGTH,
"ASN.1 length=%zu, Content-Length=%zu",
len, rctx->resp_len);
return 0;
}
rctx->resp_len = len;
return 1;
}
static int may_still_retry(time_t max_time, int *ptimeout)
{
time_t time_diff, now = time(NULL);
if (max_time != 0) {
if (max_time < now) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_RETRY_TIMEOUT);
return 0;
}
time_diff = max_time - now;
*ptimeout = time_diff > INT_MAX ? INT_MAX : (int)time_diff;
}
return 1;
}
/*
* Try exchanging request and response via HTTP on (non-)blocking BIO in rctx.
* Returns 1 on success, 0 on error or redirection, -1 on BIO_should_retry.
*/
int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
{
int i, found_expected_ct = 0, found_keep_alive = 0;
long n;
size_t resp_len;
const unsigned char *p;
char *buf, *key, *value, *line_end = NULL;
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (rctx->mem == NULL || rctx->wbio == NULL || rctx->rbio == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
rctx->redirection_url = NULL;
next_io:
buf = (char *)rctx->buf;
if ((rctx->state & OHS_NOREAD) == 0) {
if (rctx->expect_asn1) {
n = BIO_read(rctx->rbio, rctx->buf, rctx->buf_size);
} else {
(void)ERR_set_mark();
n = BIO_gets(rctx->rbio, buf, rctx->buf_size);
if (n == -2) { /* unsupported method */
(void)ERR_pop_to_mark();
n = BIO_get_line(rctx->rbio, buf, rctx->buf_size);
} else {
(void)ERR_clear_last_mark();
}
}
if (n <= 0) {
if (BIO_should_retry(rctx->rbio))
return -1;
ERR_raise(ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA);
return 0;
}
/* Write data to memory BIO */
if (BIO_write(rctx->mem, rctx->buf, n) != n)
return 0;
}
switch (rctx->state) {
case OHS_ADD_HEADERS:
/* Last operation was adding headers: need a final \r\n */
if (BIO_write(rctx->mem, "\r\n", 2) != 2) {
rctx->state = OHS_ERROR;
return 0;
}
rctx->state = OHS_WRITE_INIT;
/* fall thru */
case OHS_WRITE_INIT:
rctx->len_to_send = BIO_get_mem_data(rctx->mem, &rctx->pos);
rctx->state = OHS_WRITE_HDR;
/* fall thru */
case OHS_WRITE_HDR:
/* Copy some chunk of data from rctx->mem to rctx->wbio */
case OHS_WRITE_REQ:
/* Copy some chunk of data from rctx->req to rctx->wbio */
if (rctx->len_to_send > 0) {
i = BIO_write(rctx->wbio, rctx->pos, rctx->len_to_send);
if (i <= 0) {
if (BIO_should_retry(rctx->wbio))
return -1;
rctx->state = OHS_ERROR;
return 0;
}
rctx->pos += i;
rctx->len_to_send -= i;
goto next_io;
}
if (rctx->state == OHS_WRITE_HDR) {
(void)BIO_reset(rctx->mem);
rctx->state = OHS_WRITE_REQ;
}
if (rctx->req != NULL && !BIO_eof(rctx->req)) {
n = BIO_read(rctx->req, rctx->buf, rctx->buf_size);
if (n <= 0) {
if (BIO_should_retry(rctx->req))
return -1;
ERR_raise(ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA);
return 0;
}
rctx->pos = rctx->buf;
rctx->len_to_send = n;
goto next_io;
}
rctx->state = OHS_FLUSH;
/* fall thru */
case OHS_FLUSH:
i = BIO_flush(rctx->wbio);
if (i > 0) {
rctx->state = OHS_FIRSTLINE;
goto next_io;
}
if (BIO_should_retry(rctx->wbio))
return -1;
rctx->state = OHS_ERROR;
return 0;
case OHS_ERROR:
return 0;
case OHS_FIRSTLINE:
case OHS_HEADERS:
case OHS_REDIRECT:
/* Attempt to read a line in */
next_line:
/*
* Due to strange memory BIO behavior with BIO_gets we have to check
* there's a complete line in there before calling BIO_gets or we'll
* just get a partial read.
*/
n = BIO_get_mem_data(rctx->mem, &p);
if (n <= 0 || memchr(p, '\n', n) == 0) {
if (n >= rctx->buf_size) {
rctx->state = OHS_ERROR;
return 0;
}
goto next_io;
}
n = BIO_gets(rctx->mem, buf, rctx->buf_size);
if (n <= 0) {
if (BIO_should_retry(rctx->mem))
goto next_io;
rctx->state = OHS_ERROR;
return 0;
}
/* Don't allow excessive lines */
if (n == rctx->buf_size) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_LINE_TOO_LONG);
rctx->state = OHS_ERROR;
return 0;
}
/* First line */
if (rctx->state == OHS_FIRSTLINE) {
switch (parse_http_line1(buf, &found_keep_alive)) {
case HTTP_STATUS_CODE_OK:
rctx->state = OHS_HEADERS;
goto next_line;
case HTTP_STATUS_CODE_MOVED_PERMANENTLY:
case HTTP_STATUS_CODE_FOUND: /* i.e., moved temporarily */
if (!rctx->method_POST) { /* method is GET */
rctx->state = OHS_REDIRECT;
goto next_line;
}
ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_NOT_ENABLED);
/* redirection is not supported/recommended for POST */
/* fall through */
default:
rctx->state = OHS_ERROR;
goto next_line;
}
}
key = buf;
value = strchr(key, ':');
if (value != NULL) {
*(value++) = '\0';
while (ossl_isspace(*value))
value++;
line_end = strchr(value, '\r');
if (line_end == NULL)
line_end = strchr(value, '\n');
if (line_end != NULL)
*line_end = '\0';
}
if (value != NULL && line_end != NULL) {
if (rctx->state == OHS_REDIRECT
&& OPENSSL_strcasecmp(key, "Location") == 0) {
rctx->redirection_url = value;
return 0;
}
if (rctx->state == OHS_HEADERS && rctx->expected_ct != NULL
&& OPENSSL_strcasecmp(key, "Content-Type") == 0) {
if (OPENSSL_strcasecmp(rctx->expected_ct, value) != 0) {
ERR_raise_data(ERR_LIB_HTTP, HTTP_R_UNEXPECTED_CONTENT_TYPE,
"expected=%s, actual=%s",
rctx->expected_ct, value);
return 0;
}
found_expected_ct = 1;
}
/* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */
if (OPENSSL_strcasecmp(key, "Connection") == 0) {
if (OPENSSL_strcasecmp(value, "keep-alive") == 0)
found_keep_alive = 1;
else if (OPENSSL_strcasecmp(value, "close") == 0)
found_keep_alive = 0;
} else if (OPENSSL_strcasecmp(key, "Content-Length") == 0) {
resp_len = (size_t)strtoul(value, &line_end, 10);
if (line_end == value || *line_end != '\0') {
ERR_raise_data(ERR_LIB_HTTP,
HTTP_R_ERROR_PARSING_CONTENT_LENGTH,
"input=%s", value);
return 0;
}
if (!check_set_resp_len(rctx, resp_len))
return 0;
}
}
/* Look for blank line indicating end of headers */
for (p = rctx->buf; *p != '\0'; p++) {
if (*p != '\r' && *p != '\n')
break;
}
if (*p != '\0') /* not end of headers */
goto next_line;
if (rctx->keep_alive != 0 /* do not let server initiate keep_alive */
&& !found_keep_alive /* otherwise there is no change */) {
if (rctx->keep_alive == 2) {
rctx->keep_alive = 0;
ERR_raise(ERR_LIB_HTTP, HTTP_R_SERVER_CANCELED_CONNECTION);
return 0;
}
rctx->keep_alive = 0;
}
if (rctx->state == OHS_ERROR)
return 0;
if (rctx->expected_ct != NULL && !found_expected_ct) {
ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MISSING_CONTENT_TYPE,
"expected=%s", rctx->expected_ct);
return 0;
}
if (rctx->state == OHS_REDIRECT) {
/* http status code indicated redirect but there was no Location */
ERR_raise(ERR_LIB_HTTP, HTTP_R_MISSING_REDIRECT_LOCATION);
return 0;
}
if (!rctx->expect_asn1) {
rctx->state = OHS_STREAM;
return 1;
}
rctx->state = OHS_ASN1_HEADER;
/* Fall thru */
case OHS_ASN1_HEADER:
/*
* Now reading ASN1 header: can read at least 2 bytes which is enough
* for ASN1 SEQUENCE header and either length field or at least the
* length of the length field.
*/
n = BIO_get_mem_data(rctx->mem, &p);
if (n < 2)
goto next_io;
/* Check it is an ASN1 SEQUENCE */
if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_MISSING_ASN1_ENCODING);
return 0;
}
/* Check out length field */
if ((*p & 0x80) != 0) {
/*
* If MSB set on initial length octet we can now always read 6
* octets: make sure we have them.
*/
if (n < 6)
goto next_io;
n = *p & 0x7F;
/* Not NDEF or excessive length */
if (n == 0 || (n > 4)) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_ASN1_LENGTH);
return 0;
}
p++;
resp_len = 0;
for (i = 0; i < n; i++) {
resp_len <<= 8;
resp_len |= *p++;
}
resp_len += n + 2;
} else {
resp_len = *p + 2;
}
if (!check_set_resp_len(rctx, resp_len))
return 0;
rctx->state = OHS_ASN1_CONTENT;
/* Fall thru */
case OHS_ASN1_CONTENT:
default:
n = BIO_get_mem_data(rctx->mem, NULL);
if (n < 0 || (size_t)n < rctx->resp_len)
goto next_io;
rctx->state = OHS_ASN1_DONE;
return 1;
}
}
int OSSL_HTTP_REQ_CTX_nbio_d2i(OSSL_HTTP_REQ_CTX *rctx,
ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const unsigned char *p;
int rv;
*pval = NULL;
if ((rv = OSSL_HTTP_REQ_CTX_nbio(rctx)) != 1)
return rv;
*pval = ASN1_item_d2i(NULL, &p, BIO_get_mem_data(rctx->mem, &p), it);
return *pval != NULL;
}
#ifndef OPENSSL_NO_SOCK
+static const char *explict_or_default_port(const char *hostserv, const char *port, int use_ssl)
+{
+ if (port == NULL) {
+ char *service = NULL;
+
+ if (!BIO_parse_hostserv(hostserv, NULL, &service, BIO_PARSE_PRIO_HOST))
+ return NULL;
+ if (service == NULL) /* implicit port */
+ port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
+ OPENSSL_free(service);
+ } /* otherwise take the explicitly given port */
+ return port;
+}
+
/* set up a new connection BIO, to HTTP server or to HTTP(S) proxy if given */
static BIO *http_new_bio(const char *server /* optionally includes ":port" */,
const char *server_port /* explicit server port */,
int use_ssl,
const char *proxy /* optionally includes ":port" */,
const char *proxy_port /* explicit proxy port */)
{
const char *host = server;
const char *port = server_port;
BIO *cbio;
if (!ossl_assert(server != NULL))
return NULL;
if (proxy != NULL) {
host = proxy;
port = proxy_port;
}
- if (port == NULL && strchr(host, ':') == NULL)
- port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
+ port = explict_or_default_port(host, port, use_ssl);
cbio = BIO_new_connect(host /* optionally includes ":port" */);
if (cbio == NULL)
goto end;
if (port != NULL)
(void)BIO_set_conn_port(cbio, port);
end:
return cbio;
}
#endif /* OPENSSL_NO_SOCK */
/* Exchange request and response via HTTP on (non-)blocking BIO */
BIO *OSSL_HTTP_REQ_CTX_exchange(OSSL_HTTP_REQ_CTX *rctx)
{
int rv;
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
for (;;) {
rv = OSSL_HTTP_REQ_CTX_nbio(rctx);
if (rv != -1)
break;
/* BIO_should_retry was true */
/* will not actually wait if rctx->max_time == 0 */
if (BIO_wait(rctx->rbio, rctx->max_time, 100 /* milliseconds */) <= 0)
return NULL;
}
if (rv == 0) {
if (rctx->redirection_url == NULL) { /* an error occurred */
if (rctx->len_to_send > 0)
ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_SENDING);
else
ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_RECEIVING);
}
return NULL;
}
return rctx->state == OHS_STREAM ? rctx->rbio : rctx->mem;
}
int OSSL_HTTP_is_alive(const OSSL_HTTP_REQ_CTX *rctx)
{
return rctx != NULL && rctx->keep_alive != 0;
}
/* High-level HTTP API implementation */
/* Initiate an HTTP session using bio, else use given server, proxy, etc. */
OSSL_HTTP_REQ_CTX *OSSL_HTTP_open(const char *server, const char *port,
const char *proxy, const char *no_proxy,
int use_ssl, BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, int overall_timeout)
{
BIO *cbio; /* == bio if supplied, used as connection BIO if rbio is NULL */
OSSL_HTTP_REQ_CTX *rctx = NULL;
if (use_ssl && bio_update_fn == NULL) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_TLS_NOT_ENABLED);
return NULL;
}
if (rbio != NULL && (bio == NULL || bio_update_fn != NULL)) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
return NULL;
}
if (bio != NULL) {
cbio = bio;
if (proxy != NULL || no_proxy != NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
return NULL;
}
} else {
#ifndef OPENSSL_NO_SOCK
char *proxy_host = NULL, *proxy_port = NULL;
if (server == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (port != NULL && *port == '\0')
port = NULL;
- if (port == NULL && strchr(server, ':') == NULL)
- port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
proxy = OSSL_HTTP_adapt_proxy(proxy, no_proxy, server, use_ssl);
if (proxy != NULL
&& !OSSL_HTTP_parse_url(proxy, NULL /* use_ssl */, NULL /* user */,
&proxy_host, &proxy_port, NULL /* num */,
NULL /* path */, NULL, NULL))
return NULL;
cbio = http_new_bio(server, port, use_ssl, proxy_host, proxy_port);
OPENSSL_free(proxy_host);
OPENSSL_free(proxy_port);
if (cbio == NULL)
return NULL;
#else
ERR_raise(ERR_LIB_HTTP, HTTP_R_SOCK_NOT_SUPPORTED);
return NULL;
#endif
}
(void)ERR_set_mark(); /* prepare removing any spurious libssl errors */
if (rbio == NULL && BIO_do_connect_retry(cbio, overall_timeout, -1) <= 0) {
if (bio == NULL) /* cbio was not provided by caller */
BIO_free_all(cbio);
goto end;
}
/* now overall_timeout is guaranteed to be >= 0 */
/* adapt in order to fix callback design flaw, see #17088 */
/* callback can be used to wrap or prepend TLS session */
if (bio_update_fn != NULL) {
BIO *orig_bio = cbio;
cbio = (*bio_update_fn)(cbio, arg, 1 /* connect */, use_ssl != 0);
if (cbio == NULL) {
if (bio == NULL) /* cbio was not provided by caller */
BIO_free_all(orig_bio);
goto end;
}
}
rctx = http_req_ctx_new(bio == NULL, cbio, rbio != NULL ? rbio : cbio,
bio_update_fn, arg, use_ssl, proxy, server, port,
buf_size, overall_timeout);
end:
if (rctx != NULL)
/* remove any spurious error queue entries by ssl_add_cert_chain() */
(void)ERR_pop_to_mark();
else
(void)ERR_clear_last_mark();
return rctx;
}
int OSSL_HTTP_set1_request(OSSL_HTTP_REQ_CTX *rctx, const char *path,
const STACK_OF(CONF_VALUE) *headers,
const char *content_type, BIO *req,
const char *expected_content_type, int expect_asn1,
size_t max_resp_len, int timeout, int keep_alive)
{
int use_http_proxy;
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
use_http_proxy = rctx->proxy != NULL && !rctx->use_ssl;
if (use_http_proxy && rctx->server == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
rctx->max_resp_len = max_resp_len; /* allows for 0: indefinite */
return OSSL_HTTP_REQ_CTX_set_request_line(rctx, req != NULL,
use_http_proxy ? rctx->server
: NULL, rctx->port, path)
&& add1_headers(rctx, headers, rctx->server)
&& OSSL_HTTP_REQ_CTX_set_expected(rctx, expected_content_type,
expect_asn1, timeout, keep_alive)
&& set1_content(rctx, content_type, req);
}
/*-
* Exchange single HTTP request and response according to rctx.
* If rctx->method_POST then use POST, else use GET and ignore content_type.
* The redirection_url output (freed by caller) parameter is used only for GET.
*/
BIO *OSSL_HTTP_exchange(OSSL_HTTP_REQ_CTX *rctx, char **redirection_url)
{
BIO *resp;
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (redirection_url != NULL)
*redirection_url = NULL; /* do this beforehand to prevent dbl free */
resp = OSSL_HTTP_REQ_CTX_exchange(rctx);
if (resp == NULL) {
if (rctx->redirection_url != NULL) {
if (redirection_url == NULL)
ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_NOT_ENABLED);
else
/* may be NULL if out of memory: */
*redirection_url = OPENSSL_strdup(rctx->redirection_url);
} else {
char buf[200];
unsigned long err = ERR_peek_error();
int lib = ERR_GET_LIB(err);
int reason = ERR_GET_REASON(err);
if (lib == ERR_LIB_SSL || lib == ERR_LIB_HTTP
|| (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_TIMEOUT)
|| (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_ERROR)
#ifndef OPENSSL_NO_CMP
|| (lib == ERR_LIB_CMP
&& reason == CMP_R_POTENTIALLY_INVALID_CERTIFICATE)
#endif
) {
if (rctx->server != NULL) {
BIO_snprintf(buf, sizeof(buf), "server=http%s://%s%s%s",
rctx->use_ssl ? "s" : "", rctx->server,
rctx->port != NULL ? ":" : "",
rctx->port != NULL ? rctx->port : "");
ERR_add_error_data(1, buf);
}
if (rctx->proxy != NULL)
ERR_add_error_data(2, " proxy=", rctx->proxy);
if (err == 0) {
BIO_snprintf(buf, sizeof(buf), " peer has disconnected%s",
rctx->use_ssl ? " violating the protocol" :
", likely because it requires the use of TLS");
ERR_add_error_data(1, buf);
}
}
}
}
if (resp != NULL && !BIO_up_ref(resp))
resp = NULL;
return resp;
}
static int redirection_ok(int n_redir, const char *old_url, const char *new_url)
{
if (n_redir >= HTTP_VERSION_MAX_REDIRECTIONS) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_TOO_MANY_REDIRECTIONS);
return 0;
}
if (*new_url == '/') /* redirection to same server => same protocol */
return 1;
if (HAS_PREFIX(old_url, OSSL_HTTPS_NAME":") &&
!HAS_PREFIX(new_url, OSSL_HTTPS_NAME":")) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP);
return 0;
}
return 1;
}
/* Get data via HTTP from server at given URL, potentially with redirection */
BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, const STACK_OF(CONF_VALUE) *headers,
const char *expected_ct, int expect_asn1,
size_t max_resp_len, int timeout)
{
char *current_url, *redirection_url = NULL;
int n_redirs = 0;
char *host;
char *port;
char *path;
int use_ssl;
OSSL_HTTP_REQ_CTX *rctx = NULL;
BIO *resp = NULL;
time_t max_time = timeout > 0 ? time(NULL) + timeout : 0;
if (url == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((current_url = OPENSSL_strdup(url)) == NULL)
return NULL;
for (;;) {
if (!OSSL_HTTP_parse_url(current_url, &use_ssl, NULL /* user */, &host,
&port, NULL /* port_num */, &path, NULL, NULL))
break;
rctx = OSSL_HTTP_open(host, port, proxy, no_proxy,
use_ssl, bio, rbio, bio_update_fn, arg,
buf_size, timeout);
new_rpath:
if (rctx != NULL) {
if (!OSSL_HTTP_set1_request(rctx, path, headers,
NULL /* content_type */,
NULL /* req */,
expected_ct, expect_asn1, max_resp_len,
-1 /* use same max time (timeout) */,
0 /* no keep_alive */)) {
OSSL_HTTP_REQ_CTX_free(rctx);
rctx = NULL;
} else {
resp = OSSL_HTTP_exchange(rctx, &redirection_url);
}
}
OPENSSL_free(path);
if (resp == NULL && redirection_url != NULL) {
if (redirection_ok(++n_redirs, current_url, redirection_url)
&& may_still_retry(max_time, &timeout)) {
(void)BIO_reset(bio);
OPENSSL_free(current_url);
current_url = redirection_url;
if (*redirection_url == '/') { /* redirection to same server */
path = OPENSSL_strdup(redirection_url);
if (path == NULL) {
OPENSSL_free(host);
OPENSSL_free(port);
(void)OSSL_HTTP_close(rctx, 1);
rctx = NULL;
BIO_free(resp);
OPENSSL_free(current_url);
return NULL;
}
goto new_rpath;
}
OPENSSL_free(host);
OPENSSL_free(port);
(void)OSSL_HTTP_close(rctx, 1);
rctx = NULL;
continue;
}
/* if redirection not allowed, ignore it */
OPENSSL_free(redirection_url);
}
OPENSSL_free(host);
OPENSSL_free(port);
if (!OSSL_HTTP_close(rctx, resp != NULL)) {
BIO_free(resp);
rctx = NULL;
resp = NULL;
}
break;
}
OPENSSL_free(current_url);
return resp;
}
/* Exchange request and response over a connection managed via |prctx| */
BIO *OSSL_HTTP_transfer(OSSL_HTTP_REQ_CTX **prctx,
const char *server, const char *port,
const char *path, int use_ssl,
const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, const STACK_OF(CONF_VALUE) *headers,
const char *content_type, BIO *req,
const char *expected_ct, int expect_asn1,
size_t max_resp_len, int timeout, int keep_alive)
{
OSSL_HTTP_REQ_CTX *rctx = prctx == NULL ? NULL : *prctx;
BIO *resp = NULL;
if (rctx == NULL) {
rctx = OSSL_HTTP_open(server, port, proxy, no_proxy,
use_ssl, bio, rbio, bio_update_fn, arg,
buf_size, timeout);
timeout = -1; /* Already set during opening the connection */
}
if (rctx != NULL) {
if (OSSL_HTTP_set1_request(rctx, path, headers, content_type, req,
expected_ct, expect_asn1,
max_resp_len, timeout, keep_alive))
resp = OSSL_HTTP_exchange(rctx, NULL);
if (resp == NULL || !OSSL_HTTP_is_alive(rctx)) {
if (!OSSL_HTTP_close(rctx, resp != NULL)) {
BIO_free(resp);
resp = NULL;
}
rctx = NULL;
}
}
if (prctx != NULL)
*prctx = rctx;
return resp;
}
int OSSL_HTTP_close(OSSL_HTTP_REQ_CTX *rctx, int ok)
{
BIO *wbio;
int ret = 1;
/* callback can be used to finish TLS session and free its BIO */
if (rctx != NULL && rctx->upd_fn != NULL) {
wbio = (*rctx->upd_fn)(rctx->wbio, rctx->upd_arg,
0 /* disconnect */, ok);
ret = wbio != NULL;
if (ret)
rctx->wbio = wbio;
}
OSSL_HTTP_REQ_CTX_free(rctx);
return ret;
}
/* BASE64 encoder used for encoding basic proxy authentication credentials */
static char *base64encode(const void *buf, size_t len)
{
int i;
size_t outl;
char *out;
/* Calculate size of encoded data */
outl = (len / 3);
if (len % 3 > 0)
outl++;
outl <<= 2;
out = OPENSSL_malloc(outl + 1);
if (out == NULL)
return 0;
i = EVP_EncodeBlock((unsigned char *)out, buf, len);
if (!ossl_assert(0 <= i && (size_t)i <= outl)) {
OPENSSL_free(out);
return NULL;
}
return out;
}
/*
* Promote the given connection BIO using the CONNECT method for a TLS proxy.
* This is typically called by an app, so bio_err and prog are used unless NULL
* to print additional diagnostic information in a user-oriented way.
*/
int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
const char *proxyuser, const char *proxypass,
int timeout, BIO *bio_err, const char *prog)
{
#undef BUF_SIZE
#define BUF_SIZE (8 * 1024)
char *mbuf = OPENSSL_malloc(BUF_SIZE);
char *mbufp;
int read_len = 0;
int ret = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
int rv;
time_t max_time = timeout > 0 ? time(NULL) + timeout : 0;
if (bio == NULL || server == NULL
|| (bio_err != NULL && prog == NULL)) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
goto end;
}
if (port == NULL || *port == '\0')
port = OSSL_HTTPS_PORT;
if (mbuf == NULL || fbio == NULL) {
BIO_printf(bio_err /* may be NULL */, "%s: out of memory", prog);
goto end;
}
BIO_push(fbio, bio);
BIO_printf(fbio, "CONNECT %s:%s "HTTP_1_0"\r\n", server, port);
/*
* Workaround for broken proxies which would otherwise close
* the connection when entering tunnel mode (e.g., Squid 2.6)
*/
BIO_printf(fbio, "Proxy-Connection: Keep-Alive\r\n");
/* Support for basic (base64) proxy authentication */
if (proxyuser != NULL) {
size_t len = strlen(proxyuser) + 1;
char *proxyauth, *proxyauthenc = NULL;
if (proxypass != NULL)
len += strlen(proxypass);
proxyauth = OPENSSL_malloc(len + 1);
if (proxyauth == NULL)
goto end;
if (BIO_snprintf(proxyauth, len + 1, "%s:%s", proxyuser,
proxypass != NULL ? proxypass : "") != (int)len)
goto proxy_end;
proxyauthenc = base64encode(proxyauth, len);
if (proxyauthenc != NULL) {
BIO_printf(fbio, "Proxy-Authorization: Basic %s\r\n", proxyauthenc);
OPENSSL_clear_free(proxyauthenc, strlen(proxyauthenc));
}
proxy_end:
OPENSSL_clear_free(proxyauth, len);
if (proxyauthenc == NULL)
goto end;
}
/* Terminate the HTTP CONNECT request */
BIO_printf(fbio, "\r\n");
for (;;) {
if (BIO_flush(fbio) != 0)
break;
/* potentially needs to be retried if BIO is non-blocking */
if (!BIO_should_retry(fbio))
break;
}
for (;;) {
/* will not actually wait if timeout == 0 */
rv = BIO_wait(fbio, max_time, 100 /* milliseconds */);
if (rv <= 0) {
BIO_printf(bio_err, "%s: HTTP CONNECT %s\n", prog,
rv == 0 ? "timed out" : "failed waiting for data");
goto end;
}
/*-
* The first line is the HTTP response.
* According to RFC 7230, it is formatted exactly like this:
* HTTP/d.d ddd reason text\r\n
*/
read_len = BIO_gets(fbio, mbuf, BUF_SIZE);
/* the BIO may not block, so we must wait for the 1st line to come in */
if (read_len < (int)HTTP_LINE1_MINLEN)
continue;
/* Check for HTTP/1.x */
if (!HAS_PREFIX(mbuf, HTTP_PREFIX) != 0) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR);
BIO_printf(bio_err, "%s: HTTP CONNECT failed, non-HTTP response\n",
prog);
/* Wrong protocol, not even HTTP, so stop reading headers */
goto end;
}
mbufp = mbuf + strlen(HTTP_PREFIX);
if (!HAS_PREFIX(mbufp, HTTP_VERSION_PATT) != 0) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_RECEIVED_WRONG_HTTP_VERSION);
BIO_printf(bio_err,
"%s: HTTP CONNECT failed, bad HTTP version %.*s\n",
prog, (int)HTTP_VERSION_STR_LEN, mbufp);
goto end;
}
mbufp += HTTP_VERSION_STR_LEN;
/* RFC 7231 4.3.6: any 2xx status code is valid */
if (!HAS_PREFIX(mbufp, " 2")) {
/* chop any trailing whitespace */
while (read_len > 0 && ossl_isspace(mbuf[read_len - 1]))
read_len--;
mbuf[read_len] = '\0';
ERR_raise_data(ERR_LIB_HTTP, HTTP_R_CONNECT_FAILURE,
"reason=%s", mbufp);
BIO_printf(bio_err, "%s: HTTP CONNECT failed, reason=%s\n",
prog, mbufp);
goto end;
}
ret = 1;
break;
}
/* Read past all following headers */
do {
/*
* This does not necessarily catch the case when the full
* HTTP response came in in more than a single TCP message.
*/
read_len = BIO_gets(fbio, mbuf, BUF_SIZE);
} while (read_len > 2);
end:
if (fbio != NULL) {
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
}
OPENSSL_free(mbuf);
return ret;
#undef BUF_SIZE
}
diff --git a/crypto/openssl/crypto/http/http_lib.c b/crypto/openssl/crypto/http/http_lib.c
index 30c1cd04fc00..9c41f57541d7 100644
--- a/crypto/openssl/crypto/http/http_lib.c
+++ b/crypto/openssl/crypto/http/http_lib.c
@@ -1,293 +1,307 @@
/*
- * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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> /* for sscanf() */
#include <string.h>
+#ifndef OPENSSL_NO_SOCK
+# include "../bio/bio_local.h" /* for NI_MAXHOST */
+#endif
#include <openssl/http.h>
#include <openssl/httperr.h>
#include <openssl/bio.h> /* for BIO_snprintf() */
#include <openssl/err.h>
#include "internal/cryptlib.h" /* for ossl_assert() */
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 255
+#endif
+#include "crypto/ctype.h" /* for ossl_isspace() */
static void init_pstring(char **pstr)
{
if (pstr != NULL) {
*pstr = NULL;
}
}
static void init_pint(int *pint)
{
if (pint != NULL) {
*pint = 0;
}
}
static int copy_substring(char **dest, const char *start, const char *end)
{
return dest == NULL
|| (*dest = OPENSSL_strndup(start, end - start)) != NULL;
}
static void free_pstring(char **pstr)
{
if (pstr != NULL) {
OPENSSL_free(*pstr);
*pstr = NULL;
}
}
int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
char **pport, int *pport_num,
char **ppath, char **pquery, char **pfrag)
{
const char *p, *tmp;
const char *scheme, *scheme_end;
const char *user, *user_end;
const char *host, *host_end;
const char *port, *port_end;
unsigned int portnum;
const char *path, *path_end;
const char *query, *query_end;
const char *frag, *frag_end;
init_pstring(pscheme);
init_pstring(puser);
init_pstring(phost);
init_pstring(pport);
init_pint(pport_num);
init_pstring(ppath);
init_pstring(pfrag);
init_pstring(pquery);
if (url == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/* check for optional prefix "<scheme>://" */
scheme = scheme_end = url;
p = strstr(url, "://");
if (p == NULL) {
p = url;
} else {
scheme_end = p;
if (scheme_end == scheme)
goto parse_err;
p += strlen("://");
}
/* parse optional "userinfo@" */
user = user_end = host = p;
host = strchr(p, '@');
if (host != NULL)
user_end = host++;
else
host = p;
/* parse host name/address as far as needed here */
if (host[0] == '[') {
/* ipv6 literal, which may include ':' */
host_end = strchr(host + 1, ']');
if (host_end == NULL)
goto parse_err;
p = ++host_end;
} else {
/* look for start of optional port, path, query, or fragment */
host_end = strchr(host, ':');
if (host_end == NULL)
host_end = strchr(host, '/');
if (host_end == NULL)
host_end = strchr(host, '?');
if (host_end == NULL)
host_end = strchr(host, '#');
if (host_end == NULL) /* the remaining string is just the hostname */
host_end = host + strlen(host);
p = host_end;
}
/* parse optional port specification starting with ':' */
port = "0"; /* default */
if (*p == ':')
port = ++p;
/* remaining port spec handling is also done for the default values */
/* make sure a decimal port number is given */
if (sscanf(port, "%u", &portnum) <= 0 || portnum > 65535) {
ERR_raise_data(ERR_LIB_HTTP, HTTP_R_INVALID_PORT_NUMBER, "%s", port);
goto err;
}
for (port_end = port; '0' <= *port_end && *port_end <= '9'; port_end++)
;
if (port == p) /* port was given explicitly */
p += port_end - port;
/* check for optional path starting with '/' or '?'. Else must start '#' */
path = p;
if (*path != '\0' && *path != '/' && *path != '?' && *path != '#') {
ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_URL_PATH);
goto parse_err;
}
path_end = query = query_end = frag = frag_end = path + strlen(path);
/* parse optional "?query" */
tmp = strchr(p, '?');
if (tmp != NULL) {
p = tmp;
if (pquery != NULL) {
path_end = p;
query = p + 1;
}
}
/* parse optional "#fragment" */
tmp = strchr(p, '#');
if (tmp != NULL) {
if (query == path_end) /* we did not record a query component */
path_end = tmp;
query_end = tmp;
frag = tmp + 1;
}
if (!copy_substring(pscheme, scheme, scheme_end)
|| !copy_substring(phost, host, host_end)
|| !copy_substring(pport, port, port_end)
|| !copy_substring(puser, user, user_end)
|| !copy_substring(pquery, query, query_end)
|| !copy_substring(pfrag, frag, frag_end))
goto err;
if (pport_num != NULL)
*pport_num = (int)portnum;
if (*path == '/') {
if (!copy_substring(ppath, path, path_end))
goto err;
} else if (ppath != NULL) { /* must prepend '/' */
size_t buflen = 1 + path_end - path + 1;
if ((*ppath = OPENSSL_malloc(buflen)) == NULL)
goto err;
BIO_snprintf(*ppath, buflen, "/%s", path);
}
return 1;
parse_err:
ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_URL);
err:
free_pstring(pscheme);
free_pstring(puser);
free_pstring(phost);
free_pstring(pport);
free_pstring(ppath);
free_pstring(pquery);
free_pstring(pfrag);
return 0;
}
int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost,
char **pport, int *pport_num,
char **ppath, char **pquery, char **pfrag)
{
char *scheme, *port;
int ssl = 0, portnum;
init_pstring(pport);
if (pssl != NULL)
*pssl = 0;
if (!OSSL_parse_url(url, &scheme, puser, phost, &port, pport_num,
ppath, pquery, pfrag))
return 0;
/* check for optional HTTP scheme "http[s]" */
if (strcmp(scheme, OSSL_HTTPS_NAME) == 0) {
ssl = 1;
if (pssl != NULL)
*pssl = ssl;
} else if (*scheme != '\0' && strcmp(scheme, OSSL_HTTP_NAME) != 0) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_URL_SCHEME);
OPENSSL_free(scheme);
OPENSSL_free(port);
goto err;
}
OPENSSL_free(scheme);
if (strcmp(port, "0") == 0) {
/* set default port */
OPENSSL_free(port);
port = ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
if (!ossl_assert(sscanf(port, "%d", &portnum) == 1))
goto err;
if (pport_num != NULL)
*pport_num = portnum;
if (pport != NULL) {
*pport = OPENSSL_strdup(port);
if (*pport == NULL)
goto err;
}
} else {
if (pport != NULL)
*pport = port;
else
OPENSSL_free(port);
}
return 1;
err:
free_pstring(puser);
free_pstring(phost);
free_pstring(ppath);
free_pstring(pquery);
free_pstring(pfrag);
return 0;
}
/* Respect no_proxy, taking default value from environment variable(s) */
static int use_proxy(const char *no_proxy, const char *server)
{
size_t sl;
const char *found = NULL;
+ char host[NI_MAXHOST];
if (!ossl_assert(server != NULL))
return 0;
sl = strlen(server);
+ if (sl >= 2 && sl < sizeof(host) + 2 && server[0] == '[' && server[sl - 1] == ']') {
+ /* strip leading '[' and trailing ']' from escaped IPv6 address */
+ sl -= 2;
+ strncpy(host, server + 1, sl);
+ server = host;
+ }
/*
* using environment variable names, both lowercase and uppercase variants,
* compatible with other HTTP client implementations like wget, curl and git
*/
if (no_proxy == NULL)
no_proxy = ossl_safe_getenv("no_proxy");
if (no_proxy == NULL)
no_proxy = ossl_safe_getenv(OPENSSL_NO_PROXY);
if (no_proxy != NULL)
found = strstr(no_proxy, server);
while (found != NULL
- && ((found != no_proxy && found[-1] != ' ' && found[-1] != ',')
- || (found[sl] != '\0' && found[sl] != ' ' && found[sl] != ',')))
+ && ((found != no_proxy && !ossl_isspace(found[-1]) && found[-1] != ',')
+ || (found[sl] != '\0' && !ossl_isspace(found[sl]) && found[sl] != ',')))
found = strstr(found + 1, server);
return found == NULL;
}
/* Take default value from environment variable(s), respect no_proxy */
const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy,
const char *server, int use_ssl)
{
/*
* using environment variable names, both lowercase and uppercase variants,
* compatible with other HTTP client implementations like wget, curl and git
*/
if (proxy == NULL)
proxy = ossl_safe_getenv(use_ssl ? "https_proxy" : "http_proxy");
if (proxy == NULL)
- proxy = ossl_safe_getenv(use_ssl ? OPENSSL_HTTP_PROXY : OPENSSL_HTTPS_PROXY);
+ proxy = ossl_safe_getenv(use_ssl ? OPENSSL_HTTPS_PROXY : OPENSSL_HTTP_PROXY);
if (proxy == NULL || *proxy == '\0' || !use_proxy(no_proxy, server))
return NULL;
return proxy;
}
diff --git a/crypto/openssl/crypto/pem/pem_pk8.c b/crypto/openssl/crypto/pem/pem_pk8.c
index 1592e351edef..6e84f0afd05d 100644
--- a/crypto/openssl/crypto/pem/pem_pk8.c
+++ b/crypto/openssl/crypto/pem/pem_pk8.c
@@ -1,273 +1,273 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/core_dispatch.h>
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/pkcs12.h>
#include <openssl/pem.h>
#include <openssl/encoder.h>
static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder,
int nid, const EVP_CIPHER *enc,
const char *kstr, int klen,
pem_password_cb *cb, void *u,
const char *propq);
#ifndef OPENSSL_NO_STDIO
static int do_pk8pkey_fp(FILE *bp, const EVP_PKEY *x, int isder,
int nid, const EVP_CIPHER *enc,
const char *kstr, int klen,
pem_password_cb *cb, void *u,
const char *propq);
#endif
/*
* These functions write a private key in PKCS#8 format: it is a "drop in"
* replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc'
* is NULL then it uses the unencrypted private key form. The 'nid' versions
* uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0.
*/
int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, const EVP_PKEY *x, int nid,
const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u, NULL);
}
int PEM_write_bio_PKCS8PrivateKey(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u, NULL);
}
int i2d_PKCS8PrivateKey_bio(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u, NULL);
}
int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, const EVP_PKEY *x, int nid,
const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u, NULL);
}
static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder, int nid,
const EVP_CIPHER *enc, const char *kstr, int klen,
pem_password_cb *cb, void *u, const char *propq)
{
int ret = 0;
const char *outtype = isder ? "DER" : "PEM";
OSSL_ENCODER_CTX *ctx =
OSSL_ENCODER_CTX_new_for_pkey(x, OSSL_KEYMGMT_SELECT_ALL,
outtype, "PrivateKeyInfo", propq);
if (ctx == NULL)
return 0;
/*
* If no keystring or callback is set, OpenSSL traditionally uses the
* user's cb argument as a password string, or if that's NULL, it falls
* back on PEM_def_callback().
*/
if (kstr == NULL && cb == NULL) {
if (u != NULL) {
kstr = u;
klen = strlen(u);
} else {
cb = PEM_def_callback;
}
}
/*
* NOTE: There is no attempt to do a EVP_CIPHER_fetch() using the nid,
* since the nid is a PBE algorithm which can't be fetched currently.
* (e.g. NID_pbe_WithSHA1And2_Key_TripleDES_CBC). Just use the legacy
* path if the NID is passed.
*/
if (nid == -1 && OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0) {
ret = 1;
if (enc != NULL) {
ret = 0;
if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_get0_name(enc),
NULL)) {
const unsigned char *ukstr = (const unsigned char *)kstr;
/*
* Try to pass the passphrase if one was given, or the
* passphrase callback if one was given. If none of them
* are given and that's wrong, we rely on the _to_bio()
* call to generate errors.
*/
ret = 1;
if (kstr != NULL
&& !OSSL_ENCODER_CTX_set_passphrase(ctx, ukstr, klen))
ret = 0;
else if (cb != NULL
&& !OSSL_ENCODER_CTX_set_pem_password_cb(ctx, cb, u))
ret = 0;
}
}
ret = ret && OSSL_ENCODER_to_bio(ctx, bp);
} else {
X509_SIG *p8;
PKCS8_PRIV_KEY_INFO *p8inf;
char buf[PEM_BUFSIZE];
ret = 0;
if ((p8inf = EVP_PKEY2PKCS8(x)) == NULL) {
ERR_raise(ERR_LIB_PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
goto legacy_end;
}
if (enc || (nid != -1)) {
if (kstr == NULL) {
klen = cb(buf, PEM_BUFSIZE, 1, u);
if (klen < 0) {
ERR_raise(ERR_LIB_PEM, PEM_R_READ_KEY);
goto legacy_end;
}
kstr = buf;
}
p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
if (kstr == buf)
OPENSSL_cleanse(buf, klen);
if (p8 == NULL)
goto legacy_end;
if (isder)
ret = i2d_PKCS8_bio(bp, p8);
else
ret = PEM_write_bio_PKCS8(bp, p8);
X509_SIG_free(p8);
} else {
if (isder)
ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
else
ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
}
legacy_end:
PKCS8_PRIV_KEY_INFO_free(p8inf);
}
OSSL_ENCODER_CTX_free(ctx);
return ret;
}
EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
void *u)
{
PKCS8_PRIV_KEY_INFO *p8inf = NULL;
X509_SIG *p8 = NULL;
int klen;
EVP_PKEY *ret;
- char psbuf[PEM_BUFSIZE];
+ char psbuf[PEM_BUFSIZE + 1]; /* reserve one byte at the end */
p8 = d2i_PKCS8_bio(bp, NULL);
if (p8 == NULL)
return NULL;
if (cb != NULL)
klen = cb(psbuf, PEM_BUFSIZE, 0, u);
else
klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
- if (klen < 0) {
+ if (klen < 0 || klen > PEM_BUFSIZE) {
ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ);
X509_SIG_free(p8);
return NULL;
}
p8inf = PKCS8_decrypt(p8, psbuf, klen);
X509_SIG_free(p8);
OPENSSL_cleanse(psbuf, klen);
if (p8inf == NULL)
return NULL;
ret = EVP_PKCS82PKEY(p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
if (!ret)
return NULL;
if (x != NULL) {
EVP_PKEY_free(*x);
*x = ret;
}
return ret;
}
#ifndef OPENSSL_NO_STDIO
int i2d_PKCS8PrivateKey_fp(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u, NULL);
}
int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, const EVP_PKEY *x, int nid,
const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u, NULL);
}
int PEM_write_PKCS8PrivateKey_nid(FILE *fp, const EVP_PKEY *x, int nid,
const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u, NULL);
}
int PEM_write_PKCS8PrivateKey(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u, NULL);
}
static int do_pk8pkey_fp(FILE *fp, const EVP_PKEY *x, int isder, int nid,
const EVP_CIPHER *enc, const char *kstr, int klen,
pem_password_cb *cb, void *u, const char *propq)
{
BIO *bp;
int ret;
if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u, propq);
BIO_free(bp);
return ret;
}
EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
void *u)
{
BIO *bp;
EVP_PKEY *ret;
if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return NULL;
}
ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
BIO_free(bp);
return ret;
}
#endif
IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG)
IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF,
PKCS8_PRIV_KEY_INFO)
diff --git a/crypto/openssl/crypto/pkcs12/p12_crt.c b/crypto/openssl/crypto/pkcs12/p12_crt.c
index 1a48e5c611da..3c7d5ff97c52 100644
--- a/crypto/openssl/crypto/pkcs12/p12_crt.c
+++ b/crypto/openssl/crypto/pkcs12/p12_crt.c
@@ -1,362 +1,364 @@
/*
- * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/pkcs12.h>
#include "p12_local.h"
static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
PKCS12_SAFEBAG *bag);
static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
X509 *cert,
const char *name,
int namelen,
unsigned char *keyid,
int keyidlen);
static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
{
int idx;
X509_ATTRIBUTE *attr;
idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1);
if (idx < 0)
return 1;
attr = EVP_PKEY_get_attr(pkey, idx);
if (!X509at_add1_attr(&bag->attrib, attr))
return 0;
return 1;
}
PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
int iter, int mac_iter, int keytype,
OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS12 *p12 = NULL;
STACK_OF(PKCS7) *safes = NULL;
STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
PKCS12_SAFEBAG *bag = NULL;
int i;
unsigned char keyid[EVP_MAX_MD_SIZE];
unsigned int keyidlen = 0;
int namelen = -1;
unsigned char *pkeyid = NULL;
int pkeyidlen = -1;
/* Set defaults */
if (nid_cert == NID_undef)
nid_cert = NID_aes_256_cbc;
if (nid_key == NID_undef)
nid_key = NID_aes_256_cbc;
if (!iter)
iter = PKCS12_DEFAULT_ITER;
if (!mac_iter)
mac_iter = PKCS12_DEFAULT_ITER;
if (pkey == NULL && cert == NULL && ca == NULL) {
ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_ARGUMENT);
return NULL;
}
if (pkey && cert) {
if (!X509_check_private_key(cert, pkey))
return NULL;
if (!X509_digest(cert, EVP_sha1(), keyid, &keyidlen))
return NULL;
}
if (cert) {
if (name == NULL)
name = (char *)X509_alias_get0(cert, &namelen);
if (keyidlen > 0) {
pkeyid = keyid;
pkeyidlen = keyidlen;
} else {
pkeyid = X509_keyid_get0(cert, &pkeyidlen);
}
bag = pkcs12_add_cert_bag(&bags, cert, name, namelen, pkeyid, pkeyidlen);
}
/* Add all other certificates */
for (i = 0; i < sk_X509_num(ca); i++) {
if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i)))
goto err;
}
if (bags && !PKCS12_add_safe_ex(&safes, bags, nid_cert, iter, pass,
ctx, propq))
goto err;
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
bags = NULL;
if (pkey) {
bag = PKCS12_add_key_ex(&bags, pkey, keytype, iter, nid_key, pass,
ctx, propq);
if (!bag)
goto err;
if (!copy_bag_attr(bag, pkey, NID_ms_csp_name))
goto err;
if (!copy_bag_attr(bag, pkey, NID_LocalKeySet))
goto err;
if (name && !PKCS12_add_friendlyname(bag, name, -1))
goto err;
if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
goto err;
}
if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL))
goto err;
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
bags = NULL;
p12 = PKCS12_add_safes_ex(safes, 0, ctx, propq);
if (p12 == NULL)
goto err;
sk_PKCS7_pop_free(safes, PKCS7_free);
safes = NULL;
if ((mac_iter != -1) &&
!PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL))
goto err;
return p12;
err:
PKCS12_free(p12);
sk_PKCS7_pop_free(safes, PKCS7_free);
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
return NULL;
}
PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert,
STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
int mac_iter, int keytype)
{
return PKCS12_create_ex(pass, name, pkey, cert, ca, nid_key, nid_cert,
iter, mac_iter, keytype, NULL, NULL);
}
static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
X509 *cert,
const char *name,
int namelen,
unsigned char *keyid,
int keyidlen)
{
PKCS12_SAFEBAG *bag = NULL;
/* Add user certificate */
if ((bag = PKCS12_SAFEBAG_create_cert(cert)) == NULL)
goto err;
if (name != NULL && !PKCS12_add_friendlyname(bag, name, namelen))
goto err;
if (keyid != NULL && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
goto err;
if (!pkcs12_add_bag(pbags, bag))
goto err;
return bag;
err:
PKCS12_SAFEBAG_free(bag);
return NULL;
}
PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
{
char *name = NULL;
int namelen = -1;
unsigned char *keyid = NULL;
int keyidlen = -1;
/*
* Use friendlyName and localKeyID in certificate. (if present)
*/
name = (char *)X509_alias_get0(cert, &namelen);
keyid = X509_keyid_get0(cert, &keyidlen);
return pkcs12_add_cert_bag(pbags, cert, name, namelen, keyid, keyidlen);
}
PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
EVP_PKEY *key, int key_usage, int iter,
int nid_key, const char *pass,
OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS12_SAFEBAG *bag = NULL;
PKCS8_PRIV_KEY_INFO *p8 = NULL;
/* Make a PKCS#8 structure */
if ((p8 = EVP_PKEY2PKCS8(key)) == NULL)
goto err;
- if (key_usage && !PKCS8_add_keyusage(p8, key_usage))
+ if (key_usage && !PKCS8_add_keyusage(p8, key_usage)) {
+ PKCS8_PRIV_KEY_INFO_free(p8);
goto err;
+ }
if (nid_key != -1) {
/* This call does not take ownership of p8 */
bag = PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(nid_key, pass, -1, NULL, 0,
iter, p8, ctx, propq);
} else {
bag = PKCS12_SAFEBAG_create0_p8inf(p8);
if (bag != NULL)
p8 = NULL; /* bag takes ownership of p8 */
}
/* This does not need to be in the error path */
if (p8 != NULL)
PKCS8_PRIV_KEY_INFO_free(p8);
if (bag == NULL || !pkcs12_add_bag(pbags, bag))
goto err;
return bag;
err:
PKCS12_SAFEBAG_free(bag);
return NULL;
}
PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
EVP_PKEY *key, int key_usage, int iter,
int nid_key, const char *pass)
{
return PKCS12_add_key_ex(pbags, key, key_usage, iter, nid_key, pass,
NULL, NULL);
}
PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags,
int nid_type, const unsigned char *value, int len)
{
PKCS12_SAFEBAG *bag = NULL;
/* Add secret, storing the value as an octet string */
if ((bag = PKCS12_SAFEBAG_create_secret(nid_type, V_ASN1_OCTET_STRING, value, len)) == NULL)
goto err;
if (!pkcs12_add_bag(pbags, bag))
goto err;
return bag;
err:
PKCS12_SAFEBAG_free(bag);
return NULL;
}
int PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
int nid_safe, int iter, const char *pass,
OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS7 *p7 = NULL;
int free_safes = 0;
if (*psafes == NULL) {
*psafes = sk_PKCS7_new_null();
if (*psafes == NULL)
return 0;
free_safes = 1;
}
if (nid_safe == 0)
#ifdef OPENSSL_NO_RC2
nid_safe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
#else
nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC;
#endif
if (nid_safe == -1)
p7 = PKCS12_pack_p7data(bags);
else
p7 = PKCS12_pack_p7encdata_ex(nid_safe, pass, -1, NULL, 0, iter, bags, ctx, propq);
if (p7 == NULL)
goto err;
if (!sk_PKCS7_push(*psafes, p7))
goto err;
return 1;
err:
if (free_safes) {
sk_PKCS7_free(*psafes);
*psafes = NULL;
}
PKCS7_free(p7);
return 0;
}
int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
int nid_safe, int iter, const char *pass)
{
return PKCS12_add_safe_ex(psafes, bags, nid_safe, iter, pass, NULL, NULL);
}
static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
PKCS12_SAFEBAG *bag)
{
int free_bags = 0;
if (pbags == NULL)
return 1;
if (*pbags == NULL) {
*pbags = sk_PKCS12_SAFEBAG_new_null();
if (*pbags == NULL)
return 0;
free_bags = 1;
}
if (!sk_PKCS12_SAFEBAG_push(*pbags, bag)) {
if (free_bags) {
sk_PKCS12_SAFEBAG_free(*pbags);
*pbags = NULL;
}
return 0;
}
return 1;
}
PKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int nid_p7,
OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS12 *p12;
if (nid_p7 <= 0)
nid_p7 = NID_pkcs7_data;
p12 = PKCS12_init_ex(nid_p7, ctx, propq);
if (p12 == NULL)
return NULL;
if (!PKCS12_pack_authsafes(p12, safes)) {
PKCS12_free(p12);
return NULL;
}
return p12;
}
PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
{
return PKCS12_add_safes_ex(safes, nid_p7, NULL, NULL);
}
diff --git a/crypto/openssl/crypto/pkcs7/pk7_doit.c b/crypto/openssl/crypto/pkcs7/pk7_doit.c
index d7791e5c4f47..e9de097da186 100644
--- a/crypto/openssl/crypto/pkcs7/pk7_doit.c
+++ b/crypto/openssl/crypto/pkcs7/pk7_doit.c
@@ -1,1267 +1,1267 @@
/*
* Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/rand.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include "internal/cryptlib.h"
#include "internal/sizes.h"
#include "pk7_local.h"
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
void *value);
static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid);
int PKCS7_type_is_other(PKCS7 *p7)
{
int isOther = 1;
int nid = OBJ_obj2nid(p7->type);
switch (nid) {
case NID_pkcs7_data:
case NID_pkcs7_signed:
case NID_pkcs7_enveloped:
case NID_pkcs7_signedAndEnveloped:
case NID_pkcs7_digest:
case NID_pkcs7_encrypted:
isOther = 0;
break;
default:
isOther = 1;
}
return isOther;
}
ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
{
if (PKCS7_type_is_data(p7))
return p7->d.data;
if (PKCS7_type_is_other(p7) && p7->d.other
&& (p7->d.other->type == V_ASN1_OCTET_STRING))
return p7->d.other->value.octet_string;
return NULL;
}
static int pkcs7_bio_add_digest(BIO **pbio, X509_ALGOR *alg,
const PKCS7_CTX *ctx)
{
BIO *btmp;
char name[OSSL_MAX_NAME_SIZE];
EVP_MD *fetched = NULL;
const EVP_MD *md;
if ((btmp = BIO_new(BIO_f_md())) == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
OBJ_obj2txt(name, sizeof(name), alg->algorithm, 0);
(void)ERR_set_mark();
fetched = EVP_MD_fetch(ossl_pkcs7_ctx_get0_libctx(ctx), name,
ossl_pkcs7_ctx_get0_propq(ctx));
if (fetched != NULL)
md = fetched;
else
md = EVP_get_digestbyname(name);
if (md == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_DIGEST_TYPE);
goto err;
}
(void)ERR_pop_to_mark();
if (BIO_set_md(btmp, md) <= 0) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
EVP_MD_free(fetched);
goto err;
}
EVP_MD_free(fetched);
if (*pbio == NULL)
*pbio = btmp;
else if (!BIO_push(*pbio, btmp)) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
btmp = NULL;
return 1;
err:
BIO_free(btmp);
return 0;
}
static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
unsigned char *key, int keylen)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
unsigned char *ek = NULL;
int ret = 0;
size_t eklen;
const PKCS7_CTX *ctx = ri->ctx;
pkey = X509_get0_pubkey(ri->cert);
if (pkey == NULL)
return 0;
pctx = EVP_PKEY_CTX_new_from_pkey(ossl_pkcs7_ctx_get0_libctx(ctx), pkey,
ossl_pkcs7_ctx_get0_propq(ctx));
if (pctx == NULL)
return 0;
if (EVP_PKEY_encrypt_init(pctx) <= 0)
goto err;
if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0)
goto err;
ek = OPENSSL_malloc(eklen);
if (ek == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0)
goto err;
ASN1_STRING_set0(ri->enc_key, ek, eklen);
ek = NULL;
ret = 1;
err:
EVP_PKEY_CTX_free(pctx);
OPENSSL_free(ek);
return ret;
}
static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey,
size_t fixlen)
{
EVP_PKEY_CTX *pctx = NULL;
unsigned char *ek = NULL;
size_t eklen;
int ret = -1;
const PKCS7_CTX *ctx = ri->ctx;
pctx = EVP_PKEY_CTX_new_from_pkey(ossl_pkcs7_ctx_get0_libctx(ctx), pkey,
ossl_pkcs7_ctx_get0_propq(ctx));
if (pctx == NULL)
return -1;
if (EVP_PKEY_decrypt_init(pctx) <= 0)
goto err;
if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
ri->enc_key->data, ri->enc_key->length) <= 0)
goto err;
ek = OPENSSL_malloc(eklen);
if (ek == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_decrypt(pctx, ek, &eklen,
ri->enc_key->data, ri->enc_key->length) <= 0
|| eklen == 0
|| (fixlen != 0 && eklen != fixlen)) {
ret = 0;
ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB);
goto err;
}
ret = 1;
OPENSSL_clear_free(*pek, *peklen);
*pek = ek;
*peklen = eklen;
err:
EVP_PKEY_CTX_free(pctx);
if (!ret)
OPENSSL_free(ek);
return ret;
}
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
{
int i;
BIO *out = NULL, *btmp = NULL;
X509_ALGOR *xa = NULL;
EVP_CIPHER *fetched_cipher = NULL;
const EVP_CIPHER *cipher;
const EVP_CIPHER *evp_cipher = NULL;
STACK_OF(X509_ALGOR) *md_sk = NULL;
STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
X509_ALGOR *xalg = NULL;
PKCS7_RECIP_INFO *ri = NULL;
ASN1_OCTET_STRING *os = NULL;
const PKCS7_CTX *p7_ctx;
OSSL_LIB_CTX *libctx;
const char *propq;
if (p7 == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return NULL;
}
p7_ctx = ossl_pkcs7_get0_ctx(p7);
libctx = ossl_pkcs7_ctx_get0_libctx(p7_ctx);
propq = ossl_pkcs7_ctx_get0_propq(p7_ctx);
/*
* The content field in the PKCS7 ContentInfo is optional, but that really
* only applies to inner content (precisely, detached signatures).
*
* When reading content, missing outer content is therefore treated as an
* error.
*
* When creating content, PKCS7_content_new() must be called before
* calling this method, so a NULL p7->d is always an error.
*/
if (p7->d.ptr == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return NULL;
}
i = OBJ_obj2nid(p7->type);
p7->state = PKCS7_S_HEADER;
switch (i) {
case NID_pkcs7_signed:
md_sk = p7->d.sign->md_algs;
os = PKCS7_get_octet_string(p7->d.sign->contents);
break;
case NID_pkcs7_signedAndEnveloped:
rsk = p7->d.signed_and_enveloped->recipientinfo;
md_sk = p7->d.signed_and_enveloped->md_algs;
xalg = p7->d.signed_and_enveloped->enc_data->algorithm;
evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher;
if (evp_cipher == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_NOT_INITIALIZED);
goto err;
}
break;
case NID_pkcs7_enveloped:
rsk = p7->d.enveloped->recipientinfo;
xalg = p7->d.enveloped->enc_data->algorithm;
evp_cipher = p7->d.enveloped->enc_data->cipher;
if (evp_cipher == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_NOT_INITIALIZED);
goto err;
}
break;
case NID_pkcs7_digest:
xa = p7->d.digest->md;
os = PKCS7_get_octet_string(p7->d.digest->contents);
break;
case NID_pkcs7_data:
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++)
if (!pkcs7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i), p7_ctx))
goto err;
if (xa && !pkcs7_bio_add_digest(&out, xa, p7_ctx))
goto err;
if (evp_cipher != NULL) {
unsigned char key[EVP_MAX_KEY_LENGTH];
unsigned char iv[EVP_MAX_IV_LENGTH];
int keylen, ivlen;
EVP_CIPHER_CTX *ctx;
if ((btmp = BIO_new(BIO_f_cipher())) == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
BIO_get_cipher_ctx(btmp, &ctx);
keylen = EVP_CIPHER_get_key_length(evp_cipher);
ivlen = EVP_CIPHER_get_iv_length(evp_cipher);
xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_get_type(evp_cipher));
if (ivlen > 0)
if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0)
goto err;
(void)ERR_set_mark();
fetched_cipher = EVP_CIPHER_fetch(libctx,
EVP_CIPHER_get0_name(evp_cipher),
propq);
(void)ERR_pop_to_mark();
if (fetched_cipher != NULL)
cipher = fetched_cipher;
else
cipher = evp_cipher;
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1) <= 0)
goto err;
EVP_CIPHER_free(fetched_cipher);
fetched_cipher = NULL;
if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
goto err;
if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
goto err;
if (ivlen > 0) {
if (xalg->parameter == NULL) {
xalg->parameter = ASN1_TYPE_new();
if (xalg->parameter == NULL)
goto err;
}
if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) <= 0)
goto err;
}
/* Lets do the pub key stuff :-) */
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
if (pkcs7_encode_rinfo(ri, key, keylen) <= 0)
goto err;
}
OPENSSL_cleanse(key, keylen);
if (out == NULL)
out = btmp;
else
BIO_push(out, btmp);
btmp = NULL;
}
if (bio == NULL) {
if (PKCS7_is_detached(p7)) {
bio = BIO_new(BIO_s_null());
} else if (os && os->length > 0) {
bio = BIO_new_mem_buf(os->data, os->length);
} else {
bio = BIO_new(BIO_s_mem());
if (bio == NULL)
goto err;
BIO_set_mem_eof_return(bio, 0);
}
if (bio == NULL)
goto err;
}
if (out)
BIO_push(out, bio);
else
out = bio;
return out;
err:
EVP_CIPHER_free(fetched_cipher);
BIO_free_all(out);
BIO_free_all(btmp);
return NULL;
}
static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
{
int ret;
ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
X509_get_issuer_name(pcert));
if (ret)
return ret;
return ASN1_INTEGER_cmp(X509_get0_serialNumber(pcert),
ri->issuer_and_serial->serial);
}
/* int */
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
{
int i, len;
BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL;
X509_ALGOR *xa;
ASN1_OCTET_STRING *data_body = NULL;
EVP_MD *evp_md = NULL;
const EVP_MD *md;
EVP_CIPHER *evp_cipher = NULL;
const EVP_CIPHER *cipher = NULL;
EVP_CIPHER_CTX *evp_ctx = NULL;
X509_ALGOR *enc_alg = NULL;
STACK_OF(X509_ALGOR) *md_sk = NULL;
STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
PKCS7_RECIP_INFO *ri = NULL;
unsigned char *ek = NULL, *tkey = NULL;
int eklen = 0, tkeylen = 0;
char name[OSSL_MAX_NAME_SIZE];
const PKCS7_CTX *p7_ctx;
OSSL_LIB_CTX *libctx;
const char *propq;
if (p7 == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return NULL;
}
p7_ctx = ossl_pkcs7_get0_ctx(p7);
libctx = ossl_pkcs7_ctx_get0_libctx(p7_ctx);
propq = ossl_pkcs7_ctx_get0_propq(p7_ctx);
if (p7->d.ptr == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return NULL;
}
i = OBJ_obj2nid(p7->type);
p7->state = PKCS7_S_HEADER;
switch (i) {
case NID_pkcs7_signed:
/*
* p7->d.sign->contents is a PKCS7 structure consisting of a contentType
* field and optional content.
* data_body is NULL if that structure has no (=detached) content
* or if the contentType is wrong (i.e., not "data").
*/
data_body = PKCS7_get_octet_string(p7->d.sign->contents);
if (!PKCS7_is_detached(p7) && data_body == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_SIGNED_DATA_TYPE);
goto err;
}
md_sk = p7->d.sign->md_algs;
break;
case NID_pkcs7_signedAndEnveloped:
rsk = p7->d.signed_and_enveloped->recipientinfo;
md_sk = p7->d.signed_and_enveloped->md_algs;
/* data_body is NULL if the optional EncryptedContent is missing. */
data_body = p7->d.signed_and_enveloped->enc_data->enc_data;
enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm;
OBJ_obj2txt(name, sizeof(name), enc_alg->algorithm, 0);
(void)ERR_set_mark();
evp_cipher = EVP_CIPHER_fetch(libctx, name, propq);
if (evp_cipher != NULL)
cipher = evp_cipher;
else
cipher = EVP_get_cipherbyname(name);
if (cipher == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
goto err;
}
(void)ERR_pop_to_mark();
break;
case NID_pkcs7_enveloped:
rsk = p7->d.enveloped->recipientinfo;
enc_alg = p7->d.enveloped->enc_data->algorithm;
/* data_body is NULL if the optional EncryptedContent is missing. */
data_body = p7->d.enveloped->enc_data->enc_data;
OBJ_obj2txt(name, sizeof(name), enc_alg->algorithm, 0);
(void)ERR_set_mark();
evp_cipher = EVP_CIPHER_fetch(libctx, name, propq);
if (evp_cipher != NULL)
cipher = evp_cipher;
else
cipher = EVP_get_cipherbyname(name);
if (cipher == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
goto err;
}
(void)ERR_pop_to_mark();
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
/* Detached content must be supplied via in_bio instead. */
if (data_body == NULL && in_bio == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
goto err;
}
/* We will be checking the signature */
if (md_sk != NULL) {
for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) {
xa = sk_X509_ALGOR_value(md_sk, i);
if ((btmp = BIO_new(BIO_f_md())) == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
OBJ_obj2txt(name, sizeof(name), xa->algorithm, 0);
(void)ERR_set_mark();
evp_md = EVP_MD_fetch(libctx, name, propq);
if (evp_md != NULL)
md = evp_md;
else
md = EVP_get_digestbyname(name);
if (md == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_DIGEST_TYPE);
goto err;
}
(void)ERR_pop_to_mark();
if (BIO_set_md(btmp, md) <= 0) {
EVP_MD_free(evp_md);
ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
EVP_MD_free(evp_md);
if (out == NULL)
out = btmp;
else
BIO_push(out, btmp);
btmp = NULL;
}
}
if (cipher != NULL) {
if ((etmp = BIO_new(BIO_f_cipher())) == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
/*
* It was encrypted, we need to decrypt the secret key with the
* private key
*/
/*
* Find the recipientInfo which matches the passed certificate (if
* any)
*/
if (pcert) {
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
if (!pkcs7_cmp_ri(ri, pcert))
break;
ri = NULL;
}
if (ri == NULL) {
ERR_raise(ERR_LIB_PKCS7,
PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
goto err;
}
}
/* If we haven't got a certificate try each ri in turn */
if (pcert == NULL) {
/*
* Always attempt to decrypt all rinfo even after success as a
* defence against MMA timing attacks.
*/
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
ri->ctx = p7_ctx;
if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey,
EVP_CIPHER_get_key_length(cipher)) < 0)
goto err;
ERR_clear_error();
}
} else {
ri->ctx = p7_ctx;
/* Only exit on fatal errors, not decrypt failure */
if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0)
goto err;
ERR_clear_error();
}
evp_ctx = NULL;
BIO_get_cipher_ctx(etmp, &evp_ctx);
if (EVP_CipherInit_ex(evp_ctx, cipher, NULL, NULL, NULL, 0) <= 0)
goto err;
if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) <= 0)
goto err;
/* Generate random key as MMA defence */
len = EVP_CIPHER_CTX_get_key_length(evp_ctx);
if (len <= 0)
goto err;
tkeylen = (size_t)len;
tkey = OPENSSL_malloc(tkeylen);
if (tkey == NULL)
goto err;
if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
goto err;
if (ek == NULL) {
ek = tkey;
eklen = tkeylen;
tkey = NULL;
}
if (eklen != EVP_CIPHER_CTX_get_key_length(evp_ctx)) {
/*
* Some S/MIME clients don't use the same key and effective key
* length. The key length is determined by the size of the
* decrypted RSA key.
*/
if (EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen) <= 0) {
/* Use random key as MMA defence */
OPENSSL_clear_free(ek, eklen);
ek = tkey;
eklen = tkeylen;
tkey = NULL;
}
}
/* Clear errors so we don't leak information useful in MMA */
ERR_clear_error();
if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0)
goto err;
OPENSSL_clear_free(ek, eklen);
ek = NULL;
OPENSSL_clear_free(tkey, tkeylen);
tkey = NULL;
if (out == NULL)
out = etmp;
else
BIO_push(out, etmp);
etmp = NULL;
}
if (in_bio != NULL) {
bio = in_bio;
} else {
if (data_body->length > 0)
bio = BIO_new_mem_buf(data_body->data, data_body->length);
else {
bio = BIO_new(BIO_s_mem());
if (bio == NULL)
goto err;
BIO_set_mem_eof_return(bio, 0);
}
if (bio == NULL)
goto err;
}
BIO_push(out, bio);
bio = NULL;
EVP_CIPHER_free(evp_cipher);
return out;
err:
EVP_CIPHER_free(evp_cipher);
OPENSSL_clear_free(ek, eklen);
OPENSSL_clear_free(tkey, tkeylen);
BIO_free_all(out);
BIO_free_all(btmp);
BIO_free_all(etmp);
BIO_free_all(bio);
return NULL;
}
static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
{
for (;;) {
bio = BIO_find_type(bio, BIO_TYPE_MD);
if (bio == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
return NULL;
}
BIO_get_md_ctx(bio, pmd);
if (*pmd == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_INTERNAL_ERROR);
return NULL;
}
if (EVP_MD_CTX_get_type(*pmd) == nid)
return bio;
bio = BIO_next(bio);
}
return NULL;
}
static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx)
{
unsigned char md_data[EVP_MAX_MD_SIZE];
unsigned int md_len;
/* Add signing time if not already present */
if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) {
if (!PKCS7_add0_attrib_signing_time(si, NULL)) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
}
/* Add digest */
if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB);
return 0;
}
if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
/* Now sign the attributes */
if (!PKCS7_SIGNER_INFO_sign(si))
return 0;
return 1;
}
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
{
int ret = 0;
int i, j;
BIO *btmp;
PKCS7_SIGNER_INFO *si;
EVP_MD_CTX *mdc, *ctx_tmp;
STACK_OF(X509_ATTRIBUTE) *sk;
STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
ASN1_OCTET_STRING *os = NULL;
const PKCS7_CTX *p7_ctx;
if (p7 == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return 0;
}
p7_ctx = ossl_pkcs7_get0_ctx(p7);
if (p7->d.ptr == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return 0;
}
ctx_tmp = EVP_MD_CTX_new();
if (ctx_tmp == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
i = OBJ_obj2nid(p7->type);
p7->state = PKCS7_S_HEADER;
switch (i) {
case NID_pkcs7_data:
os = p7->d.data;
break;
case NID_pkcs7_signedAndEnveloped:
/* XXXXXXXXXXXXXXXX */
si_sk = p7->d.signed_and_enveloped->signer_info;
os = p7->d.signed_and_enveloped->enc_data->enc_data;
if (os == NULL) {
os = ASN1_OCTET_STRING_new();
if (os == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
p7->d.signed_and_enveloped->enc_data->enc_data = os;
}
break;
case NID_pkcs7_enveloped:
/* XXXXXXXXXXXXXXXX */
os = p7->d.enveloped->enc_data->enc_data;
if (os == NULL) {
os = ASN1_OCTET_STRING_new();
if (os == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
p7->d.enveloped->enc_data->enc_data = os;
}
break;
case NID_pkcs7_signed:
si_sk = p7->d.sign->signer_info;
os = PKCS7_get_octet_string(p7->d.sign->contents);
/* If detached data then the content is excluded */
if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
ASN1_OCTET_STRING_free(os);
os = NULL;
p7->d.sign->contents->d.data = NULL;
}
break;
case NID_pkcs7_digest:
os = PKCS7_get_octet_string(p7->d.digest->contents);
/* If detached data then the content is excluded */
if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) {
ASN1_OCTET_STRING_free(os);
os = NULL;
p7->d.digest->contents->d.data = NULL;
}
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
if (si_sk != NULL) {
for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) {
si = sk_PKCS7_SIGNER_INFO_value(si_sk, i);
if (si->pkey == NULL)
continue;
j = OBJ_obj2nid(si->digest_alg->algorithm);
btmp = bio;
btmp = PKCS7_find_digest(&mdc, btmp, j);
if (btmp == NULL)
goto err;
/*
* We now have the EVP_MD_CTX, lets do the signing.
*/
if (!EVP_MD_CTX_copy_ex(ctx_tmp, mdc))
goto err;
sk = si->auth_attr;
/*
* If there are attributes, we add the digest attribute and only
* sign the attributes
*/
if (sk_X509_ATTRIBUTE_num(sk) > 0) {
if (!do_pkcs7_signed_attrib(si, ctx_tmp))
goto err;
} else {
unsigned char *abuf = NULL;
unsigned int abuflen;
abuflen = EVP_PKEY_get_size(si->pkey);
abuf = OPENSSL_malloc(abuflen);
if (abuf == NULL)
goto err;
if (!EVP_SignFinal_ex(ctx_tmp, abuf, &abuflen, si->pkey,
ossl_pkcs7_ctx_get0_libctx(p7_ctx),
ossl_pkcs7_ctx_get0_propq(p7_ctx))) {
OPENSSL_free(abuf);
ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB);
goto err;
}
ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
}
}
} else if (i == NID_pkcs7_digest) {
unsigned char md_data[EVP_MAX_MD_SIZE];
unsigned int md_len;
if (!PKCS7_find_digest(&mdc, bio,
OBJ_obj2nid(p7->d.digest->md->algorithm)))
goto err;
if (!EVP_DigestFinal_ex(mdc, md_data, &md_len))
goto err;
if (!ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len))
goto err;
}
if (!PKCS7_is_detached(p7)) {
/*
* NOTE(emilia): I think we only reach os == NULL here because detached
* digested data support is broken.
*/
if (os == NULL)
goto err;
if (!(os->flags & ASN1_STRING_FLAG_NDEF)) {
char *cont;
long contlen;
btmp = BIO_find_type(bio, BIO_TYPE_MEM);
if (btmp == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
goto err;
}
contlen = BIO_get_mem_data(btmp, &cont);
/*
* Mark the BIO read only then we can use its copy of the data
* instead of making an extra copy.
*/
BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
BIO_set_mem_eof_return(btmp, 0);
ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
}
}
ret = 1;
err:
EVP_MD_CTX_free(ctx_tmp);
return ret;
}
int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
{
EVP_MD_CTX *mctx;
EVP_PKEY_CTX *pctx = NULL;
unsigned char *abuf = NULL;
int alen;
size_t siglen;
const EVP_MD *md = NULL;
const PKCS7_CTX *ctx = si->ctx;
md = EVP_get_digestbyobj(si->digest_alg->algorithm);
if (md == NULL)
return 0;
mctx = EVP_MD_CTX_new();
if (mctx == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_DigestSignInit_ex(mctx, &pctx, EVP_MD_get0_name(md),
ossl_pkcs7_ctx_get0_libctx(ctx),
ossl_pkcs7_ctx_get0_propq(ctx), si->pkey,
NULL) <= 0)
goto err;
alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf,
ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
if (!abuf)
goto err;
if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0)
goto err;
OPENSSL_free(abuf);
abuf = NULL;
if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0)
goto err;
abuf = OPENSSL_malloc(siglen);
if (abuf == NULL)
goto err;
if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
goto err;
EVP_MD_CTX_free(mctx);
ASN1_STRING_set0(si->enc_digest, abuf, siglen);
return 1;
err:
OPENSSL_free(abuf);
EVP_MD_CTX_free(mctx);
return 0;
}
int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
PKCS7 *p7, PKCS7_SIGNER_INFO *si)
{
PKCS7_ISSUER_AND_SERIAL *ias;
int ret = 0, i;
STACK_OF(X509) *cert;
X509 *x509;
if (p7 == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return 0;
}
if (p7->d.ptr == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return 0;
}
if (PKCS7_type_is_signed(p7)) {
cert = p7->d.sign->cert;
} else if (PKCS7_type_is_signedAndEnveloped(p7)) {
cert = p7->d.signed_and_enveloped->cert;
} else {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE);
goto err;
}
/* XXXXXXXXXXXXXXXXXXXXXXX */
ias = si->issuer_and_serial;
x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial);
/* were we able to find the cert in passed to us */
if (x509 == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
goto err;
}
/* Lets verify */
if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB);
goto err;
}
X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
i = X509_verify_cert(ctx);
if (i <= 0) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB);
goto err;
}
return PKCS7_signatureVerify(bio, p7, si, x509);
err:
return ret;
}
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
X509 *x509)
{
ASN1_OCTET_STRING *os;
EVP_MD_CTX *mdc_tmp, *mdc;
const EVP_MD *md;
EVP_MD *fetched_md = NULL;
int ret = 0, i;
int md_type;
STACK_OF(X509_ATTRIBUTE) *sk;
BIO *btmp;
EVP_PKEY *pkey;
+ unsigned char *abuf = NULL;
const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7);
OSSL_LIB_CTX *libctx = ossl_pkcs7_ctx_get0_libctx(ctx);
const char *propq = ossl_pkcs7_ctx_get0_propq(ctx);
mdc_tmp = EVP_MD_CTX_new();
if (mdc_tmp == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE);
goto err;
}
md_type = OBJ_obj2nid(si->digest_alg->algorithm);
btmp = bio;
for (;;) {
if ((btmp == NULL) ||
((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
goto err;
}
BIO_get_md_ctx(btmp, &mdc);
if (mdc == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_INTERNAL_ERROR);
goto err;
}
if (EVP_MD_CTX_get_type(mdc) == md_type)
break;
/*
* Workaround for some broken clients that put the signature OID
* instead of the digest OID in digest_alg->algorithm
*/
if (EVP_MD_get_pkey_type(EVP_MD_CTX_get0_md(mdc)) == md_type)
break;
btmp = BIO_next(btmp);
}
/*
* mdc is the digest ctx that we want, unless there are attributes, in
* which case the digest is the signed attributes
*/
if (!EVP_MD_CTX_copy_ex(mdc_tmp, mdc))
goto err;
sk = si->auth_attr;
if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) {
- unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
+ unsigned char md_dat[EVP_MAX_MD_SIZE];
unsigned int md_len;
int alen;
ASN1_OCTET_STRING *message_digest;
if (!EVP_DigestFinal_ex(mdc_tmp, md_dat, &md_len))
goto err;
message_digest = PKCS7_digest_from_attributes(sk);
if (!message_digest) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
goto err;
}
if ((message_digest->length != (int)md_len) ||
(memcmp(message_digest->data, md_dat, md_len))) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_DIGEST_FAILURE);
ret = -1;
goto err;
}
(void)ERR_set_mark();
fetched_md = EVP_MD_fetch(libctx, OBJ_nid2sn(md_type), propq);
if (fetched_md != NULL)
md = fetched_md;
else
md = EVP_get_digestbynid(md_type);
if (md == NULL || !EVP_VerifyInit_ex(mdc_tmp, md, NULL)) {
(void)ERR_clear_last_mark();
goto err;
}
(void)ERR_pop_to_mark();
alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
if (alen <= 0) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB);
ret = -1;
goto err;
}
if (!EVP_VerifyUpdate(mdc_tmp, abuf, alen))
goto err;
-
- OPENSSL_free(abuf);
}
os = si->enc_digest;
pkey = X509_get0_pubkey(x509);
if (pkey == NULL) {
ret = -1;
goto err;
}
i = EVP_VerifyFinal_ex(mdc_tmp, os->data, os->length, pkey, libctx, propq);
if (i <= 0) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE);
ret = -1;
goto err;
}
ret = 1;
err:
+ OPENSSL_free(abuf);
EVP_MD_CTX_free(mdc_tmp);
EVP_MD_free(fetched_md);
return ret;
}
PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
{
STACK_OF(PKCS7_RECIP_INFO) *rsk;
PKCS7_RECIP_INFO *ri;
int i;
i = OBJ_obj2nid(p7->type);
if (i != NID_pkcs7_signedAndEnveloped)
return NULL;
if (p7->d.signed_and_enveloped == NULL)
return NULL;
rsk = p7->d.signed_and_enveloped->recipientinfo;
if (rsk == NULL)
return NULL;
if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx)
return NULL;
ri = sk_PKCS7_RECIP_INFO_value(rsk, idx);
return ri->issuer_and_serial;
}
ASN1_TYPE *PKCS7_get_signed_attribute(const PKCS7_SIGNER_INFO *si, int nid)
{
return get_attribute(si->auth_attr, nid);
}
ASN1_TYPE *PKCS7_get_attribute(const PKCS7_SIGNER_INFO *si, int nid)
{
return get_attribute(si->unauth_attr, nid);
}
static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid)
{
int idx;
X509_ATTRIBUTE *xa;
idx = X509at_get_attr_by_NID(sk, nid, -1);
xa = X509at_get_attr(sk, idx);
return X509_ATTRIBUTE_get0_type(xa, 0);
}
ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
{
ASN1_TYPE *astype;
if ((astype = get_attribute(sk, NID_pkcs9_messageDigest)) == NULL)
return NULL;
return astype->value.octet_string;
}
int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
STACK_OF(X509_ATTRIBUTE) *sk)
{
int i;
sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free);
p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk);
if (p7si->auth_attr == NULL)
return 0;
for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i,
X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value
(sk, i))))
== NULL)
return 0;
}
return 1;
}
int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,
STACK_OF(X509_ATTRIBUTE) *sk)
{
int i;
sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free);
p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk);
if (p7si->unauth_attr == NULL)
return 0;
for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i,
X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value
(sk, i))))
== NULL)
return 0;
}
return 1;
}
int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
void *value)
{
return add_attribute(&(p7si->auth_attr), nid, atrtype, value);
}
int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
void *value)
{
return add_attribute(&(p7si->unauth_attr), nid, atrtype, value);
}
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
void *value)
{
X509_ATTRIBUTE *attr = NULL;
int i, n;
if (*sk == NULL) {
if ((*sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
return 0;
}
n = sk_X509_ATTRIBUTE_num(*sk);
for (i = 0; i < n; i++) {
attr = sk_X509_ATTRIBUTE_value(*sk, i);
if (OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)) == nid)
goto end;
}
if (!sk_X509_ATTRIBUTE_push(*sk, NULL))
return 0;
end:
attr = X509_ATTRIBUTE_create(nid, atrtype, value);
if (attr == NULL) {
if (i == n)
sk_X509_ATTRIBUTE_pop(*sk);
return 0;
}
X509_ATTRIBUTE_free(sk_X509_ATTRIBUTE_value(*sk, i));
(void) sk_X509_ATTRIBUTE_set(*sk, i, attr);
return 1;
}
diff --git a/crypto/openssl/crypto/pkcs7/pk7_lib.c b/crypto/openssl/crypto/pkcs7/pk7_lib.c
index 5ce591f758f7..bdd620526969 100644
--- a/crypto/openssl/crypto/pkcs7/pk7_lib.c
+++ b/crypto/openssl/crypto/pkcs7/pk7_lib.c
@@ -1,753 +1,758 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/pkcs7.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/x509.h" /* for sk_X509_add1_cert() */
#include "pk7_local.h"
long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
{
int nid;
long ret;
nid = OBJ_obj2nid(p7->type);
switch (cmd) {
/* NOTE(emilia): does not support detached digested data. */
case PKCS7_OP_SET_DETACHED_SIGNATURE:
if (nid == NID_pkcs7_signed) {
+ if (p7->d.sign == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
+ ret = 0;
+ break;
+ }
ret = p7->detached = (int)larg;
if (ret && PKCS7_type_is_data(p7->d.sign->contents)) {
ASN1_OCTET_STRING *os;
os = p7->d.sign->contents->d.data;
ASN1_OCTET_STRING_free(os);
p7->d.sign->contents->d.data = NULL;
}
} else {
ERR_raise(ERR_LIB_PKCS7,
PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
ret = 0;
}
break;
case PKCS7_OP_GET_DETACHED_SIGNATURE:
if (nid == NID_pkcs7_signed) {
if (p7->d.sign == NULL || p7->d.sign->contents->d.ptr == NULL)
ret = 1;
else
ret = 0;
p7->detached = ret;
} else {
ERR_raise(ERR_LIB_PKCS7,
PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
ret = 0;
}
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_OPERATION);
ret = 0;
}
return ret;
}
int PKCS7_content_new(PKCS7 *p7, int type)
{
PKCS7 *ret = NULL;
if ((ret = PKCS7_new()) == NULL)
goto err;
if (!PKCS7_set_type(ret, type))
goto err;
if (!PKCS7_set_content(p7, ret))
goto err;
return 1;
err:
PKCS7_free(ret);
return 0;
}
int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data)
{
int i;
i = OBJ_obj2nid(p7->type);
switch (i) {
case NID_pkcs7_signed:
PKCS7_free(p7->d.sign->contents);
p7->d.sign->contents = p7_data;
break;
case NID_pkcs7_digest:
PKCS7_free(p7->d.digest->contents);
p7->d.digest->contents = p7_data;
break;
case NID_pkcs7_data:
case NID_pkcs7_enveloped:
case NID_pkcs7_signedAndEnveloped:
case NID_pkcs7_encrypted:
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
return 1;
err:
return 0;
}
int PKCS7_set_type(PKCS7 *p7, int type)
{
ASN1_OBJECT *obj;
/*
* PKCS7_content_free(p7);
*/
obj = OBJ_nid2obj(type); /* will not fail */
switch (type) {
case NID_pkcs7_signed:
p7->type = obj;
if ((p7->d.sign = PKCS7_SIGNED_new()) == NULL)
goto err;
if (!ASN1_INTEGER_set(p7->d.sign->version, 1)) {
PKCS7_SIGNED_free(p7->d.sign);
p7->d.sign = NULL;
goto err;
}
break;
case NID_pkcs7_data:
p7->type = obj;
if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL)
goto err;
break;
case NID_pkcs7_signedAndEnveloped:
p7->type = obj;
if ((p7->d.signed_and_enveloped = PKCS7_SIGN_ENVELOPE_new())
== NULL)
goto err;
if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1))
goto err;
p7->d.signed_and_enveloped->enc_data->content_type
= OBJ_nid2obj(NID_pkcs7_data);
break;
case NID_pkcs7_enveloped:
p7->type = obj;
if ((p7->d.enveloped = PKCS7_ENVELOPE_new())
== NULL)
goto err;
if (!ASN1_INTEGER_set(p7->d.enveloped->version, 0))
goto err;
p7->d.enveloped->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data);
break;
case NID_pkcs7_encrypted:
p7->type = obj;
if ((p7->d.encrypted = PKCS7_ENCRYPT_new())
== NULL)
goto err;
if (!ASN1_INTEGER_set(p7->d.encrypted->version, 0))
goto err;
p7->d.encrypted->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data);
break;
case NID_pkcs7_digest:
p7->type = obj;
if ((p7->d.digest = PKCS7_DIGEST_new())
== NULL)
goto err;
if (!ASN1_INTEGER_set(p7->d.digest->version, 0))
goto err;
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
return 1;
err:
return 0;
}
int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other)
{
p7->type = OBJ_nid2obj(type);
p7->d.other = other;
return 1;
}
int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
{
int i, j;
ASN1_OBJECT *obj;
X509_ALGOR *alg;
STACK_OF(PKCS7_SIGNER_INFO) *signer_sk;
STACK_OF(X509_ALGOR) *md_sk;
i = OBJ_obj2nid(p7->type);
switch (i) {
case NID_pkcs7_signed:
signer_sk = p7->d.sign->signer_info;
md_sk = p7->d.sign->md_algs;
break;
case NID_pkcs7_signedAndEnveloped:
signer_sk = p7->d.signed_and_enveloped->signer_info;
md_sk = p7->d.signed_and_enveloped->md_algs;
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
obj = psi->digest_alg->algorithm;
/* If the digest is not currently listed, add it */
j = 0;
for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) {
alg = sk_X509_ALGOR_value(md_sk, i);
if (OBJ_cmp(obj, alg->algorithm) == 0) {
j = 1;
break;
}
}
if (!j) { /* we need to add another algorithm */
int nid;
if ((alg = X509_ALGOR_new()) == NULL
|| (alg->parameter = ASN1_TYPE_new()) == NULL) {
X509_ALGOR_free(alg);
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
* If there is a constant copy of the ASN1 OBJECT in libcrypto, then
* use that. Otherwise, use a dynamically duplicated copy
*/
if ((nid = OBJ_obj2nid(obj)) != NID_undef)
alg->algorithm = OBJ_nid2obj(nid);
else
alg->algorithm = OBJ_dup(obj);
alg->parameter->type = V_ASN1_NULL;
if (alg->algorithm == NULL || !sk_X509_ALGOR_push(md_sk, alg)) {
X509_ALGOR_free(alg);
return 0;
}
}
psi->ctx = ossl_pkcs7_get0_ctx(p7);
if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi))
return 0;
return 1;
}
int PKCS7_add_certificate(PKCS7 *p7, X509 *x509)
{
int i;
STACK_OF(X509) **sk;
i = OBJ_obj2nid(p7->type);
switch (i) {
case NID_pkcs7_signed:
sk = &(p7->d.sign->cert);
break;
case NID_pkcs7_signedAndEnveloped:
sk = &(p7->d.signed_and_enveloped->cert);
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
return ossl_x509_add_cert_new(sk, x509, X509_ADD_FLAG_UP_REF);
}
int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
{
int i;
STACK_OF(X509_CRL) **sk;
i = OBJ_obj2nid(p7->type);
switch (i) {
case NID_pkcs7_signed:
sk = &(p7->d.sign->crl);
break;
case NID_pkcs7_signedAndEnveloped:
sk = &(p7->d.signed_and_enveloped->crl);
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
if (*sk == NULL)
*sk = sk_X509_CRL_new_null();
if (*sk == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
X509_CRL_up_ref(crl);
if (!sk_X509_CRL_push(*sk, crl)) {
X509_CRL_free(crl);
return 0;
}
return 1;
}
static int pkcs7_ecdsa_or_dsa_sign_verify_setup(PKCS7_SIGNER_INFO *si,
int verify)
{
if (verify == 0) {
int snid, hnid;
X509_ALGOR *alg1, *alg2;
EVP_PKEY *pkey = si->pkey;
PKCS7_SIGNER_INFO_get0_algs(si, 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_get_id(pkey)))
return -1;
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
}
return 1;
}
static int pkcs7_rsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, int verify)
{
if (verify == 0) {
X509_ALGOR *alg = NULL;
PKCS7_SIGNER_INFO_get0_algs(si, NULL, NULL, &alg);
if (alg != NULL)
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
}
return 1;
}
int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
const EVP_MD *dgst)
{
int ret;
/* We now need to add another PKCS7_SIGNER_INFO entry */
if (!ASN1_INTEGER_set(p7i->version, 1))
goto err;
if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
X509_get_issuer_name(x509)))
goto err;
/*
* because ASN1_INTEGER_set is used to set a 'long' we will do things the
* ugly way.
*/
ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
if (!(p7i->issuer_and_serial->serial =
ASN1_INTEGER_dup(X509_get0_serialNumber(x509))))
goto err;
/* lets keep the pkey around for a while */
EVP_PKEY_up_ref(pkey);
p7i->pkey = pkey;
/* Set the algorithms */
X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_get_type(dgst)),
V_ASN1_NULL, NULL);
if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "DSA"))
return pkcs7_ecdsa_or_dsa_sign_verify_setup(p7i, 0);
if (EVP_PKEY_is_a(pkey, "RSA"))
return pkcs7_rsa_sign_verify_setup(p7i, 0);
if (pkey->ameth != NULL && pkey->ameth->pkey_ctrl != NULL) {
ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN, 0, p7i);
if (ret > 0)
return 1;
if (ret != -2) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_CTRL_FAILURE);
return 0;
}
}
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
err:
return 0;
}
PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey,
const EVP_MD *dgst)
{
PKCS7_SIGNER_INFO *si = NULL;
if (dgst == NULL) {
int def_nid;
if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0)
goto err;
dgst = EVP_get_digestbynid(def_nid);
if (dgst == NULL) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_DEFAULT_DIGEST);
goto err;
}
}
if ((si = PKCS7_SIGNER_INFO_new()) == NULL)
goto err;
if (PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst) <= 0)
goto err;
if (!PKCS7_add_signer(p7, si))
goto err;
return si;
err:
PKCS7_SIGNER_INFO_free(si);
return NULL;
}
static STACK_OF(X509) *pkcs7_get_signer_certs(const PKCS7 *p7)
{
if (p7->d.ptr == NULL)
return NULL;
if (PKCS7_type_is_signed(p7))
return p7->d.sign->cert;
if (PKCS7_type_is_signedAndEnveloped(p7))
return p7->d.signed_and_enveloped->cert;
return NULL;
}
static STACK_OF(PKCS7_RECIP_INFO) *pkcs7_get_recipient_info(const PKCS7 *p7)
{
if (p7->d.ptr == NULL)
return NULL;
if (PKCS7_type_is_signedAndEnveloped(p7))
return p7->d.signed_and_enveloped->recipientinfo;
if (PKCS7_type_is_enveloped(p7))
return p7->d.enveloped->recipientinfo;
return NULL;
}
/*
* Set up the library context into any loaded structure that needs it.
* i.e loaded X509 objects.
*/
void ossl_pkcs7_resolve_libctx(PKCS7 *p7)
{
int i;
const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7);
OSSL_LIB_CTX *libctx = ossl_pkcs7_ctx_get0_libctx(ctx);
const char *propq = ossl_pkcs7_ctx_get0_propq(ctx);
STACK_OF(PKCS7_RECIP_INFO) *rinfos;
STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
STACK_OF(X509) *certs;
if (ctx == NULL || p7->d.ptr == NULL)
return;
rinfos = pkcs7_get_recipient_info(p7);
sinfos = PKCS7_get_signer_info(p7);
certs = pkcs7_get_signer_certs(p7);
for (i = 0; i < sk_X509_num(certs); i++)
ossl_x509_set0_libctx(sk_X509_value(certs, i), libctx, propq);
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rinfos); i++) {
PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(rinfos, i);
ossl_x509_set0_libctx(ri->cert, libctx, propq);
}
for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
if (si != NULL)
si->ctx = ctx;
}
}
const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7)
{
return p7 != NULL ? &p7->ctx : NULL;
}
void ossl_pkcs7_set0_libctx(PKCS7 *p7, OSSL_LIB_CTX *ctx)
{
p7->ctx.libctx = ctx;
}
int ossl_pkcs7_set1_propq(PKCS7 *p7, const char *propq)
{
if (p7->ctx.propq != NULL) {
OPENSSL_free(p7->ctx.propq);
p7->ctx.propq = NULL;
}
if (propq != NULL) {
p7->ctx.propq = OPENSSL_strdup(propq);
if (p7->ctx.propq == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
}
return 1;
}
int ossl_pkcs7_ctx_propagate(const PKCS7 *from, PKCS7 *to)
{
ossl_pkcs7_set0_libctx(to, from->ctx.libctx);
if (!ossl_pkcs7_set1_propq(to, from->ctx.propq))
return 0;
ossl_pkcs7_resolve_libctx(to);
return 1;
}
OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx)
{
return ctx != NULL ? ctx->libctx : NULL;
}
const char *ossl_pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx)
{
return ctx != NULL ? ctx->propq : NULL;
}
int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
{
if (PKCS7_type_is_digest(p7)) {
if ((p7->d.digest->md->parameter = ASN1_TYPE_new()) == NULL) {
ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
p7->d.digest->md->parameter->type = V_ASN1_NULL;
p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md));
return 1;
}
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 1;
}
STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7)
{
if (p7 == NULL || p7->d.ptr == NULL)
return NULL;
if (PKCS7_type_is_signed(p7)) {
return p7->d.sign->signer_info;
} else if (PKCS7_type_is_signedAndEnveloped(p7)) {
return p7->d.signed_and_enveloped->signer_info;
} else
return NULL;
}
void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
X509_ALGOR **pdig, X509_ALGOR **psig)
{
if (pk)
*pk = si->pkey;
if (pdig)
*pdig = si->digest_alg;
if (psig)
*psig = si->digest_enc_alg;
}
void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc)
{
if (penc)
*penc = ri->key_enc_algor;
}
PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
{
PKCS7_RECIP_INFO *ri;
if ((ri = PKCS7_RECIP_INFO_new()) == NULL)
goto err;
if (PKCS7_RECIP_INFO_set(ri, x509) <= 0)
goto err;
if (!PKCS7_add_recipient_info(p7, ri))
goto err;
ri->ctx = ossl_pkcs7_get0_ctx(p7);
return ri;
err:
PKCS7_RECIP_INFO_free(ri);
return NULL;
}
int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri)
{
int i;
STACK_OF(PKCS7_RECIP_INFO) *sk;
i = OBJ_obj2nid(p7->type);
switch (i) {
case NID_pkcs7_signedAndEnveloped:
sk = p7->d.signed_and_enveloped->recipientinfo;
break;
case NID_pkcs7_enveloped:
sk = p7->d.enveloped->recipientinfo;
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
if (!sk_PKCS7_RECIP_INFO_push(sk, ri))
return 0;
return 1;
}
static int pkcs7_rsa_encrypt_decrypt_setup(PKCS7_RECIP_INFO *ri, int decrypt)
{
X509_ALGOR *alg = NULL;
if (decrypt == 0) {
PKCS7_RECIP_INFO_get0_alg(ri, &alg);
if (alg != NULL)
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
}
return 1;
}
int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509)
{
int ret;
EVP_PKEY *pkey = NULL;
if (!ASN1_INTEGER_set(p7i->version, 0))
return 0;
if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
X509_get_issuer_name(x509)))
return 0;
ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
if (!(p7i->issuer_and_serial->serial =
ASN1_INTEGER_dup(X509_get0_serialNumber(x509))))
return 0;
pkey = X509_get0_pubkey(x509);
if (pkey == NULL)
return 0;
if (EVP_PKEY_is_a(pkey, "RSA-PSS"))
return -2;
if (EVP_PKEY_is_a(pkey, "RSA")) {
if (pkcs7_rsa_encrypt_decrypt_setup(p7i, 0) <= 0)
goto err;
goto finished;
}
if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) {
ERR_raise(ERR_LIB_PKCS7,
PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
goto err;
}
ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT, 0, p7i);
if (ret == -2) {
ERR_raise(ERR_LIB_PKCS7,
PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
goto err;
}
if (ret <= 0) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_ENCRYPTION_CTRL_FAILURE);
goto err;
}
finished:
X509_up_ref(x509);
p7i->cert = x509;
return 1;
err:
return 0;
}
X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
{
if (PKCS7_type_is_signed(p7))
return (X509_find_by_issuer_and_serial(p7->d.sign->cert,
si->issuer_and_serial->issuer,
si->
issuer_and_serial->serial));
else
return NULL;
}
int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher)
{
int i;
PKCS7_ENC_CONTENT *ec;
i = OBJ_obj2nid(p7->type);
switch (i) {
case NID_pkcs7_signedAndEnveloped:
ec = p7->d.signed_and_enveloped->enc_data;
break;
case NID_pkcs7_enveloped:
ec = p7->d.enveloped->enc_data;
break;
default:
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
/* Check cipher OID exists and has data in it */
i = EVP_CIPHER_get_type(cipher);
if (i == NID_undef) {
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
return 0;
}
ec->cipher = cipher;
ec->ctx = ossl_pkcs7_get0_ctx(p7);
return 1;
}
/* unfortunately cannot constify BIO_new_NDEF() due to this and CMS_stream() */
int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7)
{
ASN1_OCTET_STRING *os = NULL;
switch (OBJ_obj2nid(p7->type)) {
case NID_pkcs7_data:
os = p7->d.data;
break;
case NID_pkcs7_signedAndEnveloped:
os = p7->d.signed_and_enveloped->enc_data->enc_data;
if (os == NULL) {
os = ASN1_OCTET_STRING_new();
p7->d.signed_and_enveloped->enc_data->enc_data = os;
}
break;
case NID_pkcs7_enveloped:
os = p7->d.enveloped->enc_data->enc_data;
if (os == NULL) {
os = ASN1_OCTET_STRING_new();
p7->d.enveloped->enc_data->enc_data = os;
}
break;
case NID_pkcs7_signed:
os = p7->d.sign->contents->d.data;
break;
default:
os = NULL;
break;
}
if (os == NULL)
return 0;
os->flags |= ASN1_STRING_FLAG_NDEF;
*boundary = &os->data;
return 1;
}
diff --git a/crypto/openssl/crypto/sm2/sm2_sign.c b/crypto/openssl/crypto/sm2/sm2_sign.c
index 71ccfcfc4c3d..2097cd2fca86 100644
--- a/crypto/openssl/crypto/sm2/sm2_sign.c
+++ b/crypto/openssl/crypto/sm2/sm2_sign.c
@@ -1,524 +1,528 @@
/*
* Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/deprecated.h"
#include "crypto/sm2.h"
#include "crypto/sm2err.h"
#include "crypto/ec.h" /* ossl_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 ossl_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);
const EC_POINT *pubkey = EC_KEY_get0_public_key(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;
/* SM2 Signatures require a public key, check for it */
if (pubkey == NULL) {
ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER);
goto done;
}
hash = EVP_MD_CTX_new();
ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key));
if (hash == NULL || ctx == NULL) {
ERR_raise(ERR_LIB_SM2, 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) {
ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!EVP_DigestInit(hash, digest)) {
ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
/* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */
if (id_len >= (UINT16_MAX / 8)) {
/* too large */
ERR_raise(ERR_LIB_SM2, SM2_R_ID_TOO_LARGE);
goto done;
}
entl = (uint16_t)(8 * id_len);
e_byte = entl >> 8;
if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
e_byte = entl & 0xFF;
if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) {
ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
if (!EC_GROUP_get_curve(group, p, a, b, ctx)) {
ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
goto done;
}
p_bytes = BN_num_bytes(p);
buf = OPENSSL_zalloc(p_bytes);
if (buf == NULL) {
ERR_raise(ERR_LIB_SM2, 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,
pubkey,
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)) {
ERR_raise(ERR_LIB_SM2, 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_get_size(digest);
uint8_t *z = NULL;
BIGNUM *e = NULL;
EVP_MD *fetched_digest = NULL;
OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
const char *propq = ossl_ec_key_get0_propq(key);
if (md_size < 0) {
ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST);
goto done;
}
z = OPENSSL_zalloc(md_size);
if (hash == NULL || z == NULL) {
ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq);
if (fetched_digest == NULL) {
ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
if (!ossl_sm2_compute_z_digest(z, fetched_digest, id, id_len, key)) {
/* SM2err already called */
goto done;
}
if (!EVP_DigestInit(hash, fetched_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)) {
ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
e = BN_bin2bn(z, md_size, NULL);
if (e == NULL)
ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
done:
EVP_MD_free(fetched_digest);
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;
OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
kG = EC_POINT_new(group);
ctx = BN_CTX_new_ex(libctx);
if (kG == NULL || ctx == NULL) {
ERR_raise(ERR_LIB_SM2, 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) {
ERR_raise(ERR_LIB_SM2, 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) {
ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
/*
* A3: Generate a random number k in [1,n-1] using random number generators;
* A4: Compute (x1,y1)=[k]G, and convert the type of data x1 to be integer
* as specified in clause 4.2.8 of GM/T 0003.1-2012;
* A5: Compute r=(e+x1) mod n. If r=0 or r+k=n, then go to A3;
* A6: Compute s=(1/(1+dA)*(k-r*dA)) mod n. If s=0, then go to A3;
* A7: Convert the type of data (r,s) to be bit strings according to the details
* in clause 4.2.2 of GM/T 0003.1-2012. Then the signature of message M is (r,s).
*/
for (;;) {
if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
ERR_raise(ERR_LIB_SM2, 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)) {
ERR_raise(ERR_LIB_SM2, 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)) {
ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
if (BN_cmp(rk, order) == 0)
continue;
if (!BN_add(s, dA, BN_value_one())
|| !ossl_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)) {
ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
/* try again if s == 0 */
if (BN_is_zero(s))
continue;
sig = ECDSA_SIG_new();
if (sig == NULL) {
ERR_raise(ERR_LIB_SM2, 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;
OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
ctx = BN_CTX_new_ex(libctx);
- pt = EC_POINT_new(group);
- if (ctx == NULL || pt == NULL) {
+ if (ctx == NULL) {
ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
-
BN_CTX_start(ctx);
t = BN_CTX_get(ctx);
x1 = BN_CTX_get(ctx);
if (x1 == NULL) {
ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
+ pt = EC_POINT_new(group);
+ if (pt == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
/*
* B1: verify whether r' in [1,n-1], verification failed if not
* B2: verify 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, verification 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) {
ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE);
goto done;
}
if (!BN_mod_add(t, r, s, order, ctx)) {
ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
if (BN_is_zero(t)) {
ERR_raise(ERR_LIB_SM2, 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)) {
ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
goto done;
}
if (!BN_mod_add(t, e, x1, order, ctx)) {
ERR_raise(ERR_LIB_SM2, 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 *ossl_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 ossl_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 ossl_sm2_internal_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;
if (sig == NULL) {
ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER);
goto done;
}
e = BN_bin2bn(dgst, dgstlen, NULL);
if (e == NULL) {
ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
s = sm2_sig_gen(eckey, e);
if (s == NULL) {
ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
sigleni = i2d_ECDSA_SIG(s, &sig);
if (sigleni < 0) {
ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
*siglen = (unsigned int)sigleni;
ret = 1;
done:
ECDSA_SIG_free(s);
BN_free(e);
return ret;
}
int ossl_sm2_internal_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) {
ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) {
ERR_raise(ERR_LIB_SM2, 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) {
ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
goto done;
}
e = BN_bin2bn(dgst, dgstlen, NULL);
if (e == NULL) {
ERR_raise(ERR_LIB_SM2, 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/openssl/crypto/srp/srp_vfy.c b/crypto/openssl/crypto/srp/srp_vfy.c
index 96d511ffe636..4b842dfd9129 100644
--- a/crypto/openssl/crypto/srp/srp_vfy.c
+++ b/crypto/openssl/crypto/srp/srp_vfy.c
@@ -1,774 +1,776 @@
/*
* Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2004, EdelKey Project. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Christophe Renou and Peter Sylvester,
* for the EdelKey project.
*/
/* All the SRP APIs in this file are deprecated */
#define OPENSSL_SUPPRESS_DEPRECATED
#ifndef OPENSSL_NO_SRP
# include "internal/cryptlib.h"
# include "crypto/evp.h"
# include <openssl/sha.h>
# include <openssl/srp.h>
# include <openssl/evp.h>
# include <openssl/buffer.h>
# include <openssl/rand.h>
# include <openssl/txt_db.h>
# include <openssl/err.h>
# define SRP_RANDOM_SALT_LEN 20
# define MAX_LEN 2500
/*
* Note that SRP uses its own variant of base 64 encoding. A different base64
* alphabet is used and no padding '=' characters are added. Instead we pad to
* the front with 0 bytes and subsequently strip off leading encoded padding.
* This variant is used for compatibility with other SRP implementations -
* notably libsrp, but also others. It is also required for backwards
* compatibility in order to load verifier files from other OpenSSL versions.
*/
/*
* Convert a base64 string into raw byte array representation.
* Returns the length of the decoded data, or -1 on error.
*/
static int t_fromb64(unsigned char *a, size_t alen, const char *src)
{
EVP_ENCODE_CTX *ctx;
int outl = 0, outl2 = 0;
size_t size, padsize;
const unsigned char *pad = (const unsigned char *)"00";
while (*src == ' ' || *src == '\t' || *src == '\n')
++src;
size = strlen(src);
padsize = 4 - (size & 3);
padsize &= 3;
/* Four bytes in src become three bytes output. */
if (size > INT_MAX || ((size + padsize) / 4) * 3 > alen)
return -1;
ctx = EVP_ENCODE_CTX_new();
if (ctx == NULL)
return -1;
/*
* This should never occur because 1 byte of data always requires 2 bytes of
* encoding, i.e.
* 0 bytes unencoded = 0 bytes encoded
* 1 byte unencoded = 2 bytes encoded
* 2 bytes unencoded = 3 bytes encoded
* 3 bytes unencoded = 4 bytes encoded
* 4 bytes unencoded = 6 bytes encoded
* etc
*/
if (padsize == 3) {
outl = -1;
goto err;
}
/* Valid padsize values are now 0, 1 or 2 */
EVP_DecodeInit(ctx);
evp_encode_ctx_set_flags(ctx, EVP_ENCODE_CTX_USE_SRP_ALPHABET);
/* Add any encoded padding that is required */
if (padsize != 0
&& EVP_DecodeUpdate(ctx, a, &outl, pad, padsize) < 0) {
outl = -1;
goto err;
}
if (EVP_DecodeUpdate(ctx, a, &outl2, (const unsigned char *)src, size) < 0) {
outl = -1;
goto err;
}
outl += outl2;
EVP_DecodeFinal(ctx, a + outl, &outl2);
outl += outl2;
/* Strip off the leading padding */
if (padsize != 0) {
if ((int)padsize >= outl) {
outl = -1;
goto err;
}
/*
* If we added 1 byte of padding prior to encoding then we have 2 bytes
* of "real" data which gets spread across 4 encoded bytes like this:
* (6 bits pad)(2 bits pad | 4 bits data)(6 bits data)(6 bits data)
* So 1 byte of pre-encoding padding results in 1 full byte of encoded
* padding.
* If we added 2 bytes of padding prior to encoding this gets encoded
* as:
* (6 bits pad)(6 bits pad)(4 bits pad | 2 bits data)(6 bits data)
* So 2 bytes of pre-encoding padding results in 2 full bytes of encoded
* padding, i.e. we have to strip the same number of bytes of padding
* from the encoded data as we added to the pre-encoded data.
*/
memmove(a, a + padsize, outl - padsize);
outl -= padsize;
}
err:
EVP_ENCODE_CTX_free(ctx);
return outl;
}
/*
* Convert a raw byte string into a null-terminated base64 ASCII string.
* Returns 1 on success or 0 on error.
*/
static int t_tob64(char *dst, const unsigned char *src, int size)
{
EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
int outl = 0, outl2 = 0;
unsigned char pad[2] = {0, 0};
size_t leadz = 0;
if (ctx == NULL)
return 0;
EVP_EncodeInit(ctx);
evp_encode_ctx_set_flags(ctx, EVP_ENCODE_CTX_NO_NEWLINES
| EVP_ENCODE_CTX_USE_SRP_ALPHABET);
/*
* We pad at the front with zero bytes until the length is a multiple of 3
* so that EVP_EncodeUpdate/EVP_EncodeFinal does not add any of its own "="
* padding
*/
leadz = 3 - (size % 3);
if (leadz != 3
&& !EVP_EncodeUpdate(ctx, (unsigned char *)dst, &outl, pad,
leadz)) {
EVP_ENCODE_CTX_free(ctx);
return 0;
}
if (!EVP_EncodeUpdate(ctx, (unsigned char *)dst + outl, &outl2, src,
size)) {
EVP_ENCODE_CTX_free(ctx);
return 0;
}
outl += outl2;
EVP_EncodeFinal(ctx, (unsigned char *)dst + outl, &outl2);
outl += outl2;
/* Strip the encoded padding at the front */
if (leadz != 3) {
memmove(dst, dst + leadz, outl - leadz);
dst[outl - leadz] = '\0';
}
EVP_ENCODE_CTX_free(ctx);
return 1;
}
void SRP_user_pwd_free(SRP_user_pwd *user_pwd)
{
if (user_pwd == NULL)
return;
BN_free(user_pwd->s);
BN_clear_free(user_pwd->v);
OPENSSL_free(user_pwd->id);
OPENSSL_free(user_pwd->info);
OPENSSL_free(user_pwd);
}
SRP_user_pwd *SRP_user_pwd_new(void)
{
SRP_user_pwd *ret;
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
/* ERR_raise(ERR_LIB_SRP, ERR_R_MALLOC_FAILURE); */ /*ckerr_ignore*/
return NULL;
}
ret->N = NULL;
ret->g = NULL;
ret->s = NULL;
ret->v = NULL;
ret->id = NULL;
ret->info = NULL;
return ret;
}
void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g,
const BIGNUM *N)
{
vinfo->N = N;
vinfo->g = g;
}
int SRP_user_pwd_set1_ids(SRP_user_pwd *vinfo, const char *id,
const char *info)
{
OPENSSL_free(vinfo->id);
OPENSSL_free(vinfo->info);
+ vinfo->id = NULL;
+ vinfo->info = NULL;
if (id != NULL && NULL == (vinfo->id = OPENSSL_strdup(id)))
return 0;
return (info == NULL || NULL != (vinfo->info = OPENSSL_strdup(info)));
}
static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s,
const char *v)
{
unsigned char tmp[MAX_LEN];
int len;
vinfo->v = NULL;
vinfo->s = NULL;
len = t_fromb64(tmp, sizeof(tmp), v);
if (len < 0)
return 0;
if (NULL == (vinfo->v = BN_bin2bn(tmp, len, NULL)))
return 0;
len = t_fromb64(tmp, sizeof(tmp), s);
if (len < 0)
goto err;
vinfo->s = BN_bin2bn(tmp, len, NULL);
if (vinfo->s == NULL)
goto err;
return 1;
err:
BN_free(vinfo->v);
vinfo->v = NULL;
return 0;
}
int SRP_user_pwd_set0_sv(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v)
{
BN_free(vinfo->s);
BN_clear_free(vinfo->v);
vinfo->v = v;
vinfo->s = s;
return (vinfo->s != NULL && vinfo->v != NULL);
}
static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src)
{
SRP_user_pwd *ret;
if (src == NULL)
return NULL;
if ((ret = SRP_user_pwd_new()) == NULL)
return NULL;
SRP_user_pwd_set_gN(ret, src->g, src->N);
if (!SRP_user_pwd_set1_ids(ret, src->id, src->info)
|| !SRP_user_pwd_set0_sv(ret, BN_dup(src->s), BN_dup(src->v))) {
SRP_user_pwd_free(ret);
return NULL;
}
return ret;
}
SRP_VBASE *SRP_VBASE_new(char *seed_key)
{
SRP_VBASE *vb = OPENSSL_malloc(sizeof(*vb));
if (vb == NULL)
return NULL;
if ((vb->users_pwd = sk_SRP_user_pwd_new_null()) == NULL
|| (vb->gN_cache = sk_SRP_gN_cache_new_null()) == NULL) {
sk_SRP_user_pwd_free(vb->users_pwd);
OPENSSL_free(vb);
return NULL;
}
vb->default_g = NULL;
vb->default_N = NULL;
vb->seed_key = NULL;
if ((seed_key != NULL) && (vb->seed_key = OPENSSL_strdup(seed_key)) == NULL) {
sk_SRP_user_pwd_free(vb->users_pwd);
sk_SRP_gN_cache_free(vb->gN_cache);
OPENSSL_free(vb);
return NULL;
}
return vb;
}
void SRP_VBASE_free(SRP_VBASE *vb)
{
if (!vb)
return;
sk_SRP_user_pwd_pop_free(vb->users_pwd, SRP_user_pwd_free);
sk_SRP_gN_cache_free(vb->gN_cache);
OPENSSL_free(vb->seed_key);
OPENSSL_free(vb);
}
static SRP_gN_cache *SRP_gN_new_init(const char *ch)
{
unsigned char tmp[MAX_LEN];
int len;
SRP_gN_cache *newgN = OPENSSL_malloc(sizeof(*newgN));
if (newgN == NULL)
return NULL;
len = t_fromb64(tmp, sizeof(tmp), ch);
if (len < 0)
goto err;
if ((newgN->b64_bn = OPENSSL_strdup(ch)) == NULL)
goto err;
if ((newgN->bn = BN_bin2bn(tmp, len, NULL)))
return newgN;
OPENSSL_free(newgN->b64_bn);
err:
OPENSSL_free(newgN);
return NULL;
}
static void SRP_gN_free(SRP_gN_cache *gN_cache)
{
if (gN_cache == NULL)
return;
OPENSSL_free(gN_cache->b64_bn);
BN_free(gN_cache->bn);
OPENSSL_free(gN_cache);
}
static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab)
{
int i;
SRP_gN *gN;
if (gN_tab != NULL) {
for (i = 0; i < sk_SRP_gN_num(gN_tab); i++) {
gN = sk_SRP_gN_value(gN_tab, i);
if (gN && (id == NULL || strcmp(gN->id, id) == 0))
return gN;
}
}
return SRP_get_default_gN(id);
}
static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch)
{
int i;
if (gN_cache == NULL)
return NULL;
/* search if we have already one... */
for (i = 0; i < sk_SRP_gN_cache_num(gN_cache); i++) {
SRP_gN_cache *cache = sk_SRP_gN_cache_value(gN_cache, i);
if (strcmp(cache->b64_bn, ch) == 0)
return cache->bn;
}
{ /* it is the first time that we find it */
SRP_gN_cache *newgN = SRP_gN_new_init(ch);
if (newgN) {
if (sk_SRP_gN_cache_insert(gN_cache, newgN, 0) > 0)
return newgN->bn;
SRP_gN_free(newgN);
}
}
return NULL;
}
/*
* This function parses the verifier file generated by the srp app.
* The format for each entry is:
* V base64(verifier) base64(salt) username gNid userinfo(optional)
* or
* I base64(N) base64(g)
* Note that base64 is the SRP variant of base64 encoding described
* in t_fromb64().
*/
int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file)
{
int error_code;
STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null();
char *last_index = NULL;
int i;
char **pp;
SRP_gN *gN = NULL;
SRP_user_pwd *user_pwd = NULL;
TXT_DB *tmpdb = NULL;
BIO *in = BIO_new(BIO_s_file());
error_code = SRP_ERR_OPEN_FILE;
if (in == NULL || BIO_read_filename(in, verifier_file) <= 0)
goto err;
error_code = SRP_ERR_VBASE_INCOMPLETE_FILE;
if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
goto err;
error_code = SRP_ERR_MEMORY;
if (vb->seed_key) {
last_index = SRP_get_default_gN(NULL)->id;
}
for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++) {
pp = sk_OPENSSL_PSTRING_value(tmpdb->data, i);
if (pp[DB_srptype][0] == DB_SRP_INDEX) {
/*
* we add this couple in the internal Stack
*/
if ((gN = OPENSSL_malloc(sizeof(*gN))) == NULL)
goto err;
if ((gN->id = OPENSSL_strdup(pp[DB_srpid])) == NULL
|| (gN->N = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpverifier]))
== NULL
|| (gN->g = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpsalt]))
== NULL
|| sk_SRP_gN_insert(SRP_gN_tab, gN, 0) == 0)
goto err;
gN = NULL;
if (vb->seed_key != NULL) {
last_index = pp[DB_srpid];
}
} else if (pp[DB_srptype][0] == DB_SRP_VALID) {
/* it is a user .... */
const SRP_gN *lgN;
if ((lgN = SRP_get_gN_by_id(pp[DB_srpgN], SRP_gN_tab)) != NULL) {
error_code = SRP_ERR_MEMORY;
if ((user_pwd = SRP_user_pwd_new()) == NULL)
goto err;
SRP_user_pwd_set_gN(user_pwd, lgN->g, lgN->N);
if (!SRP_user_pwd_set1_ids
(user_pwd, pp[DB_srpid], pp[DB_srpinfo]))
goto err;
error_code = SRP_ERR_VBASE_BN_LIB;
if (!SRP_user_pwd_set_sv
(user_pwd, pp[DB_srpsalt], pp[DB_srpverifier]))
goto err;
if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0)
goto err;
user_pwd = NULL; /* abandon responsibility */
}
}
}
if (last_index != NULL) {
/* this means that we want to simulate a default user */
if (((gN = SRP_get_gN_by_id(last_index, SRP_gN_tab)) == NULL)) {
error_code = SRP_ERR_VBASE_BN_LIB;
goto err;
}
vb->default_g = gN->g;
vb->default_N = gN->N;
gN = NULL;
}
error_code = SRP_NO_ERROR;
err:
/*
* there may be still some leaks to fix, if this fails, the application
* terminates most likely
*/
if (gN != NULL) {
OPENSSL_free(gN->id);
OPENSSL_free(gN);
}
SRP_user_pwd_free(user_pwd);
TXT_DB_free(tmpdb);
BIO_free_all(in);
sk_SRP_gN_free(SRP_gN_tab);
return error_code;
}
static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username)
{
int i;
SRP_user_pwd *user;
if (vb == NULL)
return NULL;
for (i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) {
user = sk_SRP_user_pwd_value(vb->users_pwd, i);
if (strcmp(user->id, username) == 0)
return user;
}
return NULL;
}
int SRP_VBASE_add0_user(SRP_VBASE *vb, SRP_user_pwd *user_pwd)
{
if (sk_SRP_user_pwd_push(vb->users_pwd, user_pwd) <= 0)
return 0;
return 1;
}
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
/*
* DEPRECATED: use SRP_VBASE_get1_by_user instead.
* This method ignores the configured seed and fails for an unknown user.
* Ownership of the returned pointer is not released to the caller.
* In other words, caller must not free the result.
*/
SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)
{
return find_user(vb, username);
}
# endif
/*
* Ownership of the returned pointer is released to the caller.
* In other words, caller must free the result once done.
*/
SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username)
{
SRP_user_pwd *user;
unsigned char digv[SHA_DIGEST_LENGTH];
unsigned char digs[SHA_DIGEST_LENGTH];
EVP_MD_CTX *ctxt = NULL;
EVP_MD *md = NULL;
if (vb == NULL)
return NULL;
if ((user = find_user(vb, username)) != NULL)
return srp_user_pwd_dup(user);
if ((vb->seed_key == NULL) ||
(vb->default_g == NULL) || (vb->default_N == NULL))
return NULL;
/* if the user is unknown we set parameters as well if we have a seed_key */
if ((user = SRP_user_pwd_new()) == NULL)
return NULL;
SRP_user_pwd_set_gN(user, vb->default_g, vb->default_N);
if (!SRP_user_pwd_set1_ids(user, username, NULL))
goto err;
if (RAND_priv_bytes(digv, SHA_DIGEST_LENGTH) <= 0)
goto err;
md = EVP_MD_fetch(NULL, SN_sha1, NULL);
if (md == NULL)
goto err;
ctxt = EVP_MD_CTX_new();
if (ctxt == NULL
|| !EVP_DigestInit_ex(ctxt, md, NULL)
|| !EVP_DigestUpdate(ctxt, vb->seed_key, strlen(vb->seed_key))
|| !EVP_DigestUpdate(ctxt, username, strlen(username))
|| !EVP_DigestFinal_ex(ctxt, digs, NULL))
goto err;
EVP_MD_CTX_free(ctxt);
ctxt = NULL;
EVP_MD_free(md);
md = NULL;
if (SRP_user_pwd_set0_sv(user,
BN_bin2bn(digs, SHA_DIGEST_LENGTH, NULL),
BN_bin2bn(digv, SHA_DIGEST_LENGTH, NULL)))
return user;
err:
EVP_MD_free(md);
EVP_MD_CTX_free(ctxt);
SRP_user_pwd_free(user);
return NULL;
}
/*
* create a verifier (*salt,*verifier,g and N are in base64)
*/
char *SRP_create_verifier_ex(const char *user, const char *pass, char **salt,
char **verifier, const char *N, const char *g,
OSSL_LIB_CTX *libctx, const char *propq)
{
int len;
char *result = NULL, *vf = NULL;
const BIGNUM *N_bn = NULL, *g_bn = NULL;
BIGNUM *N_bn_alloc = NULL, *g_bn_alloc = NULL, *s = NULL, *v = NULL;
unsigned char tmp[MAX_LEN];
unsigned char tmp2[MAX_LEN];
char *defgNid = NULL;
int vfsize = 0;
if ((user == NULL) ||
(pass == NULL) || (salt == NULL) || (verifier == NULL))
goto err;
if (N) {
if ((len = t_fromb64(tmp, sizeof(tmp), N)) <= 0)
goto err;
N_bn_alloc = BN_bin2bn(tmp, len, NULL);
if (N_bn_alloc == NULL)
goto err;
N_bn = N_bn_alloc;
if ((len = t_fromb64(tmp, sizeof(tmp) ,g)) <= 0)
goto err;
g_bn_alloc = BN_bin2bn(tmp, len, NULL);
if (g_bn_alloc == NULL)
goto err;
g_bn = g_bn_alloc;
defgNid = "*";
} else {
SRP_gN *gN = SRP_get_default_gN(g);
if (gN == NULL)
goto err;
N_bn = gN->N;
g_bn = gN->g;
defgNid = gN->id;
}
if (*salt == NULL) {
if (RAND_bytes_ex(libctx, tmp2, SRP_RANDOM_SALT_LEN, 0) <= 0)
goto err;
s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
} else {
if ((len = t_fromb64(tmp2, sizeof(tmp2), *salt)) <= 0)
goto err;
s = BN_bin2bn(tmp2, len, NULL);
}
if (s == NULL)
goto err;
if (!SRP_create_verifier_BN_ex(user, pass, &s, &v, N_bn, g_bn, libctx,
propq))
goto err;
if (BN_bn2bin(v, tmp) < 0)
goto err;
vfsize = BN_num_bytes(v) * 2;
if (((vf = OPENSSL_malloc(vfsize)) == NULL))
goto err;
if (!t_tob64(vf, tmp, BN_num_bytes(v)))
goto err;
if (*salt == NULL) {
char *tmp_salt;
if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) {
goto err;
}
if (!t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN)) {
OPENSSL_free(tmp_salt);
goto err;
}
*salt = tmp_salt;
}
*verifier = vf;
vf = NULL;
result = defgNid;
err:
BN_free(N_bn_alloc);
BN_free(g_bn_alloc);
OPENSSL_clear_free(vf, vfsize);
BN_clear_free(s);
BN_clear_free(v);
return result;
}
char *SRP_create_verifier(const char *user, const char *pass, char **salt,
char **verifier, const char *N, const char *g)
{
return SRP_create_verifier_ex(user, pass, salt, verifier, N, g, NULL, NULL);
}
/*
* create a verifier (*salt,*verifier,g and N are BIGNUMs). If *salt != NULL
* then the provided salt will be used. On successful exit *verifier will point
* to a newly allocated BIGNUM containing the verifier and (if a salt was not
* provided) *salt will be populated with a newly allocated BIGNUM containing a
* random salt.
* The caller is responsible for freeing the allocated *salt and *verifier
* BIGNUMS.
*/
int SRP_create_verifier_BN_ex(const char *user, const char *pass, BIGNUM **salt,
BIGNUM **verifier, const BIGNUM *N,
const BIGNUM *g, OSSL_LIB_CTX *libctx,
const char *propq)
{
int result = 0;
BIGNUM *x = NULL;
BN_CTX *bn_ctx = BN_CTX_new_ex(libctx);
unsigned char tmp2[MAX_LEN];
BIGNUM *salttmp = NULL, *verif;
if ((user == NULL) ||
(pass == NULL) ||
(salt == NULL) ||
(verifier == NULL) || (N == NULL) || (g == NULL) || (bn_ctx == NULL))
goto err;
if (*salt == NULL) {
if (RAND_bytes_ex(libctx, tmp2, SRP_RANDOM_SALT_LEN, 0) <= 0)
goto err;
salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
if (salttmp == NULL)
goto err;
} else {
salttmp = *salt;
}
x = SRP_Calc_x_ex(salttmp, user, pass, libctx, propq);
if (x == NULL)
goto err;
verif = BN_new();
if (verif == NULL)
goto err;
if (!BN_mod_exp(verif, g, x, N, bn_ctx)) {
BN_clear_free(verif);
goto err;
}
result = 1;
*salt = salttmp;
*verifier = verif;
err:
if (salt != NULL && *salt != salttmp)
BN_clear_free(salttmp);
BN_clear_free(x);
BN_CTX_free(bn_ctx);
return result;
}
int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
BIGNUM **verifier, const BIGNUM *N,
const BIGNUM *g)
{
return SRP_create_verifier_BN_ex(user, pass, salt, verifier, N, g, NULL,
NULL);
}
#endif
diff --git a/crypto/openssl/crypto/threads_win.c b/crypto/openssl/crypto/threads_win.c
index dbeda74d73a7..43f36ee6a333 100644
--- a/crypto/openssl/crypto/threads_win.c
+++ b/crypto/openssl/crypto/threads_win.c
@@ -1,263 +1,264 @@
/*
* Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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(_WIN32)
# include <windows.h>
# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
# define USE_RWLOCK
# endif
#endif
/*
* VC++ 2008 or earlier x86 compilers do not have an inline implementation
* of InterlockedOr64 for 32bit and will fail to run on Windows XP 32bit.
* https://docs.microsoft.com/en-us/cpp/intrinsics/interlockedor-intrinsic-functions#requirements
* To work around this problem, we implement a manual locking mechanism for
* only VC++ 2008 or earlier x86 compilers.
*/
#if (defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER <= 1600)
# define NO_INTERLOCKEDOR64
#endif
#include <openssl/crypto.h>
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS)
# ifdef USE_RWLOCK
typedef struct {
SRWLOCK lock;
int exclusive;
} CRYPTO_win_rwlock;
# endif
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
{
CRYPTO_RWLOCK *lock;
# ifdef USE_RWLOCK
CRYPTO_win_rwlock *rwlock;
if ((lock = OPENSSL_zalloc(sizeof(CRYPTO_win_rwlock))) == NULL)
return NULL;
rwlock = lock;
InitializeSRWLock(&rwlock->lock);
# else
if ((lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION))) == NULL) {
/* Don't set error, to avoid recursion blowup. */
return NULL;
}
# if !defined(_WIN32_WCE)
/* 0x400 is the spin count value suggested in the documentation */
if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) {
OPENSSL_free(lock);
return NULL;
}
# else
InitializeCriticalSection(lock);
# endif
# endif
return lock;
}
__owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
{
# ifdef USE_RWLOCK
CRYPTO_win_rwlock *rwlock = lock;
AcquireSRWLockShared(&rwlock->lock);
# else
EnterCriticalSection(lock);
# endif
return 1;
}
__owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
{
# ifdef USE_RWLOCK
CRYPTO_win_rwlock *rwlock = lock;
AcquireSRWLockExclusive(&rwlock->lock);
rwlock->exclusive = 1;
# else
EnterCriticalSection(lock);
# endif
return 1;
}
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
{
# ifdef USE_RWLOCK
CRYPTO_win_rwlock *rwlock = lock;
if (rwlock->exclusive) {
rwlock->exclusive = 0;
ReleaseSRWLockExclusive(&rwlock->lock);
} else {
ReleaseSRWLockShared(&rwlock->lock);
}
# else
LeaveCriticalSection(lock);
# endif
return 1;
}
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
{
if (lock == NULL)
return;
# ifndef USE_RWLOCK
DeleteCriticalSection(lock);
# endif
OPENSSL_free(lock);
return;
}
# define ONCE_UNINITED 0
# define ONCE_ININIT 1
# define ONCE_DONE 2
/*
* We don't use InitOnceExecuteOnce because that isn't available in WinXP which
* we still have to support.
*/
int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
{
LONG volatile *lock = (LONG *)once;
LONG result;
if (*lock == ONCE_DONE)
return 1;
do {
result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED);
if (result == ONCE_UNINITED) {
init();
*lock = ONCE_DONE;
return 1;
}
} while (result == ONCE_ININIT);
return (*lock == ONCE_DONE);
}
int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
{
*key = TlsAlloc();
if (*key == TLS_OUT_OF_INDEXES)
return 0;
return 1;
}
void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
{
DWORD last_error;
void *ret;
/*
* TlsGetValue clears the last error even on success, so that callers may
* distinguish it successfully returning NULL or failing. It is documented
* to never fail if the argument is a valid index from TlsAlloc, so we do
* not need to handle this.
*
* However, this error-mangling behavior interferes with the caller's use of
* GetLastError. In particular SSL_get_error queries the error queue to
* determine whether the caller should look at the OS's errors. To avoid
* destroying state, save and restore the Windows error.
*
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms686812(v=vs.85).aspx
*/
last_error = GetLastError();
ret = TlsGetValue(*key);
SetLastError(last_error);
return ret;
}
int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
{
if (TlsSetValue(*key, val) == 0)
return 0;
return 1;
}
int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
{
if (TlsFree(*key) == 0)
return 0;
return 1;
}
CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
{
return GetCurrentThreadId();
}
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
{
return (a == b);
}
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
{
- *ret = (int)InterlockedExchangeAdd((long volatile *)val, (long)amount) + amount;
+ *ret = (int)InterlockedExchangeAdd((LONG volatile *)val, (LONG)amount)
+ + amount;
return 1;
}
int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
CRYPTO_RWLOCK *lock)
{
#if (defined(NO_INTERLOCKEDOR64))
if (lock == NULL || !CRYPTO_THREAD_write_lock(lock))
return 0;
*val |= op;
*ret = *val;
if (!CRYPTO_THREAD_unlock(lock))
return 0;
return 1;
#else
*ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, (LONG64)op) | op;
return 1;
#endif
}
int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
{
#if (defined(NO_INTERLOCKEDOR64))
if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
return 0;
*ret = *val;
if (!CRYPTO_THREAD_unlock(lock))
return 0;
return 1;
#else
*ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, 0);
return 1;
#endif
}
int openssl_init_fork_handlers(void)
{
return 0;
}
int openssl_get_fork_id(void)
{
return 0;
}
#endif
diff --git a/crypto/openssl/crypto/trace.c b/crypto/openssl/crypto/trace.c
index 3df9b5a51e99..90a6350bebae 100644
--- a/crypto/openssl/crypto/trace.c
+++ b/crypto/openssl/crypto/trace.c
@@ -1,531 +1,531 @@
/*
* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <string.h>
#include "internal/thread_once.h"
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/trace.h>
#include "internal/bio.h"
#include "internal/nelem.h"
#include "internal/refcount.h"
#include "crypto/cryptlib.h"
#ifndef OPENSSL_NO_TRACE
static CRYPTO_RWLOCK *trace_lock = NULL;
static const BIO *current_channel = NULL;
/*-
* INTERNAL TRACE CHANNEL IMPLEMENTATION
*
* For our own flexibility, all trace categories are associated with a
* BIO sink object, also called the trace channel. Instead of a BIO object,
* the application can also provide a callback function, in which case an
* internal trace channel is attached, which simply calls the registered
* callback function.
*/
static int trace_write(BIO *b, const char *buf,
size_t num, size_t *written);
static int trace_puts(BIO *b, const char *str);
static long trace_ctrl(BIO *channel, int cmd, long argl, void *argp);
static int trace_free(BIO *b);
static const BIO_METHOD trace_method = {
BIO_TYPE_SOURCE_SINK,
"trace",
trace_write,
NULL, /* old write */
NULL, /* read_ex */
NULL, /* read */
trace_puts,
NULL, /* gets */
trace_ctrl, /* ctrl */
NULL, /* create */
trace_free, /* free */
NULL, /* callback_ctrl */
};
struct trace_data_st {
OSSL_trace_cb callback;
int category;
void *data;
};
static int trace_write(BIO *channel,
const char *buf, size_t num, size_t *written)
{
struct trace_data_st *ctx = BIO_get_data(channel);
size_t cnt = ctx->callback(buf, num, ctx->category, OSSL_TRACE_CTRL_WRITE,
ctx->data);
*written = cnt;
return cnt != 0;
}
static int trace_puts(BIO *channel, const char *str)
{
size_t written;
if (trace_write(channel, str, strlen(str), &written))
return (int)written;
return EOF;
}
static long trace_ctrl(BIO *channel, int cmd, long argl, void *argp)
{
struct trace_data_st *ctx = BIO_get_data(channel);
switch (cmd) {
case OSSL_TRACE_CTRL_BEGIN:
case OSSL_TRACE_CTRL_END:
/* We know that the callback is likely to return 0 here */
ctx->callback("", 0, ctx->category, cmd, ctx->data);
return 1;
default:
break;
}
return -2; /* Unsupported */
}
static int trace_free(BIO *channel)
{
if (channel == NULL)
return 0;
OPENSSL_free(BIO_get_data(channel));
return 1;
}
#endif
/*-
* TRACE
*/
/* Helper struct and macro to get name string to number mapping */
struct trace_category_st {
const char * const name;
const int num;
};
#define TRACE_CATEGORY_(name) { #name, OSSL_TRACE_CATEGORY_##name }
static const struct trace_category_st
trace_categories[OSSL_TRACE_CATEGORY_NUM] = {
TRACE_CATEGORY_(ALL),
TRACE_CATEGORY_(TRACE),
TRACE_CATEGORY_(INIT),
TRACE_CATEGORY_(TLS),
TRACE_CATEGORY_(TLS_CIPHER),
TRACE_CATEGORY_(CONF),
TRACE_CATEGORY_(ENGINE_TABLE),
TRACE_CATEGORY_(ENGINE_REF_COUNT),
TRACE_CATEGORY_(PKCS5V2),
TRACE_CATEGORY_(PKCS12_KEYGEN),
TRACE_CATEGORY_(PKCS12_DECRYPT),
TRACE_CATEGORY_(X509V3_POLICY),
TRACE_CATEGORY_(BN_CTX),
TRACE_CATEGORY_(CMP),
TRACE_CATEGORY_(STORE),
TRACE_CATEGORY_(DECODER),
TRACE_CATEGORY_(ENCODER),
TRACE_CATEGORY_(REF_COUNT)
};
const char *OSSL_trace_get_category_name(int num)
{
if (num < 0 || (size_t)num >= OSSL_NELEM(trace_categories))
return NULL;
/*
* Partial check that OSSL_TRACE_CATEGORY_... macros
* are synced with trace_categories array
*/
if (!ossl_assert(trace_categories[num].name != NULL)
|| !ossl_assert(trace_categories[num].num == num))
return NULL;
return trace_categories[num].name;
}
int OSSL_trace_get_category_num(const char *name)
{
size_t i;
if (name == NULL)
return -1;
for (i = 0; i < OSSL_NELEM(trace_categories); i++)
if (OPENSSL_strcasecmp(name, trace_categories[i].name) == 0)
return trace_categories[i].num;
return -1; /* not found */
}
#ifndef OPENSSL_NO_TRACE
/* We use one trace channel for each trace category */
static struct {
enum { SIMPLE_CHANNEL, CALLBACK_CHANNEL } type;
BIO *bio;
char *prefix;
char *suffix;
} trace_channels[OSSL_TRACE_CATEGORY_NUM] = {
{ 0, NULL, NULL, NULL },
};
#endif
#ifndef OPENSSL_NO_TRACE
enum {
CHANNEL,
PREFIX,
SUFFIX
};
static int trace_attach_cb(int category, int type, const void *data)
{
switch (type) {
case CHANNEL:
OSSL_TRACE2(TRACE, "Attach channel %p to category '%s'\n",
data, trace_categories[category].name);
break;
case PREFIX:
OSSL_TRACE2(TRACE, "Attach prefix \"%s\" to category '%s'\n",
(const char *)data, trace_categories[category].name);
break;
case SUFFIX:
OSSL_TRACE2(TRACE, "Attach suffix \"%s\" to category '%s'\n",
(const char *)data, trace_categories[category].name);
break;
default: /* No clue */
break;
}
return 1;
}
static int trace_detach_cb(int category, int type, const void *data)
{
switch (type) {
case CHANNEL:
OSSL_TRACE2(TRACE, "Detach channel %p from category '%s'\n",
data, trace_categories[category].name);
break;
case PREFIX:
OSSL_TRACE2(TRACE, "Detach prefix \"%s\" from category '%s'\n",
(const char *)data, trace_categories[category].name);
break;
case SUFFIX:
OSSL_TRACE2(TRACE, "Detach suffix \"%s\" from category '%s'\n",
(const char *)data, trace_categories[category].name);
break;
default: /* No clue */
break;
}
return 1;
}
static int do_ossl_trace_init(void);
static CRYPTO_ONCE trace_inited = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_trace_init)
{
return do_ossl_trace_init();
}
static int set_trace_data(int category, int type, BIO **channel,
const char **prefix, const char **suffix,
int (*attach_cb)(int, int, const void *),
int (*detach_cb)(int, int, const void *))
{
BIO *curr_channel = NULL;
char *curr_prefix = NULL;
char *curr_suffix = NULL;
/* Ensure do_ossl_trace_init() is called once */
if (!RUN_ONCE(&trace_inited, ossl_trace_init))
return 0;
curr_channel = trace_channels[category].bio;
curr_prefix = trace_channels[category].prefix;
curr_suffix = trace_channels[category].suffix;
/* Make sure to run the detach callback first on all data */
if (prefix != NULL && curr_prefix != NULL) {
detach_cb(category, PREFIX, curr_prefix);
}
if (suffix != NULL && curr_suffix != NULL) {
detach_cb(category, SUFFIX, curr_suffix);
}
if (channel != NULL && curr_channel != NULL) {
detach_cb(category, CHANNEL, curr_channel);
}
/* After detach callbacks are done, clear data where appropriate */
if (prefix != NULL && curr_prefix != NULL) {
OPENSSL_free(curr_prefix);
trace_channels[category].prefix = NULL;
}
if (suffix != NULL && curr_suffix != NULL) {
OPENSSL_free(curr_suffix);
trace_channels[category].suffix = NULL;
}
if (channel != NULL && curr_channel != NULL) {
BIO_free(curr_channel);
trace_channels[category].type = 0;
trace_channels[category].bio = NULL;
}
/* Before running callbacks are done, set new data where appropriate */
if (prefix != NULL && *prefix != NULL) {
if ((curr_prefix = OPENSSL_strdup(*prefix)) == NULL)
return 0;
trace_channels[category].prefix = curr_prefix;
}
if (suffix != NULL && *suffix != NULL) {
if ((curr_suffix = OPENSSL_strdup(*suffix)) == NULL)
return 0;
trace_channels[category].suffix = curr_suffix;
}
if (channel != NULL && *channel != NULL) {
trace_channels[category].type = type;
trace_channels[category].bio = *channel;
/*
* This must not be done before setting prefix/suffix,
* as those may fail, and then the caller is mislead to free *channel.
*/
}
/* Finally, run the attach callback on the new data */
if (channel != NULL && *channel != NULL) {
attach_cb(category, CHANNEL, *channel);
}
if (prefix != NULL && *prefix != NULL) {
attach_cb(category, PREFIX, *prefix);
}
if (suffix != NULL && *suffix != NULL) {
attach_cb(category, SUFFIX, *suffix);
}
return 1;
}
static int do_ossl_trace_init(void)
{
trace_lock = CRYPTO_THREAD_lock_new();
return trace_lock != NULL;
}
#endif
void ossl_trace_cleanup(void)
{
#ifndef OPENSSL_NO_TRACE
int category;
BIO *channel = NULL;
const char *prefix = NULL;
const char *suffix = NULL;
for (category = 0; category < OSSL_TRACE_CATEGORY_NUM; category++) {
/* We force the TRACE category to be treated last */
if (category == OSSL_TRACE_CATEGORY_TRACE)
continue;
set_trace_data(category, 0, &channel, &prefix, &suffix,
trace_attach_cb, trace_detach_cb);
}
set_trace_data(OSSL_TRACE_CATEGORY_TRACE, 0, &channel,
&prefix, &suffix,
trace_attach_cb, trace_detach_cb);
CRYPTO_THREAD_lock_free(trace_lock);
#endif
}
int OSSL_trace_set_channel(int category, BIO *channel)
{
#ifndef OPENSSL_NO_TRACE
if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
return set_trace_data(category, SIMPLE_CHANNEL, &channel, NULL, NULL,
trace_attach_cb, trace_detach_cb);
#endif
return 0;
}
#ifndef OPENSSL_NO_TRACE
static int trace_attach_w_callback_cb(int category, int type, const void *data)
{
switch (type) {
case CHANNEL:
OSSL_TRACE2(TRACE,
"Attach channel %p to category '%s' (with callback)\n",
data, trace_categories[category].name);
break;
case PREFIX:
OSSL_TRACE2(TRACE, "Attach prefix \"%s\" to category '%s'\n",
(const char *)data, trace_categories[category].name);
break;
case SUFFIX:
OSSL_TRACE2(TRACE, "Attach suffix \"%s\" to category '%s'\n",
(const char *)data, trace_categories[category].name);
break;
default: /* No clue */
break;
}
return 1;
}
#endif
int OSSL_trace_set_callback(int category, OSSL_trace_cb callback, void *data)
{
#ifndef OPENSSL_NO_TRACE
BIO *channel = NULL;
struct trace_data_st *trace_data = NULL;
if (category < 0 || category >= OSSL_TRACE_CATEGORY_NUM)
return 0;
if (callback != NULL) {
if ((channel = BIO_new(&trace_method)) == NULL
|| (trace_data =
OPENSSL_zalloc(sizeof(struct trace_data_st))) == NULL)
goto err;
trace_data->callback = callback;
trace_data->category = category;
trace_data->data = data;
BIO_set_data(channel, trace_data);
}
if (!set_trace_data(category, CALLBACK_CHANNEL, &channel, NULL, NULL,
trace_attach_w_callback_cb, trace_detach_cb))
goto err;
return 1;
err:
BIO_free(channel);
OPENSSL_free(trace_data);
#endif
return 0;
}
int OSSL_trace_set_prefix(int category, const char *prefix)
{
#ifndef OPENSSL_NO_TRACE
if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
return set_trace_data(category, 0, NULL, &prefix, NULL,
trace_attach_cb, trace_detach_cb);
#endif
return 0;
}
int OSSL_trace_set_suffix(int category, const char *suffix)
{
#ifndef OPENSSL_NO_TRACE
if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
return set_trace_data(category, 0, NULL, NULL, &suffix,
trace_attach_cb, trace_detach_cb);
#endif
return 0;
}
#ifndef OPENSSL_NO_TRACE
static int ossl_trace_get_category(int category)
{
if (category < 0 || category >= OSSL_TRACE_CATEGORY_NUM)
return -1;
if (trace_channels[category].bio != NULL)
return category;
return OSSL_TRACE_CATEGORY_ALL;
}
#endif
int OSSL_trace_enabled(int category)
{
int ret = 0;
#ifndef OPENSSL_NO_TRACE
category = ossl_trace_get_category(category);
if (category >= 0)
ret = trace_channels[category].bio != NULL;
#endif
return ret;
}
BIO *OSSL_trace_begin(int category)
{
BIO *channel = NULL;
#ifndef OPENSSL_NO_TRACE
char *prefix = NULL;
category = ossl_trace_get_category(category);
- if (category < 0)
+ if (category < 0 || !OSSL_trace_enabled(category))
return NULL;
channel = trace_channels[category].bio;
prefix = trace_channels[category].prefix;
if (channel != NULL) {
if (!CRYPTO_THREAD_write_lock(trace_lock))
return NULL;
current_channel = channel;
switch (trace_channels[category].type) {
case SIMPLE_CHANNEL:
if (prefix != NULL) {
(void)BIO_puts(channel, prefix);
(void)BIO_puts(channel, "\n");
}
break;
case CALLBACK_CHANNEL:
(void)BIO_ctrl(channel, OSSL_TRACE_CTRL_BEGIN,
prefix == NULL ? 0 : strlen(prefix), prefix);
break;
}
}
#endif
return channel;
}
void OSSL_trace_end(int category, BIO * channel)
{
#ifndef OPENSSL_NO_TRACE
char *suffix = NULL;
category = ossl_trace_get_category(category);
if (category < 0)
return;
suffix = trace_channels[category].suffix;
if (channel != NULL
&& ossl_assert(channel == current_channel)) {
(void)BIO_flush(channel);
switch (trace_channels[category].type) {
case SIMPLE_CHANNEL:
if (suffix != NULL) {
(void)BIO_puts(channel, suffix);
(void)BIO_puts(channel, "\n");
}
break;
case CALLBACK_CHANNEL:
(void)BIO_ctrl(channel, OSSL_TRACE_CTRL_END,
suffix == NULL ? 0 : strlen(suffix), suffix);
break;
}
current_channel = NULL;
CRYPTO_THREAD_unlock(trace_lock);
}
#endif
}
diff --git a/crypto/openssl/crypto/ui/ui_util.c b/crypto/openssl/crypto/ui/ui_util.c
index 59b00b225adf..554bf7985659 100644
--- a/crypto/openssl/crypto/ui/ui_util.c
+++ b/crypto/openssl/crypto/ui/ui_util.c
@@ -1,163 +1,167 @@
/*
* Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/pem.h> /* PEM_def_callback() */
#include "internal/thread_once.h"
#include "ui_local.h"
#ifndef BUFSIZ
#define BUFSIZ 256
#endif
int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt,
int verify)
{
char buff[BUFSIZ];
int ret;
ret =
UI_UTIL_read_pw(buf, buff, (length > BUFSIZ) ? BUFSIZ : length,
prompt, verify);
OPENSSL_cleanse(buff, BUFSIZ);
return ret;
}
int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt,
int verify)
{
int ok = -2;
UI *ui;
if (size < 1)
return -1;
ui = UI_new();
if (ui != NULL) {
ok = UI_add_input_string(ui, prompt, 0, buf, 0, size - 1);
if (ok >= 0 && verify)
ok = UI_add_verify_string(ui, prompt, 0, buff, 0, size - 1, buf);
if (ok >= 0)
ok = UI_process(ui);
UI_free(ui);
}
return ok;
}
/*
* Wrapper around pem_password_cb, a method to help older APIs use newer
* ones.
*/
struct pem_password_cb_data {
pem_password_cb *cb;
int rwflag;
};
static void ui_new_method_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
int idx, long argl, void *argp)
{
/*
* Do nothing, the data is allocated externally and assigned later with
* CRYPTO_set_ex_data()
*/
}
static int ui_dup_method_data(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
void **pptr, int idx, long argl, void *argp)
{
if (*pptr != NULL) {
*pptr = OPENSSL_memdup(*pptr, sizeof(struct pem_password_cb_data));
if (*pptr != NULL)
return 1;
}
return 0;
}
static void ui_free_method_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
int idx, long argl, void *argp)
{
OPENSSL_free(ptr);
}
static CRYPTO_ONCE get_index_once = CRYPTO_ONCE_STATIC_INIT;
static int ui_method_data_index = -1;
DEFINE_RUN_ONCE_STATIC(ui_method_data_index_init)
{
ui_method_data_index = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI_METHOD,
0, NULL, ui_new_method_data,
ui_dup_method_data,
ui_free_method_data);
return 1;
}
static int ui_open(UI *ui)
{
return 1;
}
static int ui_read(UI *ui, UI_STRING *uis)
{
switch (UI_get_string_type(uis)) {
case UIT_PROMPT:
{
- char result[PEM_BUFSIZE + 1];
+ int len;
+ char result[PEM_BUFSIZE + 1]; /* reserve one byte at the end */
const struct pem_password_cb_data *data =
UI_method_get_ex_data(UI_get_method(ui), ui_method_data_index);
int maxsize = UI_get_result_maxsize(uis);
- int len = data->cb(result,
- maxsize > PEM_BUFSIZE ? PEM_BUFSIZE : maxsize,
- data->rwflag, UI_get0_user_data(ui));
+ if (maxsize > PEM_BUFSIZE)
+ maxsize = PEM_BUFSIZE;
+ len = data->cb(result, maxsize, data->rwflag,
+ UI_get0_user_data(ui));
+ if (len > maxsize)
+ return -1;
if (len >= 0)
result[len] = '\0';
if (len < 0)
return len;
if (UI_set_result_ex(ui, uis, result, len) >= 0)
return 1;
return 0;
}
case UIT_VERIFY:
case UIT_NONE:
case UIT_BOOLEAN:
case UIT_INFO:
case UIT_ERROR:
break;
}
return 1;
}
static int ui_write(UI *ui, UI_STRING *uis)
{
return 1;
}
static int ui_close(UI *ui)
{
return 1;
}
UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag)
{
struct pem_password_cb_data *data = NULL;
UI_METHOD *ui_method = NULL;
if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL
|| (ui_method = UI_create_method("PEM password callback wrapper")) == NULL
|| UI_method_set_opener(ui_method, ui_open) < 0
|| UI_method_set_reader(ui_method, ui_read) < 0
|| UI_method_set_writer(ui_method, ui_write) < 0
|| UI_method_set_closer(ui_method, ui_close) < 0
|| !RUN_ONCE(&get_index_once, ui_method_data_index_init)
|| !UI_method_set_ex_data(ui_method, ui_method_data_index, data)) {
UI_destroy_method(ui_method);
OPENSSL_free(data);
return NULL;
}
data->rwflag = rwflag;
data->cb = cb != NULL ? cb : PEM_def_callback;
return ui_method;
}
diff --git a/crypto/openssl/crypto/x509/v3_admis.c b/crypto/openssl/crypto/x509/v3_admis.c
index 3bce232ed2fe..53259c29f569 100644
--- a/crypto/openssl/crypto/x509/v3_admis.c
+++ b/crypto/openssl/crypto/x509/v3_admis.c
@@ -1,355 +1,353 @@
/*
* Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/conf.h>
#include <openssl/types.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/x509v3.h>
#include <openssl/safestack.h>
#include "v3_admis.h"
#include "ext_dat.h"
ASN1_SEQUENCE(NAMING_AUTHORITY) = {
ASN1_OPT(NAMING_AUTHORITY, namingAuthorityId, ASN1_OBJECT),
ASN1_OPT(NAMING_AUTHORITY, namingAuthorityUrl, ASN1_IA5STRING),
ASN1_OPT(NAMING_AUTHORITY, namingAuthorityText, DIRECTORYSTRING),
} ASN1_SEQUENCE_END(NAMING_AUTHORITY)
ASN1_SEQUENCE(PROFESSION_INFO) = {
ASN1_EXP_OPT(PROFESSION_INFO, namingAuthority, NAMING_AUTHORITY, 0),
ASN1_SEQUENCE_OF(PROFESSION_INFO, professionItems, DIRECTORYSTRING),
ASN1_SEQUENCE_OF_OPT(PROFESSION_INFO, professionOIDs, ASN1_OBJECT),
ASN1_OPT(PROFESSION_INFO, registrationNumber, ASN1_PRINTABLESTRING),
ASN1_OPT(PROFESSION_INFO, addProfessionInfo, ASN1_OCTET_STRING),
} ASN1_SEQUENCE_END(PROFESSION_INFO)
ASN1_SEQUENCE(ADMISSIONS) = {
ASN1_EXP_OPT(ADMISSIONS, admissionAuthority, GENERAL_NAME, 0),
ASN1_EXP_OPT(ADMISSIONS, namingAuthority, NAMING_AUTHORITY, 1),
ASN1_SEQUENCE_OF(ADMISSIONS, professionInfos, PROFESSION_INFO),
} ASN1_SEQUENCE_END(ADMISSIONS)
ASN1_SEQUENCE(ADMISSION_SYNTAX) = {
ASN1_OPT(ADMISSION_SYNTAX, admissionAuthority, GENERAL_NAME),
ASN1_SEQUENCE_OF(ADMISSION_SYNTAX, contentsOfAdmissions, ADMISSIONS),
} ASN1_SEQUENCE_END(ADMISSION_SYNTAX)
IMPLEMENT_ASN1_FUNCTIONS(NAMING_AUTHORITY)
IMPLEMENT_ASN1_FUNCTIONS(PROFESSION_INFO)
IMPLEMENT_ASN1_FUNCTIONS(ADMISSIONS)
IMPLEMENT_ASN1_FUNCTIONS(ADMISSION_SYNTAX)
static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
BIO *bp, int ind);
const X509V3_EXT_METHOD ossl_v3_ext_admission = {
NID_x509ExtAdmission, /* .ext_nid = */
0, /* .ext_flags = */
ASN1_ITEM_ref(ADMISSION_SYNTAX), /* .it = */
NULL, NULL, NULL, NULL,
NULL, /* .i2s = */
NULL, /* .s2i = */
NULL, /* .i2v = */
NULL, /* .v2i = */
&i2r_ADMISSION_SYNTAX, /* .i2r = */
NULL, /* .r2i = */
NULL /* extension-specific data */
};
-
static int i2r_NAMING_AUTHORITY(const struct v3_ext_method *method, void *in,
BIO *bp, int ind)
{
- NAMING_AUTHORITY * namingAuthority = (NAMING_AUTHORITY*) in;
+ NAMING_AUTHORITY *namingAuthority = (NAMING_AUTHORITY *) in;
if (namingAuthority == NULL)
return 0;
if (namingAuthority->namingAuthorityId == NULL
&& namingAuthority->namingAuthorityText == NULL
&& namingAuthority->namingAuthorityUrl == NULL)
return 0;
- if (BIO_printf(bp, "%*snamingAuthority: ", ind, "") <= 0)
+ if (BIO_printf(bp, "%*snamingAuthority:\n", ind, "") <= 0)
goto err;
if (namingAuthority->namingAuthorityId != NULL) {
char objbuf[128];
const char *ln = OBJ_nid2ln(OBJ_obj2nid(namingAuthority->namingAuthorityId));
- if (BIO_printf(bp, "%*s admissionAuthorityId: ", ind, "") <= 0)
+ if (BIO_printf(bp, "%*s namingAuthorityId: ", ind, "") <= 0)
goto err;
OBJ_obj2txt(objbuf, sizeof(objbuf), namingAuthority->namingAuthorityId, 1);
if (BIO_printf(bp, "%s%s%s%s\n", ln ? ln : "",
ln ? " (" : "", objbuf, ln ? ")" : "") <= 0)
goto err;
}
if (namingAuthority->namingAuthorityText != NULL) {
if (BIO_printf(bp, "%*s namingAuthorityText: ", ind, "") <= 0
|| ASN1_STRING_print(bp, namingAuthority->namingAuthorityText) <= 0
|| BIO_printf(bp, "\n") <= 0)
goto err;
}
if (namingAuthority->namingAuthorityUrl != NULL ) {
if (BIO_printf(bp, "%*s namingAuthorityUrl: ", ind, "") <= 0
|| ASN1_STRING_print(bp, namingAuthority->namingAuthorityUrl) <= 0
|| BIO_printf(bp, "\n") <= 0)
goto err;
}
return 1;
err:
return 0;
}
static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
BIO *bp, int ind)
{
ADMISSION_SYNTAX * admission = (ADMISSION_SYNTAX *)in;
int i, j, k;
if (admission->admissionAuthority != NULL) {
if (BIO_printf(bp, "%*sadmissionAuthority:\n", ind, "") <= 0
|| BIO_printf(bp, "%*s ", ind, "") <= 0
|| GENERAL_NAME_print(bp, admission->admissionAuthority) <= 0
|| BIO_printf(bp, "\n") <= 0)
goto err;
}
for (i = 0; i < sk_ADMISSIONS_num(admission->contentsOfAdmissions); i++) {
- ADMISSIONS* entry = sk_ADMISSIONS_value(admission->contentsOfAdmissions, i);
+ ADMISSIONS *entry = sk_ADMISSIONS_value(admission->contentsOfAdmissions, i);
- if (BIO_printf(bp, "%*sEntry %0d:\n", ind, "", 1 + i) <= 0) goto err;
+ if (BIO_printf(bp, "%*sEntry %0d:\n", ind, "", 1 + i) <= 0)
+ goto err;
if (entry->admissionAuthority != NULL) {
if (BIO_printf(bp, "%*s admissionAuthority:\n", ind, "") <= 0
|| BIO_printf(bp, "%*s ", ind, "") <= 0
|| GENERAL_NAME_print(bp, entry->admissionAuthority) <= 0
|| BIO_printf(bp, "\n") <= 0)
goto err;
}
if (entry->namingAuthority != NULL) {
- if (i2r_NAMING_AUTHORITY(method, entry->namingAuthority, bp, ind) <= 0)
+ if (i2r_NAMING_AUTHORITY(method, entry->namingAuthority, bp, ind + 2) <= 0)
goto err;
}
for (j = 0; j < sk_PROFESSION_INFO_num(entry->professionInfos); j++) {
- PROFESSION_INFO* pinfo = sk_PROFESSION_INFO_value(entry->professionInfos, j);
+ PROFESSION_INFO *pinfo = sk_PROFESSION_INFO_value(entry->professionInfos, j);
if (BIO_printf(bp, "%*s Profession Info Entry %0d:\n", ind, "", 1 + j) <= 0)
goto err;
if (pinfo->registrationNumber != NULL) {
if (BIO_printf(bp, "%*s registrationNumber: ", ind, "") <= 0
|| ASN1_STRING_print(bp, pinfo->registrationNumber) <= 0
|| BIO_printf(bp, "\n") <= 0)
goto err;
}
if (pinfo->namingAuthority != NULL) {
- if (i2r_NAMING_AUTHORITY(method, pinfo->namingAuthority, bp, ind + 2) <= 0)
+ if (i2r_NAMING_AUTHORITY(method, pinfo->namingAuthority, bp, ind + 4) <= 0)
goto err;
}
if (pinfo->professionItems != NULL) {
if (BIO_printf(bp, "%*s Info Entries:\n", ind, "") <= 0)
goto err;
for (k = 0; k < sk_ASN1_STRING_num(pinfo->professionItems); k++) {
- ASN1_STRING* val = sk_ASN1_STRING_value(pinfo->professionItems, k);
+ ASN1_STRING *val = sk_ASN1_STRING_value(pinfo->professionItems, k);
if (BIO_printf(bp, "%*s ", ind, "") <= 0
|| ASN1_STRING_print(bp, val) <= 0
|| BIO_printf(bp, "\n") <= 0)
goto err;
}
}
if (pinfo->professionOIDs != NULL) {
if (BIO_printf(bp, "%*s Profession OIDs:\n", ind, "") <= 0)
goto err;
for (k = 0; k < sk_ASN1_OBJECT_num(pinfo->professionOIDs); k++) {
- ASN1_OBJECT* obj = sk_ASN1_OBJECT_value(pinfo->professionOIDs, k);
+ ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(pinfo->professionOIDs, k);
const char *ln = OBJ_nid2ln(OBJ_obj2nid(obj));
char objbuf[128];
OBJ_obj2txt(objbuf, sizeof(objbuf), obj, 1);
if (BIO_printf(bp, "%*s %s%s%s%s\n", ind, "",
ln ? ln : "", ln ? " (" : "",
objbuf, ln ? ")" : "") <= 0)
goto err;
}
}
}
}
return 1;
err:
return 0;
}
const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId(const NAMING_AUTHORITY *n)
{
return n->namingAuthorityId;
}
-void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n, ASN1_OBJECT* id)
+void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n, ASN1_OBJECT *id)
{
ASN1_OBJECT_free(n->namingAuthorityId);
n->namingAuthorityId = id;
}
-const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL(
- const NAMING_AUTHORITY *n)
+const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL(const NAMING_AUTHORITY *n)
{
return n->namingAuthorityUrl;
}
-void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n, ASN1_IA5STRING* u)
+void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n, ASN1_IA5STRING *u)
{
ASN1_IA5STRING_free(n->namingAuthorityUrl);
n->namingAuthorityUrl = u;
}
-const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText(
- const NAMING_AUTHORITY *n)
+const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText(const NAMING_AUTHORITY *n)
{
return n->namingAuthorityText;
}
-void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n, ASN1_STRING* t)
+void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n, ASN1_STRING *t)
{
ASN1_IA5STRING_free(n->namingAuthorityText);
n->namingAuthorityText = t;
}
const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority(const ADMISSION_SYNTAX *as)
{
return as->admissionAuthority;
}
void ADMISSION_SYNTAX_set0_admissionAuthority(ADMISSION_SYNTAX *as,
GENERAL_NAME *aa)
{
GENERAL_NAME_free(as->admissionAuthority);
as->admissionAuthority = aa;
}
const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions(const ADMISSION_SYNTAX *as)
{
return as->contentsOfAdmissions;
}
void ADMISSION_SYNTAX_set0_contentsOfAdmissions(ADMISSION_SYNTAX *as,
STACK_OF(ADMISSIONS) *a)
{
sk_ADMISSIONS_pop_free(as->contentsOfAdmissions, ADMISSIONS_free);
as->contentsOfAdmissions = a;
}
const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a)
{
return a->admissionAuthority;
}
void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa)
{
GENERAL_NAME_free(a->admissionAuthority);
a->admissionAuthority = aa;
}
const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a)
{
return a->namingAuthority;
}
void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na)
{
NAMING_AUTHORITY_free(a->namingAuthority);
a->namingAuthority = na;
}
const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a)
{
return a->professionInfos;
}
void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi)
{
sk_PROFESSION_INFO_pop_free(a->professionInfos, PROFESSION_INFO_free);
a->professionInfos = pi;
}
const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo(const PROFESSION_INFO *pi)
{
return pi->addProfessionInfo;
}
void PROFESSION_INFO_set0_addProfessionInfo(PROFESSION_INFO *pi,
ASN1_OCTET_STRING *aos)
{
ASN1_OCTET_STRING_free(pi->addProfessionInfo);
pi->addProfessionInfo = aos;
}
const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority(const PROFESSION_INFO *pi)
{
return pi->namingAuthority;
}
void PROFESSION_INFO_set0_namingAuthority(PROFESSION_INFO *pi,
NAMING_AUTHORITY *na)
{
NAMING_AUTHORITY_free(pi->namingAuthority);
pi->namingAuthority = na;
}
const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems(const PROFESSION_INFO *pi)
{
return pi->professionItems;
}
void PROFESSION_INFO_set0_professionItems(PROFESSION_INFO *pi,
STACK_OF(ASN1_STRING) *as)
{
sk_ASN1_STRING_pop_free(pi->professionItems, ASN1_STRING_free);
pi->professionItems = as;
}
const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs(const PROFESSION_INFO *pi)
{
return pi->professionOIDs;
}
void PROFESSION_INFO_set0_professionOIDs(PROFESSION_INFO *pi,
STACK_OF(ASN1_OBJECT) *po)
{
sk_ASN1_OBJECT_pop_free(pi->professionOIDs, ASN1_OBJECT_free);
pi->professionOIDs = po;
}
const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber(const PROFESSION_INFO *pi)
{
return pi->registrationNumber;
}
void PROFESSION_INFO_set0_registrationNumber(PROFESSION_INFO *pi,
ASN1_PRINTABLESTRING *rn)
{
ASN1_PRINTABLESTRING_free(pi->registrationNumber);
pi->registrationNumber = rn;
}
diff --git a/crypto/openssl/crypto/x509/v3_san.c b/crypto/openssl/crypto/x509/v3_san.c
index 34ca16a6d72d..d4999f1fc6c7 100644
--- a/crypto/openssl/crypto/x509/v3_san.c
+++ b/crypto/openssl/crypto/x509/v3_san.c
@@ -1,698 +1,699 @@
/*
* Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 "crypto/x509.h"
#include <openssl/conf.h>
#include <openssl/x509v3.h>
#include <openssl/bio.h>
#include "ext_dat.h"
static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *nval);
static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *nval);
static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
const X509V3_EXT_METHOD ossl_v3_alt[3] = {
{NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
0, 0, 0, 0,
0, 0,
(X509V3_EXT_I2V) i2v_GENERAL_NAMES,
(X509V3_EXT_V2I)v2i_subject_alt,
NULL, NULL, NULL},
{NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
0, 0, 0, 0,
0, 0,
(X509V3_EXT_I2V) i2v_GENERAL_NAMES,
(X509V3_EXT_V2I)v2i_issuer_alt,
NULL, NULL, NULL},
{NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
0, 0, 0, 0,
0, 0,
(X509V3_EXT_I2V) i2v_GENERAL_NAMES,
NULL, NULL, NULL, NULL},
};
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
GENERAL_NAMES *gens,
STACK_OF(CONF_VALUE) *ret)
{
int i;
GENERAL_NAME *gen;
STACK_OF(CONF_VALUE) *tmpret = NULL, *origret = ret;
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
gen = sk_GENERAL_NAME_value(gens, i);
/*
* i2v_GENERAL_NAME allocates ret if it is NULL. If something goes
* wrong we need to free the stack - but only if it was empty when we
* originally entered this function.
*/
tmpret = i2v_GENERAL_NAME(method, gen, ret);
if (tmpret == NULL) {
if (origret == NULL)
sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
return NULL;
}
ret = tmpret;
}
if (ret == NULL)
return sk_CONF_VALUE_new_null();
return ret;
}
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
GENERAL_NAME *gen,
STACK_OF(CONF_VALUE) *ret)
{
char othername[300];
char oline[256], *tmp;
switch (gen->type) {
case GEN_OTHERNAME:
switch (OBJ_obj2nid(gen->d.otherName->type_id)) {
case NID_id_on_SmtpUTF8Mailbox:
if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
|| !x509v3_add_len_value_uchar("othername: SmtpUTF8Mailbox:",
gen->d.otherName->value->value.utf8string->data,
gen->d.otherName->value->value.utf8string->length,
&ret))
return NULL;
break;
case NID_XmppAddr:
if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
|| !x509v3_add_len_value_uchar("othername: XmppAddr:",
gen->d.otherName->value->value.utf8string->data,
gen->d.otherName->value->value.utf8string->length,
&ret))
return NULL;
break;
case NID_SRVName:
if (gen->d.otherName->value->type != V_ASN1_IA5STRING
|| !x509v3_add_len_value_uchar("othername: SRVName:",
gen->d.otherName->value->value.ia5string->data,
gen->d.otherName->value->value.ia5string->length,
&ret))
return NULL;
break;
case NID_ms_upn:
if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
|| !x509v3_add_len_value_uchar("othername: UPN:",
gen->d.otherName->value->value.utf8string->data,
gen->d.otherName->value->value.utf8string->length,
&ret))
return NULL;
break;
case NID_NAIRealm:
if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
|| !x509v3_add_len_value_uchar("othername: NAIRealm:",
gen->d.otherName->value->value.utf8string->data,
gen->d.otherName->value->value.utf8string->length,
&ret))
return NULL;
break;
default:
if (OBJ_obj2txt(oline, sizeof(oline), gen->d.otherName->type_id, 0) > 0)
BIO_snprintf(othername, sizeof(othername), "othername: %s:",
oline);
else
OPENSSL_strlcpy(othername, "othername:", sizeof(othername));
/* check if the value is something printable */
if (gen->d.otherName->value->type == V_ASN1_IA5STRING) {
if (x509v3_add_len_value_uchar(othername,
gen->d.otherName->value->value.ia5string->data,
gen->d.otherName->value->value.ia5string->length,
&ret))
return ret;
}
if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) {
if (x509v3_add_len_value_uchar(othername,
gen->d.otherName->value->value.utf8string->data,
gen->d.otherName->value->value.utf8string->length,
&ret))
return ret;
}
if (!X509V3_add_value(othername, "<unsupported>", &ret))
return NULL;
break;
}
break;
case GEN_X400:
if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
return NULL;
break;
case GEN_EDIPARTY:
if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
return NULL;
break;
case GEN_EMAIL:
if (!x509v3_add_len_value_uchar("email", gen->d.ia5->data,
gen->d.ia5->length, &ret))
return NULL;
break;
case GEN_DNS:
if (!x509v3_add_len_value_uchar("DNS", gen->d.ia5->data,
gen->d.ia5->length, &ret))
return NULL;
break;
case GEN_URI:
if (!x509v3_add_len_value_uchar("URI", gen->d.ia5->data,
gen->d.ia5->length, &ret))
return NULL;
break;
case GEN_DIRNAME:
if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL
|| !X509V3_add_value("DirName", oline, &ret))
return NULL;
break;
case GEN_IPADD:
tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length);
if (tmp == NULL || !X509V3_add_value("IP Address", tmp, &ret))
ret = NULL;
OPENSSL_free(tmp);
break;
case GEN_RID:
i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
if (!X509V3_add_value("Registered ID", oline, &ret))
return NULL;
break;
}
return ret;
}
int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
{
char *tmp;
int nid;
switch (gen->type) {
case GEN_OTHERNAME:
nid = OBJ_obj2nid(gen->d.otherName->type_id);
/* Validate the types are as we expect before we use them */
if ((nid == NID_SRVName
&& gen->d.otherName->value->type != V_ASN1_IA5STRING)
|| (nid != NID_SRVName
&& gen->d.otherName->value->type != V_ASN1_UTF8STRING)) {
BIO_printf(out, "othername:<unsupported>");
break;
}
switch (nid) {
case NID_id_on_SmtpUTF8Mailbox:
BIO_printf(out, "othername:SmtpUTF8Mailbox:%.*s",
gen->d.otherName->value->value.utf8string->length,
gen->d.otherName->value->value.utf8string->data);
break;
case NID_XmppAddr:
BIO_printf(out, "othername:XmppAddr:%.*s",
gen->d.otherName->value->value.utf8string->length,
gen->d.otherName->value->value.utf8string->data);
break;
case NID_SRVName:
BIO_printf(out, "othername:SRVName:%.*s",
gen->d.otherName->value->value.ia5string->length,
gen->d.otherName->value->value.ia5string->data);
break;
case NID_ms_upn:
BIO_printf(out, "othername:UPN:%.*s",
gen->d.otherName->value->value.utf8string->length,
gen->d.otherName->value->value.utf8string->data);
break;
case NID_NAIRealm:
BIO_printf(out, "othername:NAIRealm:%.*s",
gen->d.otherName->value->value.utf8string->length,
gen->d.otherName->value->value.utf8string->data);
break;
default:
BIO_printf(out, "othername:<unsupported>");
break;
}
break;
case GEN_X400:
BIO_printf(out, "X400Name:<unsupported>");
break;
case GEN_EDIPARTY:
/* Maybe fix this: it is supported now */
BIO_printf(out, "EdiPartyName:<unsupported>");
break;
case GEN_EMAIL:
BIO_printf(out, "email:");
ASN1_STRING_print(out, gen->d.ia5);
break;
case GEN_DNS:
BIO_printf(out, "DNS:");
ASN1_STRING_print(out, gen->d.ia5);
break;
case GEN_URI:
BIO_printf(out, "URI:");
ASN1_STRING_print(out, gen->d.ia5);
break;
case GEN_DIRNAME:
BIO_printf(out, "DirName:");
X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
break;
case GEN_IPADD:
tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length);
if (tmp == NULL)
return 0;
BIO_printf(out, "IP Address:%s", tmp);
OPENSSL_free(tmp);
break;
case GEN_RID:
BIO_printf(out, "Registered ID:");
i2a_ASN1_OBJECT(out, gen->d.rid);
break;
}
return 1;
}
static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *nval)
{
const int num = sk_CONF_VALUE_num(nval);
GENERAL_NAMES *gens = sk_GENERAL_NAME_new_reserve(NULL, num);
int i;
if (gens == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
sk_GENERAL_NAME_free(gens);
return NULL;
}
for (i = 0; i < num; i++) {
CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
if (!ossl_v3_name_cmp(cnf->name, "issuer")
&& cnf->value && strcmp(cnf->value, "copy") == 0) {
if (!copy_issuer(ctx, gens))
goto err;
} else {
GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
if (gen == NULL)
goto err;
sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
}
}
return gens;
err:
sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
return NULL;
}
/* Append subject altname of issuer to issuer alt name of subject */
static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
{
- GENERAL_NAMES *ialt;
+ GENERAL_NAMES *ialt = NULL;
GENERAL_NAME *gen;
X509_EXTENSION *ext;
int i, num;
if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
return 1;
if (!ctx || !ctx->issuer_cert) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_DETAILS);
goto err;
}
i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
if (i < 0)
return 1;
if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL
|| (ialt = X509V3_EXT_d2i(ext)) == NULL) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_ISSUER_DECODE_ERROR);
goto err;
}
num = sk_GENERAL_NAME_num(ialt);
if (!sk_GENERAL_NAME_reserve(gens, num)) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
for (i = 0; i < num; i++) {
gen = sk_GENERAL_NAME_value(ialt, i);
sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
}
sk_GENERAL_NAME_free(ialt);
return 1;
err:
+ sk_GENERAL_NAME_free(ialt);
return 0;
}
static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *nval)
{
GENERAL_NAMES *gens;
CONF_VALUE *cnf;
const int num = sk_CONF_VALUE_num(nval);
int i;
gens = sk_GENERAL_NAME_new_reserve(NULL, num);
if (gens == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
sk_GENERAL_NAME_free(gens);
return NULL;
}
for (i = 0; i < num; i++) {
cnf = sk_CONF_VALUE_value(nval, i);
if (ossl_v3_name_cmp(cnf->name, "email") == 0
&& cnf->value && strcmp(cnf->value, "copy") == 0) {
if (!copy_email(ctx, gens, 0))
goto err;
} else if (ossl_v3_name_cmp(cnf->name, "email") == 0
&& cnf->value && strcmp(cnf->value, "move") == 0) {
if (!copy_email(ctx, gens, 1))
goto err;
} else {
GENERAL_NAME *gen;
if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
goto err;
sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
}
}
return gens;
err:
sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
return NULL;
}
/*
* Copy any email addresses in a certificate or request to GENERAL_NAMES
*/
static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
{
X509_NAME *nm;
ASN1_IA5STRING *email = NULL;
X509_NAME_ENTRY *ne;
GENERAL_NAME *gen = NULL;
int i = -1;
if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
return 1;
if (ctx == NULL
|| (ctx->subject_cert == NULL && ctx->subject_req == NULL)) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS);
return 0;
}
/* Find the subject name */
nm = ctx->subject_cert != NULL ?
X509_get_subject_name(ctx->subject_cert) :
X509_REQ_get_subject_name(ctx->subject_req);
/* Now add any email address(es) to STACK */
while ((i = X509_NAME_get_index_by_NID(nm,
NID_pkcs9_emailAddress, i)) >= 0) {
ne = X509_NAME_get_entry(nm, i);
email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
if (move_p) {
X509_NAME_delete_entry(nm, i);
X509_NAME_ENTRY_free(ne);
i--;
}
if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
gen->d.ia5 = email;
email = NULL;
gen->type = GEN_EMAIL;
if (!sk_GENERAL_NAME_push(gens, gen)) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
gen = NULL;
}
return 1;
err:
GENERAL_NAME_free(gen);
ASN1_IA5STRING_free(email);
return 0;
}
GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
{
GENERAL_NAME *gen;
GENERAL_NAMES *gens;
CONF_VALUE *cnf;
const int num = sk_CONF_VALUE_num(nval);
int i;
gens = sk_GENERAL_NAME_new_reserve(NULL, num);
if (gens == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
sk_GENERAL_NAME_free(gens);
return NULL;
}
for (i = 0; i < num; i++) {
cnf = sk_CONF_VALUE_value(nval, i);
if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
goto err;
sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
}
return gens;
err:
sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
return NULL;
}
GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, CONF_VALUE *cnf)
{
return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
}
GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, int gen_type, const char *value,
int is_nc)
{
char is_string = 0;
GENERAL_NAME *gen = NULL;
if (!value) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
return NULL;
}
if (out)
gen = out;
else {
gen = GENERAL_NAME_new();
if (gen == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
switch (gen_type) {
case GEN_URI:
case GEN_EMAIL:
case GEN_DNS:
is_string = 1;
break;
case GEN_RID:
{
ASN1_OBJECT *obj;
if ((obj = OBJ_txt2obj(value, 0)) == NULL) {
ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT,
"value=%s", value);
goto err;
}
gen->d.rid = obj;
}
break;
case GEN_IPADD:
if (is_nc)
gen->d.ip = a2i_IPADDRESS_NC(value);
else
gen->d.ip = a2i_IPADDRESS(value);
if (gen->d.ip == NULL) {
ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_IP_ADDRESS,
"value=%s", value);
goto err;
}
break;
case GEN_DIRNAME:
if (!do_dirname(gen, value, ctx)) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_DIRNAME_ERROR);
goto err;
}
break;
case GEN_OTHERNAME:
if (!do_othername(gen, value, ctx)) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_OTHERNAME_ERROR);
goto err;
}
break;
default:
ERR_raise(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_TYPE);
goto err;
}
if (is_string) {
if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL ||
!ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
strlen(value))) {
ASN1_IA5STRING_free(gen->d.ia5);
gen->d.ia5 = NULL;
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
}
gen->type = gen_type;
return gen;
err:
if (!out)
GENERAL_NAME_free(gen);
return NULL;
}
GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
{
int type;
char *name, *value;
name = cnf->name;
value = cnf->value;
if (!value) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
return NULL;
}
if (!ossl_v3_name_cmp(name, "email"))
type = GEN_EMAIL;
else if (!ossl_v3_name_cmp(name, "URI"))
type = GEN_URI;
else if (!ossl_v3_name_cmp(name, "DNS"))
type = GEN_DNS;
else if (!ossl_v3_name_cmp(name, "RID"))
type = GEN_RID;
else if (!ossl_v3_name_cmp(name, "IP"))
type = GEN_IPADD;
else if (!ossl_v3_name_cmp(name, "dirName"))
type = GEN_DIRNAME;
else if (!ossl_v3_name_cmp(name, "otherName"))
type = GEN_OTHERNAME;
else {
ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_OPTION,
"name=%s", name);
return NULL;
}
return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
}
static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
{
char *objtmp = NULL, *p;
int objlen;
if ((p = strchr(value, ';')) == NULL)
return 0;
if ((gen->d.otherName = OTHERNAME_new()) == NULL)
return 0;
/*
* Free this up because we will overwrite it. no need to free type_id
* because it is static
*/
ASN1_TYPE_free(gen->d.otherName->value);
if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL)
goto err;
objlen = p - value;
objtmp = OPENSSL_strndup(value, objlen);
if (objtmp == NULL)
goto err;
gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
OPENSSL_free(objtmp);
if (!gen->d.otherName->type_id)
goto err;
return 1;
err:
OTHERNAME_free(gen->d.otherName);
gen->d.otherName = NULL;
return 0;
}
static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
{
int ret = 0;
STACK_OF(CONF_VALUE) *sk = NULL;
X509_NAME *nm;
if ((nm = X509_NAME_new()) == NULL)
goto err;
sk = X509V3_get_section(ctx, value);
if (!sk) {
ERR_raise_data(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND,
"section=%s", value);
goto err;
}
/* FIXME: should allow other character types... */
ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
if (!ret)
goto err;
gen->d.dirn = nm;
err:
if (ret == 0)
X509_NAME_free(nm);
X509V3_section_free(ctx, sk);
return ret;
}
diff --git a/crypto/openssl/crypto/x509/x509_cmp.c b/crypto/openssl/crypto/x509/x509_cmp.c
index 989fb8faa9f4..f2c3a568198d 100644
--- a/crypto/openssl/crypto/x509/x509_cmp.c
+++ b/crypto/openssl/crypto/x509/x509_cmp.c
@@ -1,588 +1,590 @@
/*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/asn1.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/core_names.h>
#include "crypto/x509.h"
int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
{
int i;
const X509_CINF *ai, *bi;
if (b == NULL)
return a != NULL;
if (a == NULL)
return -1;
ai = &a->cert_info;
bi = &b->cert_info;
i = ASN1_INTEGER_cmp(&ai->serialNumber, &bi->serialNumber);
if (i != 0)
return i < 0 ? -1 : 1;
return X509_NAME_cmp(ai->issuer, bi->issuer);
}
#ifndef OPENSSL_NO_MD5
unsigned long X509_issuer_and_serial_hash(X509 *a)
{
unsigned long ret = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned char md[16];
char *f = NULL;
EVP_MD *digest = NULL;
if (ctx == NULL)
goto err;
f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0);
if (f == NULL)
goto err;
digest = EVP_MD_fetch(a->libctx, SN_md5, a->propq);
if (digest == NULL)
goto err;
if (!EVP_DigestInit_ex(ctx, digest, NULL))
goto err;
if (!EVP_DigestUpdate(ctx, (unsigned char *)f, strlen(f)))
goto err;
if (!EVP_DigestUpdate
(ctx, (unsigned char *)a->cert_info.serialNumber.data,
(unsigned long)a->cert_info.serialNumber.length))
goto err;
if (!EVP_DigestFinal_ex(ctx, &(md[0]), NULL))
goto err;
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
err:
OPENSSL_free(f);
EVP_MD_free(digest);
EVP_MD_CTX_free(ctx);
return ret;
}
#endif
int X509_issuer_name_cmp(const X509 *a, const X509 *b)
{
return X509_NAME_cmp(a->cert_info.issuer, b->cert_info.issuer);
}
int X509_subject_name_cmp(const X509 *a, const X509 *b)
{
return X509_NAME_cmp(a->cert_info.subject, b->cert_info.subject);
}
int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
{
return X509_NAME_cmp(a->crl.issuer, b->crl.issuer);
}
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
{
int rv;
if ((a->flags & EXFLAG_NO_FINGERPRINT) == 0
&& (b->flags & EXFLAG_NO_FINGERPRINT) == 0)
rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
else
return -2;
return rv < 0 ? -1 : rv > 0;
}
X509_NAME *X509_get_issuer_name(const X509 *a)
{
return a->cert_info.issuer;
}
unsigned long X509_issuer_name_hash(X509 *x)
{
return X509_NAME_hash_ex(x->cert_info.issuer, NULL, NULL, NULL);
}
#ifndef OPENSSL_NO_MD5
unsigned long X509_issuer_name_hash_old(X509 *x)
{
return X509_NAME_hash_old(x->cert_info.issuer);
}
#endif
X509_NAME *X509_get_subject_name(const X509 *a)
{
return a->cert_info.subject;
}
ASN1_INTEGER *X509_get_serialNumber(X509 *a)
{
return &a->cert_info.serialNumber;
}
const ASN1_INTEGER *X509_get0_serialNumber(const X509 *a)
{
return &a->cert_info.serialNumber;
}
unsigned long X509_subject_name_hash(X509 *x)
{
return X509_NAME_hash_ex(x->cert_info.subject, NULL, NULL, NULL);
}
#ifndef OPENSSL_NO_MD5
unsigned long X509_subject_name_hash_old(X509 *x)
{
return X509_NAME_hash_old(x->cert_info.subject);
}
#endif
/*
* Compare two certificates: they must be identical for this to work. NB:
* Although "cmp" operations are generally prototyped to take "const"
* arguments (eg. for use in STACKs), the way X509 handling is - these
* operations may involve ensuring the hashes are up-to-date and ensuring
* certain cert information is cached. So this is the point where the
* "depth-first" constification tree has to halt with an evil cast.
*/
int X509_cmp(const X509 *a, const X509 *b)
{
int rv = 0;
if (a == b) /* for efficiency */
return 0;
/* attempt to compute cert hash */
(void)X509_check_purpose((X509 *)a, -1, 0);
(void)X509_check_purpose((X509 *)b, -1, 0);
if ((a->ex_flags & EXFLAG_NO_FINGERPRINT) == 0
&& (b->ex_flags & EXFLAG_NO_FINGERPRINT) == 0)
rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
if (rv != 0)
return rv < 0 ? -1 : 1;
/* Check for match against stored encoding too */
if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) {
if (a->cert_info.enc.len < b->cert_info.enc.len)
return -1;
if (a->cert_info.enc.len > b->cert_info.enc.len)
return 1;
rv = memcmp(a->cert_info.enc.enc,
b->cert_info.enc.enc, a->cert_info.enc.len);
}
return rv < 0 ? -1 : rv > 0;
}
int ossl_x509_add_cert_new(STACK_OF(X509) **p_sk, X509 *cert, int flags)
{
if (*p_sk == NULL && (*p_sk = sk_X509_new_null()) == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
return X509_add_cert(*p_sk, cert, flags);
}
int X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags)
{
if (sk == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+ if (cert == NULL)
+ return 0;
if ((flags & X509_ADD_FLAG_NO_DUP) != 0) {
/*
* not using sk_X509_set_cmp_func() and sk_X509_find()
* because this re-orders the certs on the stack
*/
int i;
for (i = 0; i < sk_X509_num(sk); i++) {
if (X509_cmp(sk_X509_value(sk, i), cert) == 0)
return 1;
}
}
if ((flags & X509_ADD_FLAG_NO_SS) != 0) {
int ret = X509_self_signed(cert, 0);
if (ret != 0)
return ret > 0 ? 1 : 0;
}
if (!sk_X509_insert(sk, cert,
(flags & X509_ADD_FLAG_PREPEND) != 0 ? 0 : -1)) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
if ((flags & X509_ADD_FLAG_UP_REF) != 0)
(void)X509_up_ref(cert);
return 1;
}
int X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags)
/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */
{
if (sk == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
return ossl_x509_add_certs_new(&sk, certs, flags);
}
int ossl_x509_add_certs_new(STACK_OF(X509) **p_sk, STACK_OF(X509) *certs,
int flags)
/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */
{
int n = sk_X509_num(certs /* may be NULL */);
int i;
for (i = 0; i < n; i++) {
int j = (flags & X509_ADD_FLAG_PREPEND) == 0 ? i : n - 1 - i;
/* if prepend, add certs in reverse order to keep original order */
if (!ossl_x509_add_cert_new(p_sk, sk_X509_value(certs, j), flags))
return 0;
}
return 1;
}
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
{
int ret;
if (b == NULL)
return a != NULL;
if (a == NULL)
return -1;
/* Ensure canonical encoding is present and up to date */
if (a->canon_enc == NULL || a->modified) {
ret = i2d_X509_NAME((X509_NAME *)a, NULL);
if (ret < 0)
return -2;
}
if (b->canon_enc == NULL || b->modified) {
ret = i2d_X509_NAME((X509_NAME *)b, NULL);
if (ret < 0)
return -2;
}
ret = a->canon_enclen - b->canon_enclen;
if (ret == 0 && a->canon_enclen == 0)
return 0;
if (ret == 0) {
if (a->canon_enc == NULL || b->canon_enc == NULL)
return -2;
ret = memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
}
return ret < 0 ? -1 : ret > 0;
}
unsigned long X509_NAME_hash_ex(const X509_NAME *x, OSSL_LIB_CTX *libctx,
const char *propq, int *ok)
{
unsigned long ret = 0;
unsigned char md[SHA_DIGEST_LENGTH];
EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
int i2d_ret;
/* Make sure X509_NAME structure contains valid cached encoding */
i2d_ret = i2d_X509_NAME(x, NULL);
if (ok != NULL)
*ok = 0;
if (i2d_ret >= 0 && sha1 != NULL
&& EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, sha1, NULL)) {
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
if (ok != NULL)
*ok = 1;
}
EVP_MD_free(sha1);
return ret;
}
#ifndef OPENSSL_NO_MD5
/*
* I now DER encode the name and hash it. Since I cache the DER encoding,
* this is reasonably efficient.
*/
unsigned long X509_NAME_hash_old(const X509_NAME *x)
{
EVP_MD *md5 = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_MD5, "-fips");
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
unsigned long ret = 0;
unsigned char md[16];
if (md5 == NULL || md_ctx == NULL)
goto end;
/* Make sure X509_NAME structure contains valid cached encoding */
if (i2d_X509_NAME(x, NULL) < 0)
goto end;
if (EVP_DigestInit_ex(md_ctx, md5, NULL)
&& EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length)
&& EVP_DigestFinal_ex(md_ctx, md, NULL))
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
end:
EVP_MD_CTX_free(md_ctx);
EVP_MD_free(md5);
return ret;
}
#endif
/* Search a stack of X509 for a match */
X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, const X509_NAME *name,
const ASN1_INTEGER *serial)
{
int i;
X509 x, *x509 = NULL;
if (!sk)
return NULL;
x.cert_info.serialNumber = *serial;
x.cert_info.issuer = (X509_NAME *)name; /* won't modify it */
for (i = 0; i < sk_X509_num(sk); i++) {
x509 = sk_X509_value(sk, i);
if (X509_issuer_and_serial_cmp(x509, &x) == 0)
return x509;
}
return NULL;
}
X509 *X509_find_by_subject(STACK_OF(X509) *sk, const X509_NAME *name)
{
X509 *x509;
int i;
for (i = 0; i < sk_X509_num(sk); i++) {
x509 = sk_X509_value(sk, i);
if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0)
return x509;
}
return NULL;
}
EVP_PKEY *X509_get0_pubkey(const X509 *x)
{
if (x == NULL)
return NULL;
return X509_PUBKEY_get0(x->cert_info.key);
}
EVP_PKEY *X509_get_pubkey(X509 *x)
{
if (x == NULL)
return NULL;
return X509_PUBKEY_get(x->cert_info.key);
}
int X509_check_private_key(const X509 *x, const EVP_PKEY *k)
{
const EVP_PKEY *xk;
int ret;
xk = X509_get0_pubkey(x);
if (xk == NULL) {
ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
return 0;
}
switch (ret = EVP_PKEY_eq(xk, k)) {
case 0:
ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH);
break;
case -1:
ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH);
break;
case -2:
ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE);
break;
}
return ret > 0;
}
/*
* Check a suite B algorithm is permitted: pass in a public key and the NID
* of its signature (or 0 if no signature). The pflags is a pointer to a
* flags field which must contain the suite B verification flags.
*/
#ifndef OPENSSL_NO_EC
static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
{
char curve_name[80];
size_t curve_name_len;
int curve_nid;
if (pkey == NULL || !EVP_PKEY_is_a(pkey, "EC"))
return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
if (!EVP_PKEY_get_group_name(pkey, curve_name, sizeof(curve_name),
&curve_name_len))
return X509_V_ERR_SUITE_B_INVALID_CURVE;
curve_nid = OBJ_txt2nid(curve_name);
/* Check curve is consistent with LOS */
if (curve_nid == NID_secp384r1) { /* P-384 */
/*
* Check signature algorithm is consistent with curve.
*/
if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
/* If we encounter P-384 we cannot use P-256 later */
*pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
} else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */
if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
} else {
return X509_V_ERR_SUITE_B_INVALID_CURVE;
}
return X509_V_OK;
}
int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
unsigned long flags)
{
int rv, i, sign_nid;
EVP_PKEY *pk;
unsigned long tflags = flags;
if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
return X509_V_OK;
/* If no EE certificate passed in must be first in chain */
if (x == NULL) {
x = sk_X509_value(chain, 0);
i = 1;
} else {
i = 0;
}
pk = X509_get0_pubkey(x);
/*
* With DANE-EE(3) success, or DANE-EE(3)/PKIX-EE(1) failure we don't build
* a chain all, just report trust success or failure, but must also report
* Suite-B errors if applicable. This is indicated via a NULL chain
* pointer. All we need to do is check the leaf key algorithm.
*/
if (chain == NULL)
return check_suite_b(pk, -1, &tflags);
if (X509_get_version(x) != X509_VERSION_3) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
/* Correct error depth */
i = 0;
goto end;
}
/* Check EE key only */
rv = check_suite_b(pk, -1, &tflags);
if (rv != X509_V_OK) {
/* Correct error depth */
i = 0;
goto end;
}
for (; i < sk_X509_num(chain); i++) {
sign_nid = X509_get_signature_nid(x);
x = sk_X509_value(chain, i);
if (X509_get_version(x) != X509_VERSION_3) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
goto end;
}
pk = X509_get0_pubkey(x);
rv = check_suite_b(pk, sign_nid, &tflags);
if (rv != X509_V_OK)
goto end;
}
/* Final check: root CA signature */
rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
end:
if (rv != X509_V_OK) {
/* Invalid signature or LOS errors are for previous cert */
if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
|| rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
i--;
/*
* If we have LOS error and flags changed then we are signing P-384
* with P-256. Use more meaningful error.
*/
if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
if (perror_depth)
*perror_depth = i;
}
return rv;
}
int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
{
int sign_nid;
if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
return X509_V_OK;
sign_nid = OBJ_obj2nid(crl->crl.sig_alg.algorithm);
return check_suite_b(pk, sign_nid, &flags);
}
#else
int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
unsigned long flags)
{
return 0;
}
int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
{
return 0;
}
#endif
/*
* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
* count but it has the same effect by duping the STACK and upping the ref of
* each X509 structure.
*/
STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
{
STACK_OF(X509) *ret = sk_X509_dup(chain);
int i;
if (ret == NULL)
return NULL;
for (i = 0; i < sk_X509_num(ret); i++) {
X509 *x = sk_X509_value(ret, i);
if (!X509_up_ref(x))
goto err;
}
return ret;
err:
while (i-- > 0)
X509_free(sk_X509_value(ret, i));
sk_X509_free(ret);
return NULL;
}
diff --git a/crypto/openssl/crypto/x509/x_all.c b/crypto/openssl/crypto/x509/x_all.c
index e58c9ab1c117..158e11a8649c 100644
--- a/crypto/openssl/crypto/x509/x_all.c
+++ b/crypto/openssl/crypto/x509/x_all.c
@@ -1,778 +1,780 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* Low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/http.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/x509v3.h>
#include "internal/asn1.h"
#include "crypto/pkcs7.h"
#include "crypto/x509.h"
#include "crypto/rsa.h"
int X509_verify(X509 *a, EVP_PKEY *r)
{
if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature) != 0)
return 0;
return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg,
&a->signature, &a->cert_info,
a->distinguishing_id, r, a->libctx, a->propq);
}
int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *r, OSSL_LIB_CTX *libctx,
const char *propq)
{
return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_REQ_INFO), &a->sig_alg,
a->signature, &a->req_info, a->distinguishing_id,
r, libctx, propq);
}
int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
{
return X509_REQ_verify_ex(a, r, NULL, NULL);
}
int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r)
{
return ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC),
&a->sig_algor, a->signature, a->spkac, r);
}
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
{
if (x == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/*
* Setting the modified flag before signing it. This makes the cached
* encoding to be ignored, so even if the certificate fields have changed,
* they are signed correctly.
* The X509_sign_ctx, X509_REQ_sign{,_ctx}, X509_CRL_sign{,_ctx} functions
* which exist below are the same.
*/
x->cert_info.enc.modified = 1;
return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature,
&x->sig_alg, &x->signature, &x->cert_info, NULL,
pkey, md, x->libctx, x->propq);
}
int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
{
if (x == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
x->cert_info.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
&x->cert_info.signature,
&x->sig_alg, &x->signature, &x->cert_info, ctx);
}
static ASN1_VALUE *simple_get_asn1(const char *url, BIO *bio, BIO *rbio,
int timeout, const ASN1_ITEM *it)
{
+ size_t max_resp_len = (it == ASN1_ITEM_rptr(X509_CRL)) ?
+ OSSL_HTTP_DEFAULT_MAX_CRL_LEN : OSSL_HTTP_DEFAULT_MAX_RESP_LEN;
BIO *mem = OSSL_HTTP_get(url, NULL /* proxy */, NULL /* no_proxy */,
bio, rbio, NULL /* cb */, NULL /* arg */,
1024 /* buf_size */, NULL /* headers */,
NULL /* expected_ct */, 1 /* expect_asn1 */,
- OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout);
+ max_resp_len, timeout);
ASN1_VALUE *res = ASN1_item_d2i_bio(it, mem, NULL);
BIO_free(mem);
return res;
}
X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout)
{
return (X509 *)simple_get_asn1(url, bio, rbio, timeout,
ASN1_ITEM_rptr(X509));
}
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
{
if (x == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
x->req_info.enc.modified = 1;
return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL,
x->signature, &x->req_info, NULL,
pkey, md, x->libctx, x->propq);
}
int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
{
if (x == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
x->req_info.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
&x->sig_alg, NULL, x->signature, &x->req_info,
ctx);
}
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
{
if (x == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
x->crl.enc.modified = 1;
return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_CRL_INFO), &x->crl.sig_alg,
&x->sig_alg, &x->signature, &x->crl, NULL,
pkey, md, x->libctx, x->propq);
}
int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
{
if (x == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
x->crl.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
&x->crl.sig_alg, &x->sig_alg, &x->signature,
&x->crl, ctx);
}
X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout)
{
return (X509_CRL *)simple_get_asn1(url, bio, rbio, timeout,
ASN1_ITEM_rptr(X509_CRL));
}
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
{
return
ASN1_item_sign_ex(ASN1_ITEM_rptr(NETSCAPE_SPKAC), &x->sig_algor, NULL,
x->signature, x->spkac, NULL, pkey, md, NULL, NULL);
}
#ifndef OPENSSL_NO_STDIO
X509 *d2i_X509_fp(FILE *fp, X509 **x509)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
}
int i2d_X509_fp(FILE *fp, const X509 *x509)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
}
#endif
X509 *d2i_X509_bio(BIO *bp, X509 **x509)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
}
int i2d_X509_bio(BIO *bp, const X509 *x509)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
}
#ifndef OPENSSL_NO_STDIO
X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
}
int i2d_X509_CRL_fp(FILE *fp, const X509_CRL *crl)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
}
#endif
X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
}
int i2d_X509_CRL_bio(BIO *bp, const X509_CRL *crl)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
}
#ifndef OPENSSL_NO_STDIO
PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
{
PKCS7 *ret;
OSSL_LIB_CTX *libctx = NULL;
const char *propq = NULL;
if (p7 != NULL && *p7 != NULL) {
libctx = (*p7)->ctx.libctx;
propq = (*p7)->ctx.propq;
}
ret = ASN1_item_d2i_fp_ex(ASN1_ITEM_rptr(PKCS7), fp, p7, libctx, propq);
if (ret != NULL)
ossl_pkcs7_resolve_libctx(ret);
return ret;
}
int i2d_PKCS7_fp(FILE *fp, const PKCS7 *p7)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
}
#endif
PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
{
PKCS7 *ret;
OSSL_LIB_CTX *libctx = NULL;
const char *propq = NULL;
if (p7 != NULL && *p7 != NULL) {
libctx = (*p7)->ctx.libctx;
propq = (*p7)->ctx.propq;
}
ret = ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(PKCS7), bp, p7, libctx, propq);
if (ret != NULL)
ossl_pkcs7_resolve_libctx(ret);
return ret;
}
int i2d_PKCS7_bio(BIO *bp, const PKCS7 *p7)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
}
#ifndef OPENSSL_NO_STDIO
X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
}
int i2d_X509_REQ_fp(FILE *fp, const X509_REQ *req)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
}
#endif
X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
{
OSSL_LIB_CTX *libctx = NULL;
const char *propq = NULL;
if (req != NULL && *req != NULL) {
libctx = (*req)->libctx;
propq = (*req)->propq;
}
return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(X509_REQ), bp, req, libctx, propq);
}
int i2d_X509_REQ_bio(BIO *bp, const X509_REQ *req)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
}
#ifndef OPENSSL_NO_STDIO
RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
}
int i2d_RSAPrivateKey_fp(FILE *fp, const RSA *rsa)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
}
RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
}
RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
{
return ASN1_d2i_fp((void *(*)(void))
RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp,
(void **)rsa);
}
int i2d_RSAPublicKey_fp(FILE *fp, const RSA *rsa)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
}
int i2d_RSA_PUBKEY_fp(FILE *fp, const RSA *rsa)
{
return ASN1_i2d_fp((I2D_OF(void))i2d_RSA_PUBKEY, fp, rsa);
}
#endif
RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
}
int i2d_RSAPrivateKey_bio(BIO *bp, const RSA *rsa)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
}
RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
}
RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
{
return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa);
}
int i2d_RSAPublicKey_bio(BIO *bp, const RSA *rsa)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
}
int i2d_RSA_PUBKEY_bio(BIO *bp, const RSA *rsa)
{
return ASN1_i2d_bio_of(RSA, i2d_RSA_PUBKEY, bp, rsa);
}
#ifndef OPENSSL_NO_DSA
# ifndef OPENSSL_NO_STDIO
DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
{
return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa);
}
int i2d_DSAPrivateKey_fp(FILE *fp, const DSA *dsa)
{
return ASN1_i2d_fp_of(DSA, i2d_DSAPrivateKey, fp, dsa);
}
DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
{
return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa);
}
int i2d_DSA_PUBKEY_fp(FILE *fp, const DSA *dsa)
{
return ASN1_i2d_fp_of(DSA, i2d_DSA_PUBKEY, fp, dsa);
}
# endif
DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
{
return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa);
}
int i2d_DSAPrivateKey_bio(BIO *bp, const DSA *dsa)
{
return ASN1_i2d_bio_of(DSA, i2d_DSAPrivateKey, bp, dsa);
}
DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
{
return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa);
}
int i2d_DSA_PUBKEY_bio(BIO *bp, const DSA *dsa)
{
return ASN1_i2d_bio_of(DSA, i2d_DSA_PUBKEY, bp, dsa);
}
#endif
#ifndef OPENSSL_NO_EC
# ifndef OPENSSL_NO_STDIO
EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
{
return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey);
}
int i2d_EC_PUBKEY_fp(FILE *fp, const EC_KEY *eckey)
{
return ASN1_i2d_fp_of(EC_KEY, i2d_EC_PUBKEY, fp, eckey);
}
EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
{
return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey);
}
int i2d_ECPrivateKey_fp(FILE *fp, const EC_KEY *eckey)
{
return ASN1_i2d_fp_of(EC_KEY, i2d_ECPrivateKey, fp, eckey);
}
# endif
EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
{
return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey);
}
int i2d_EC_PUBKEY_bio(BIO *bp, const EC_KEY *ecdsa)
{
return ASN1_i2d_bio_of(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa);
}
EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
{
return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey);
}
int i2d_ECPrivateKey_bio(BIO *bp, const EC_KEY *eckey)
{
return ASN1_i2d_bio_of(EC_KEY, i2d_ECPrivateKey, bp, eckey);
}
#endif
int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
ASN1_BIT_STRING *key = X509_get0_pubkey_bitstr(data);
if (key == NULL)
return 0;
return EVP_Digest(key->data, key->length, md, len, type, NULL);
}
int X509_digest(const X509 *cert, const EVP_MD *md, unsigned char *data,
unsigned int *len)
{
if (EVP_MD_is_a(md, SN_sha1) && (cert->ex_flags & EXFLAG_SET) != 0
&& (cert->ex_flags & EXFLAG_NO_FINGERPRINT) == 0) {
/* Asking for SHA1 and we already computed it. */
if (len != NULL)
*len = sizeof(cert->sha1_hash);
memcpy(data, cert->sha1_hash, sizeof(cert->sha1_hash));
return 1;
}
return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509), md, (char *)cert,
data, len, cert->libctx, cert->propq);
}
/* calculate cert digest using the same hash algorithm as in its signature */
ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
EVP_MD **md_used, int *md_is_fallback)
{
unsigned int len;
unsigned char hash[EVP_MAX_MD_SIZE];
int mdnid, pknid;
EVP_MD *md = NULL;
const char *md_name;
ASN1_OCTET_STRING *new;
if (md_used != NULL)
*md_used = NULL;
if (md_is_fallback != NULL)
*md_is_fallback = 0;
if (cert == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (!OBJ_find_sigid_algs(X509_get_signature_nid(cert), &mdnid, &pknid)) {
ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_SIGID_ALGS);
return NULL;
}
if (mdnid == NID_undef) {
if (pknid == EVP_PKEY_RSA_PSS) {
RSA_PSS_PARAMS *pss = ossl_rsa_pss_decode(&cert->sig_alg);
const EVP_MD *mgf1md, *mmd = NULL;
int saltlen, trailerfield;
if (pss == NULL
|| !ossl_rsa_pss_get_param_unverified(pss, &mmd, &mgf1md,
&saltlen,
&trailerfield)
|| mmd == NULL) {
RSA_PSS_PARAMS_free(pss);
ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
RSA_PSS_PARAMS_free(pss);
/* Fetch explicitly and do not fallback */
if ((md = EVP_MD_fetch(cert->libctx, EVP_MD_get0_name(mmd),
cert->propq)) == NULL)
/* Error code from fetch is sufficient */
return NULL;
} else if (pknid != NID_undef) {
/* A known algorithm, but without a digest */
switch (pknid) {
case NID_ED25519: /* Follow CMS default given in RFC8419 */
md_name = "SHA512";
break;
case NID_ED448: /* Follow CMS default given in RFC8419 */
md_name = "SHAKE256";
break;
default: /* Fall back to SHA-256 */
md_name = "SHA256";
break;
}
if ((md = EVP_MD_fetch(cert->libctx, md_name,
cert->propq)) == NULL)
return NULL;
if (md_is_fallback != NULL)
*md_is_fallback = 1;
} else {
/* A completely unknown algorithm */
ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
} else if ((md = EVP_MD_fetch(cert->libctx, OBJ_nid2sn(mdnid),
cert->propq)) == NULL
&& (md = (EVP_MD *)EVP_get_digestbynid(mdnid)) == NULL) {
ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
if (!X509_digest(cert, md, hash, &len)
|| (new = ASN1_OCTET_STRING_new()) == NULL)
goto err;
if (ASN1_OCTET_STRING_set(new, hash, len)) {
if (md_used != NULL)
*md_used = md;
else
EVP_MD_free(md);
return new;
}
ASN1_OCTET_STRING_free(new);
err:
EVP_MD_free(md);
return NULL;
}
int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
if (type == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (EVP_MD_is_a(type, SN_sha1)
&& (data->flags & EXFLAG_SET) != 0
&& (data->flags & EXFLAG_NO_FINGERPRINT) == 0) {
/* Asking for SHA1; always computed in CRL d2i. */
if (len != NULL)
*len = sizeof(data->sha1_hash);
memcpy(md, data->sha1_hash, sizeof(data->sha1_hash));
return 1;
}
return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_CRL), type, (char *)data,
md, len, data->libctx, data->propq);
}
int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_REQ), type, (char *)data,
md, len, data->libctx, data->propq);
}
int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
return ASN1_item_digest(ASN1_ITEM_rptr(X509_NAME), type, (char *)data,
md, len);
}
int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,
const EVP_MD *type, unsigned char *md,
unsigned int *len)
{
return ASN1_item_digest(ASN1_ITEM_rptr(PKCS7_ISSUER_AND_SERIAL), type,
(char *)data, md, len);
}
#ifndef OPENSSL_NO_STDIO
X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
{
return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8);
}
int i2d_PKCS8_fp(FILE *fp, const X509_SIG *p8)
{
return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8);
}
#endif
X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
{
return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8);
}
int i2d_PKCS8_bio(BIO *bp, const X509_SIG *p8)
{
return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8);
}
#ifndef OPENSSL_NO_STDIO
X509_PUBKEY *d2i_X509_PUBKEY_fp(FILE *fp, X509_PUBKEY **xpk)
{
return ASN1_d2i_fp_of(X509_PUBKEY, X509_PUBKEY_new, d2i_X509_PUBKEY,
fp, xpk);
}
int i2d_X509_PUBKEY_fp(FILE *fp, const X509_PUBKEY *xpk)
{
return ASN1_i2d_fp_of(X509_PUBKEY, i2d_X509_PUBKEY, fp, xpk);
}
#endif
X509_PUBKEY *d2i_X509_PUBKEY_bio(BIO *bp, X509_PUBKEY **xpk)
{
return ASN1_d2i_bio_of(X509_PUBKEY, X509_PUBKEY_new, d2i_X509_PUBKEY,
bp, xpk);
}
int i2d_X509_PUBKEY_bio(BIO *bp, const X509_PUBKEY *xpk)
{
return ASN1_i2d_bio_of(X509_PUBKEY, i2d_X509_PUBKEY, bp, xpk);
}
#ifndef OPENSSL_NO_STDIO
PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
PKCS8_PRIV_KEY_INFO **p8inf)
{
return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf);
}
int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, const PKCS8_PRIV_KEY_INFO *p8inf)
{
return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp,
p8inf);
}
int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, const EVP_PKEY *key)
{
PKCS8_PRIV_KEY_INFO *p8inf;
int ret;
p8inf = EVP_PKEY2PKCS8(key);
if (p8inf == NULL)
return 0;
ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
return ret;
}
int i2d_PrivateKey_fp(FILE *fp, const EVP_PKEY *pkey)
{
return ASN1_i2d_fp_of(EVP_PKEY, i2d_PrivateKey, fp, pkey);
}
EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
{
return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a);
}
EVP_PKEY *d2i_PrivateKey_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq)
{
BIO *b;
void *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
return NULL;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = d2i_PrivateKey_ex_bio(b, a, libctx, propq);
BIO_free(b);
return ret;
}
int i2d_PUBKEY_fp(FILE *fp, const EVP_PKEY *pkey)
{
return ASN1_i2d_fp_of(EVP_PKEY, i2d_PUBKEY, fp, pkey);
}
EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
{
return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a);
}
#endif
PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
PKCS8_PRIV_KEY_INFO **p8inf)
{
return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf);
}
int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, const PKCS8_PRIV_KEY_INFO *p8inf)
{
return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp,
p8inf);
}
int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, const EVP_PKEY *key)
{
PKCS8_PRIV_KEY_INFO *p8inf;
int ret;
p8inf = EVP_PKEY2PKCS8(key);
if (p8inf == NULL)
return 0;
ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
return ret;
}
int i2d_PrivateKey_bio(BIO *bp, const EVP_PKEY *pkey)
{
return ASN1_i2d_bio_of(EVP_PKEY, i2d_PrivateKey, bp, pkey);
}
EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
{
return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a);
}
EVP_PKEY *d2i_PrivateKey_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;
len = asn1_d2i_read_bio(bp, &b);
if (len < 0)
goto err;
p = (unsigned char *)b->data;
ret = d2i_AutoPrivateKey_ex(a, &p, len, libctx, propq);
err:
BUF_MEM_free(b);
return ret;
}
int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey)
{
return ASN1_i2d_bio_of(EVP_PKEY, i2d_PUBKEY, bp, pkey);
}
EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
{
return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a);
}
diff --git a/crypto/openssl/demos/cipher/aesccm.c b/crypto/openssl/demos/cipher/aesccm.c
index 5a2d4281506e..f4430e727b2f 100644
--- a/crypto/openssl/demos/cipher/aesccm.c
+++ b/crypto/openssl/demos/cipher/aesccm.c
@@ -1,238 +1,238 @@
/*
* Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* Simple AES CCM authenticated encryption with additional data (AEAD)
* demonstration program.
*/
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/core_names.h>
/* AES-CCM test data obtained from NIST public test vectors */
/* AES key */
static const unsigned char ccm_key[] = {
0xce, 0xb0, 0x09, 0xae, 0xa4, 0x45, 0x44, 0x51, 0xfe, 0xad, 0xf0, 0xe6,
0xb3, 0x6f, 0x45, 0x55, 0x5d, 0xd0, 0x47, 0x23, 0xba, 0xa4, 0x48, 0xe8
};
/* Unique nonce to be used for this message */
static const unsigned char ccm_nonce[] = {
0x76, 0x40, 0x43, 0xc4, 0x94, 0x60, 0xb7
};
/*
* Example of Additional Authenticated Data (AAD), i.e. unencrypted data
* which can be authenticated using the generated Tag value.
*/
static const unsigned char ccm_adata[] = {
0x6e, 0x80, 0xdd, 0x7f, 0x1b, 0xad, 0xf3, 0xa1, 0xc9, 0xab, 0x25, 0xc7,
0x5f, 0x10, 0xbd, 0xe7, 0x8c, 0x23, 0xfa, 0x0e, 0xb8, 0xf9, 0xaa, 0xa5,
0x3a, 0xde, 0xfb, 0xf4, 0xcb, 0xf7, 0x8f, 0xe4
};
/* Example plaintext to encrypt */
static const unsigned char ccm_pt[] = {
0xc8, 0xd2, 0x75, 0xf9, 0x19, 0xe1, 0x7d, 0x7f, 0xe6, 0x9c, 0x2a, 0x1f,
0x58, 0x93, 0x9d, 0xfe, 0x4d, 0x40, 0x37, 0x91, 0xb5, 0xdf, 0x13, 0x10
};
/* Expected ciphertext value */
static const unsigned char ccm_ct[] = {
0x8a, 0x0f, 0x3d, 0x82, 0x29, 0xe4, 0x8e, 0x74, 0x87, 0xfd, 0x95, 0xa2,
0x8a, 0xd3, 0x92, 0xc8, 0x0b, 0x36, 0x81, 0xd4, 0xfb, 0xc7, 0xbb, 0xfd
};
/* Expected AEAD Tag value */
static const unsigned char ccm_tag[] = {
0x2d, 0xd6, 0xef, 0x1c, 0x45, 0xd4, 0xcc, 0xb7, 0x23, 0xdc, 0x07, 0x44,
0x14, 0xdb, 0x50, 0x6d
};
/*
* A library context and property query can be used to select & filter
* algorithm implementations. If they are NULL then the default library
* context and properties are used.
*/
OSSL_LIB_CTX *libctx = NULL;
const char *propq = NULL;
int aes_ccm_encrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
size_t ccm_nonce_len = sizeof(ccm_nonce);
size_t ccm_tag_len = sizeof(ccm_tag);
unsigned char outbuf[1024];
unsigned char outtag[16];
OSSL_PARAM params[3] = {
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
};
printf("AES CCM Encrypt:\n");
printf("Plaintext:\n");
BIO_dump_fp(stdout, ccm_pt, sizeof(ccm_pt));
/* Create a context for the encrypt operation */
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "AES-192-CCM", propq)) == NULL)
goto err;
- /* Set nonce length if default 96 bits is not appropriate */
+ /* Default nonce length for AES-CCM is 7 bytes (56 bits). */
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
&ccm_nonce_len);
/* Set tag length */
params[1] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
NULL, ccm_tag_len);
/*
* Initialise encrypt operation with the cipher & mode,
* nonce length and tag length parameters.
*/
if (!EVP_EncryptInit_ex2(ctx, cipher, NULL, NULL, params))
goto err;
/* Initialise key and nonce */
if (!EVP_EncryptInit_ex(ctx, NULL, NULL, ccm_key, ccm_nonce))
goto err;
/* Set plaintext length: only needed if AAD is used */
if (!EVP_EncryptUpdate(ctx, NULL, &outlen, NULL, sizeof(ccm_pt)))
goto err;
/* Zero or one call to specify any AAD */
if (!EVP_EncryptUpdate(ctx, NULL, &outlen, ccm_adata, sizeof(ccm_adata)))
goto err;
/* Encrypt plaintext: can only be called once */
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, ccm_pt, sizeof(ccm_pt)))
goto err;
/* Output encrypted block */
printf("Ciphertext:\n");
BIO_dump_fp(stdout, outbuf, outlen);
/* Finalise: note get no output for CCM */
if (!EVP_EncryptFinal_ex(ctx, NULL, &tmplen))
goto err;
/* Get tag */
params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
outtag, ccm_tag_len);
params[1] = OSSL_PARAM_construct_end();
if (!EVP_CIPHER_CTX_get_params(ctx, params))
goto err;
/* Output tag */
printf("Tag:\n");
BIO_dump_fp(stdout, outtag, ccm_tag_len);
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
int aes_ccm_decrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, rv;
unsigned char outbuf[1024];
size_t ccm_nonce_len = sizeof(ccm_nonce);
OSSL_PARAM params[3] = {
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
};
printf("AES CCM Decrypt:\n");
printf("Ciphertext:\n");
BIO_dump_fp(stdout, ccm_ct, sizeof(ccm_ct));
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "AES-192-CCM", propq)) == NULL)
goto err;
/* Set nonce length if default 96 bits is not appropriate */
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
&ccm_nonce_len);
/* Set tag length */
params[1] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
(unsigned char *)ccm_tag,
sizeof(ccm_tag));
/*
* Initialise decrypt operation with the cipher & mode,
* nonce length and expected tag parameters.
*/
if (!EVP_DecryptInit_ex2(ctx, cipher, NULL, NULL, params))
goto err;
/* Specify key and IV */
if (!EVP_DecryptInit_ex(ctx, NULL, NULL, ccm_key, ccm_nonce))
goto err;
/* Set ciphertext length: only needed if we have AAD */
if (!EVP_DecryptUpdate(ctx, NULL, &outlen, NULL, sizeof(ccm_ct)))
goto err;
/* Zero or one call to specify any AAD */
if (!EVP_DecryptUpdate(ctx, NULL, &outlen, ccm_adata, sizeof(ccm_adata)))
goto err;
/* Decrypt plaintext, verify tag: can only be called once */
rv = EVP_DecryptUpdate(ctx, outbuf, &outlen, ccm_ct, sizeof(ccm_ct));
/* Output decrypted block: if tag verify failed we get nothing */
if (rv > 0) {
printf("Tag verify successful!\nPlaintext:\n");
BIO_dump_fp(stdout, outbuf, outlen);
} else {
printf("Tag verify failed!\nPlaintext not available\n");
goto err;
}
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
int main(int argc, char **argv)
{
if (!aes_ccm_encrypt())
return 1;
if (!aes_ccm_decrypt())
return 1;
return 0;
}
diff --git a/crypto/openssl/doc/man1/openssl-ca.pod.in b/crypto/openssl/doc/man1/openssl-ca.pod.in
index 1d497e848e79..1c07db3c8ef1 100644
--- a/crypto/openssl/doc/man1/openssl-ca.pod.in
+++ b/crypto/openssl/doc/man1/openssl-ca.pod.in
@@ -1,849 +1,849 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-ca - sample minimal CA application
=head1 SYNOPSIS
B<openssl> B<ca>
[B<-help>]
[B<-verbose>]
[B<-config> I<filename>]
[B<-name> I<section>]
[B<-section> I<section>]
[B<-gencrl>]
[B<-revoke> I<file>]
[B<-valid> I<file>]
[B<-status> I<serial>]
[B<-updatedb>]
[B<-crl_reason> I<reason>]
[B<-crl_hold> I<instruction>]
[B<-crl_compromise> I<time>]
[B<-crl_CA_compromise> I<time>]
[B<-crl_lastupdate> I<date>]
[B<-crl_nextupdate> I<date>]
[B<-crldays> I<days>]
[B<-crlhours> I<hours>]
[B<-crlsec> I<seconds>]
[B<-crlexts> I<section>]
[B<-startdate> I<date>]
[B<-enddate> I<date>]
[B<-days> I<arg>]
[B<-md> I<arg>]
[B<-policy> I<arg>]
[B<-keyfile> I<filename>|I<uri>]
[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
[B<-key> I<arg>]
[B<-passin> I<arg>]
[B<-cert> I<file>]
[B<-certform> B<DER>|B<PEM>|B<P12>]
[B<-selfsign>]
[B<-in> I<file>]
[B<-inform> B<DER>|<PEM>]
[B<-out> I<file>]
[B<-notext>]
[B<-dateopt>]
[B<-outdir> I<dir>]
[B<-infiles>]
[B<-spkac> I<file>]
[B<-ss_cert> I<file>]
[B<-preserveDN>]
[B<-noemailDN>]
[B<-batch>]
[B<-msie_hack>]
[B<-extensions> I<section>]
[B<-extfile> I<section>]
[B<-subj> I<arg>]
[B<-utf8>]
[B<-sigopt> I<nm>:I<v>]
[B<-vfyopt> I<nm>:I<v>]
[B<-create_serial>]
[B<-rand_serial>]
[B<-multivalue-rdn>]
{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
[I<certreq>...]
=head1 DESCRIPTION
This command emulates a CA application.
See the B<WARNINGS> especially when considering to use it productively.
It can be used to sign certificate requests (CSRs) in a variety of forms
and generate certificate revocation lists (CRLs).
It also maintains a text database of issued certificates and their status.
When signing certificates, a single request can be specified
with the B<-in> option, or multiple requests can be processed by
specifying a set of B<certreq> files after all options.
Note that there are also very lean ways of generating certificates:
the B<req> and B<x509> commands can be used for directly creating certificates.
See L<openssl-req(1)> and L<openssl-x509(1)> for details.
The descriptions of the B<ca> command options are 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> I<filename>
Specifies the configuration file to use.
Optional; for a description of the default value,
see L<openssl(1)/COMMAND SUMMARY>.
=item B<-name> I<section>, B<-section> I<section>
Specifies the configuration file section to use (overrides
B<default_ca> in the B<ca> section).
=item B<-in> I<filename>
An input filename containing a single certificate request (CSR) to be
signed by the CA.
=item B<-inform> B<DER>|B<PEM>
The format of the data in certificate request input files;
unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-ss_cert> I<filename>
A single self-signed certificate to be signed by the CA.
=item B<-spkac> I<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> I<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> I<directory>
The directory to output certificates to. The certificate will be
written to a filename consisting of the serial number in hex with
F<.pem> appended.
=item B<-cert> I<filename>
The CA certificate, which must match with B<-keyfile>.
=item B<-certform> B<DER>|B<PEM>|B<P12>
The format of the data in certificate input files; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-keyfile> I<filename>|I<uri>
The CA private key to sign certificate requests with.
This must match with B<-cert>.
=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The format of the private key input file; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-sigopt> I<nm>:I<v>
Pass options to the signature algorithm during sign operations.
Names and values of these options are algorithm-specific.
=item B<-vfyopt> I<nm>:I<v>
Pass options to the signature algorithm during verify operations.
Names and values of these options are algorithm-specific.
This often needs to be given while signing too, because the self-signature of
a certificate signing request (CSR) is verified against the included public key,
and that verification may need its own set of options.
=item B<-key> I<password>
=for openssl foreign manual ps(1)
The password used to encrypt the private key. Since on some
systems the command line arguments are visible (e.g., when using
L<ps(1)> on Unix),
this option should be used with caution.
Better use B<-passin>.
=item B<-passin> I<arg>
The key password source for key files and certificate PKCS#12 files.
For more information about the format of B<arg>
see L<openssl-passphrase-options(1)>.
=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<-notext>
Don't output the text form of a certificate to the output file.
=item B<-dateopt>
Specify the date output format. Values are: rfc_822 and iso_8601.
Defaults to rfc_822.
=item B<-startdate> I<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> I<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> I<arg>
The number of days to certify the certificate for.
=item B<-md> I<alg>
The message digest to use.
Any digest supported by the L<openssl-dgst(1)> 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> I<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 this command 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> I<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 X.509 extensions are specified then a V1 certificate is created,
else a V3 certificate is created.
See the L<x509v3_config(5)> manual page for details of the
extension section format.
=item B<-extfile> I<file>
An additional configuration file to read certificate extensions from
(using the default section unless the B<-extensions> option is also
used).
=item B<-subj> I<arg>
Supersedes subject name given in the request.
The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
Special characters may be escaped by C<\> (backslash), whitespace is retained.
Empty values are permitted, but the corresponding type will not be included
in the resulting certificate.
Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
between the AttributeValueAssertions (AVAs) that specify the members of the set.
Example:
C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
=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 has been deprecated and has no effect.
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_engine_item -}
{- $OpenSSL::safe::opt_provider_item -}
=back
=head1 CRL OPTIONS
=over 4
=item B<-gencrl>
This option generates a CRL based on information in the index file.
=item B<-crl_lastupdate> I<time>
Allows the value of the CRL's lastUpdate field to be explicitly set; if
this option is not present, the current time is used. Accepts times in
YYMMDDHHMMSSZ format (the same as an ASN1 UTCTime structure) or
YYYYMMDDHHMMSSZ format (the same as an ASN1 GeneralizedTime structure).
=item B<-crl_nextupdate> I<time>
Allows the value of the CRL's nextUpdate field to be explicitly set; if
this option is present, any values given for B<-crldays>, B<-crlhours>
and B<-crlsec> are ignored. Accepts times in the same formats as
B<-crl_lastupdate>.
=item B<-crldays> I<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> I<num>
The number of hours before the next CRL is due.
=item B<-crlsec> I<num>
The number of seconds before the next CRL is due.
=item B<-revoke> I<filename>
A filename containing a certificate to revoke.
=item B<-valid> I<filename>
A filename containing a certificate to add a Valid certificate entry.
=item B<-status> I<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> I<reason>
Revocation reason, where I<reason> is one of: B<unspecified>, B<keyCompromise>,
B<CACompromise>, B<affiliationChanged>, B<superseded>, B<cessationOfOperation>,
B<certificateHold> or B<removeFromCRL>. The matching of I<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> I<instruction>
This sets the CRL revocation reason code to B<certificateHold> and the hold
instruction to I<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> I<time>
This sets the revocation reason to B<keyCompromise> and the compromise time to
I<time>. I<time> should be in GeneralizedTime format that is I<YYYYMMDDHHMMSSZ>.
=item B<-crl_CA_compromise> I<time>
This is the same as B<crl_compromise> except the revocation reason is set to
B<CACompromise>.
=item B<-crlexts> I<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 this command
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 whitespace then the short name followed
by whitespace 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. (Note: Using a RANDFILE is
not necessary anymore, see the L</HISTORY> section.
=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>
A fallback to the B<-extensions> option.
=item B<crl_extensions>
A fallback to the B<-crlexts> option.
=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 L<openssl-spkac(1)>.
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 directory structure this command
assumes is already set up and the relevant files already exist. This
usually involves creating a CA certificate and private key with
L<openssl-req(1)>, 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 F<demoCA>,
F<demoCA/private> and F<demoCA/newcerts> would be created. The CA
certificate would be copied to F<demoCA/cacert.pem> and its private
key to F<demoCA/private/cakey.pem>. A file F<demoCA/serial> would be
created containing for example "01" and the empty index file
F<demoCA/index.txt>.
Sign a certificate request:
openssl ca -in req.pem -out newcert.pem
Sign an SM2 certificate request:
openssl ca -in sm2.csr -out sm2.crt -md sm3 \
-sigopt "distid:1234567812345678" \
-vfyopt "distid:1234567812345678"
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 this command:
[ 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
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
- default_md = md5 # md to use
+ default_md = sha256 # 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
=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
This command is quirky and at times downright unfriendly.
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.
This command really needs rewriting or the required functionality
exposed at either a command or interface level so that a more user-friendly
replacement could 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
This command was originally meant as an example of how to do things in a CA.
Its code does not have production quality.
It was not supposed to be used as a full blown CA itself,
nevertheless some people are using it for this purpose at least internally.
When doing so, specific care should be taken to
properly secure the private key(s) used for signing certificates.
It is advisable to keep them in a secure HW storage such as a smart card or HSM
and access them via a suitable engine or crypto provider.
This command command is effectively a single user command: no locking
is done on the various files and attempts to run more than one B<openssl 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>) and CRL last/next update time (specified by
any of B<-crl_lastupdate>, B<-crl_nextupdate>, B<-crldays>, B<-crlhours>
and B<-crlsec>) 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.
OpenSSL 1.1.1 introduced a new random generator (CSPRNG) with an improved
seeding mechanism. The new seeding mechanism makes it unnecessary to
define a RANDFILE for saving and restoring randomness. This option is
retained mainly for compatibility reasons.
The B<-section> option was added in OpenSSL 3.0.0.
The B<-multivalue-rdn> option has become obsolete in OpenSSL 3.0.0 and
has no effect.
The B<-engine> option was deprecated in OpenSSL 3.0.
=head1 SEE ALSO
L<openssl(1)>,
L<openssl-req(1)>,
L<openssl-spkac(1)>,
L<openssl-x509(1)>,
L<CA.pl(1)>,
L<config(5)>,
L<x509v3_config(5)>
=head1 COPYRIGHT
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-cmp.pod.in b/crypto/openssl/doc/man1/openssl-cmp.pod.in
index 9240916fce40..889a59cd497e 100644
--- a/crypto/openssl/doc/man1/openssl-cmp.pod.in
+++ b/crypto/openssl/doc/man1/openssl-cmp.pod.in
@@ -1,1307 +1,1312 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-cmp - Certificate Management Protocol (CMP, RFC 4210) application
=head1 SYNOPSIS
B<openssl> B<cmp>
[B<-help>]
[B<-config> I<filename>]
[B<-section> I<names>]
[B<-verbosity> I<level>]
Generic message options:
[B<-cmd> I<ir|cr|kur|p10cr|rr|genm>]
[B<-infotype> I<name>]
[B<-geninfo> I<OID:int:N>]
Certificate enrollment options:
[B<-newkey> I<filename>|I<uri>]
[B<-newkeypass> I<arg>]
[B<-subject> I<name>]
[B<-issuer> I<name>]
[B<-days> I<number>]
[B<-reqexts> I<name>]
[B<-sans> I<spec>]
[B<-san_nodefault>]
[B<-policies> I<name>]
[B<-policy_oids> I<names>]
[B<-policy_oids_critical>]
[B<-popo> I<number>]
[B<-csr> I<filename>]
[B<-out_trusted> I<filenames>|I<uris>]
[B<-implicit_confirm>]
[B<-disable_confirm>]
[B<-certout> I<filename>]
[B<-chainout> I<filename>]
Certificate enrollment and revocation options:
[B<-oldcert> I<filename>|I<uri>]
[B<-revreason> I<number>]
Message transfer options:
[B<-server> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>]
[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>]
[B<-no_proxy> I<addresses>]
[B<-recipient> I<name>]
[B<-path> I<remote_path>]
[B<-keep_alive> I<value>]
[B<-msg_timeout> I<seconds>]
[B<-total_timeout> I<seconds>]
Server authentication options:
[B<-trusted> I<filenames>|I<uris>]
[B<-untrusted> I<filenames>|I<uris>]
[B<-srvcert> I<filename>|I<uri>]
[B<-expect_sender> I<name>]
[B<-ignore_keyusage>]
[B<-unprotected_errors>]
[B<-extracertsout> I<filename>]
[B<-cacertsout> I<filename>]
Client authentication and protection options:
[B<-ref> I<value>]
[B<-secret> I<arg>]
[B<-cert> I<filename>|I<uri>]
[B<-own_trusted> I<filenames>|I<uris>]
[B<-key> I<filename>|I<uri>]
[B<-keypass> I<arg>]
[B<-digest> I<name>]
[B<-mac> I<name>]
[B<-extracerts> I<filenames>|I<uris>]
[B<-unprotected_requests>]
Credentials format options:
[B<-certform> I<PEM|DER>]
[B<-keyform> I<PEM|DER|P12|ENGINE>]
[B<-otherpass> I<arg>]
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
Random state options:
{- $OpenSSL::safe::opt_r_synopsis -}
TLS connection options:
[B<-tls_used>]
[B<-tls_cert> I<filename>|I<uri>]
[B<-tls_key> I<filename>|I<uri>]
[B<-tls_keypass> I<arg>]
[B<-tls_extra> I<filenames>|I<uris>]
[B<-tls_trusted> I<filenames>|I<uris>]
[B<-tls_host> I<name>]
Client-side debugging options:
[B<-batch>]
[B<-repeat> I<number>]
[B<-reqin> I<filenames>]
[B<-reqin_new_tid>]
[B<-reqout> I<filenames>]
[B<-rspin> I<filenames>]
[B<-rspout> I<filenames>]
[B<-use_mock_srv>]
Mock server options:
[B<-port> I<number>]
[B<-max_msgs> I<number>]
[B<-srv_ref> I<value>]
[B<-srv_secret> I<arg>]
[B<-srv_cert> I<filename>|I<uri>]
[B<-srv_key> I<filename>|I<uri>]
[B<-srv_keypass> I<arg>]
[B<-srv_trusted> I<filenames>|I<uris>]
[B<-srv_untrusted> I<filenames>|I<uris>]
[B<-rsp_cert> I<filename>|I<uri>]
[B<-rsp_extracerts> I<filenames>|I<uris>]
[B<-rsp_capubs> I<filenames>|I<uris>]
[B<-poll_count> I<number>]
[B<-check_after> I<number>]
[B<-grant_implicitconf>]
[B<-pkistatus> I<number>]
[B<-failure> I<number>]
[B<-failurebits> I<number>]
[B<-statusstring> I<arg>]
[B<-send_error>]
[B<-send_unprotected>]
[B<-send_unprot_err>]
[B<-accept_unprotected>]
[B<-accept_unprot_err>]
[B<-accept_raverified>]
Certificate verification options, for both CMP and TLS:
{- $OpenSSL::safe::opt_v_synopsis -}
=head1 DESCRIPTION
The B<cmp> command is a client implementation for the Certificate
Management Protocol (CMP) as defined in RFC4210.
It can be used to request certificates from a CA server,
update their certificates,
request certificates to be revoked, and perform other types of CMP requests.
=head1 OPTIONS
=over 4
=item B<-help>
Display a summary of all options
=item B<-config> I<filename>
Configuration file to use.
An empty string C<""> means none.
Default filename is from the environment variable C<OPENSSL_CONF>.
=item B<-section> I<names>
Section(s) to use within config file defining CMP options.
An empty string C<""> means no specific section.
Default is C<cmp>.
Multiple section names may be given, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Contents of sections named later may override contents of sections named before.
In any case, as usual, the C<[default]> section and finally the unnamed
section (as far as present) can provide per-option fallback values.
=item B<-verbosity> I<level>
Level of verbosity for logging, error output, etc.
0 = EMERG, 1 = ALERT, 2 = CRIT, 3 = ERR, 4 = WARN, 5 = NOTE,
6 = INFO, 7 = DEBUG, 8 = TRACE.
Defaults to 6 = INFO.
=back
=head2 Generic message options
=over 4
=item B<-cmd> I<ir|cr|kur|p10cr|rr|genm>
CMP command to execute.
Currently implemented commands are:
=over 8
=item ir E<nbsp> - Initialization Request
=item cr E<nbsp> - Certificate Request
=item p10cr - PKCS#10 Certification Request (for legacy support)
=item kur E<nbsp>E<nbsp>- Key Update Request
=item rr E<nbsp> - Revocation Request
=item genm - General Message
=back
B<ir> requests initialization of an end entity into a PKI hierarchy
by issuing a first certificate.
B<cr> requests issuing an additional certificate for an end entity already
initialized to the PKI hierarchy.
B<p10cr> requests issuing an additional certificate similarly to B<cr>
but using legacy PKCS#10 CSR format.
B<kur> requests a (key) update for an existing certificate.
B<rr> requests revocation of an existing certificate.
B<genm> requests information using a General Message, where optionally
included B<InfoTypeAndValue>s may be used to state which info is of interest.
Upon receipt of the General Response, information about all received
ITAV B<infoType>s is printed to stdout.
=item B<-infotype> I<name>
Set InfoType name to use for requesting specific info in B<genm>,
e.g., C<signKeyPairTypes>.
=item B<-geninfo> I<OID:int:N>
generalInfo integer values to place in request PKIHeader with given OID,
e.g., C<1.2.3.4:int:56789>.
=back
=head2 Certificate enrollment options
=over 4
=item B<-newkey> I<filename>|I<uri>
The source of the private or public key for the certificate being requested.
Defaults to the public key in the PKCS#10 CSR given with the B<-csr> option,
the public key of the reference certificate, or the current client key.
The public portion of the key is placed in the certification request.
Unless B<-cmd> I<p10cr>, B<-popo> I<-1>, or B<-popo> I<0> is given, the
private key will be needed as well to provide the proof of possession (POPO),
where the B<-key> option may provide a fallback.
=item B<-newkeypass> I<arg>
Pass phrase source for the key given with the B<-newkey> option.
If not given here, the password will be prompted for if needed.
For more information about the format of I<arg> see
L<openssl-passphrase-options(1)>.
=item B<-subject> I<name>
X509 Distinguished Name (DN) of subject to use in the requested certificate
template.
If the NULL-DN (C<"/">) is given then no subject is placed in the template.
Default is the subject DN of any PKCS#10 CSR given with the B<-csr> option.
For KUR, a further fallback is the subject DN
of the reference certificate (see B<-oldcert>) if provided.
This fallback is used for IR and CR only if no SANs are set.
If provided and neither B<-cert> nor B<-oldcert> is given,
the subject DN is used as fallback sender of outgoing CMP messages.
The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
Special characters may be escaped by C<\> (backslash); whitespace is retained.
Empty values are permitted, but the corresponding type will not be included.
Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
between the AttributeValueAssertions (AVAs) that specify the members of the set.
Example:
C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
=item B<-issuer> I<name>
X509 issuer Distinguished Name (DN) of the CA server
to place in the requested certificate template in IR/CR/KUR.
If the NULL-DN (C<"/">) is given then no issuer is placed in the template.
If provided and neither B<-recipient> nor B<-srvcert> is given,
the issuer DN is used as fallback recipient of outgoing CMP messages.
The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
For details see the description of the B<-subject> option.
=item B<-days> I<number>
Number of days the new certificate is requested to be valid for, counting from
the current time of the host.
Also triggers the explicit request that the
validity period starts from the current time (as seen by the host).
=item B<-reqexts> I<name>
Name of section in OpenSSL config file defining certificate request extensions.
If the B<-csr> option is present, these extensions augment the extensions
contained the given PKCS#10 CSR, overriding any extensions with same OIDs.
=item B<-sans> I<spec>
One or more IP addresses, DNS names, or URIs separated by commas or whitespace
(where in the latter case the whole argument must be enclosed in "...")
to add as Subject Alternative Name(s) (SAN) certificate request extension.
If the special element "critical" is given the SANs are flagged as critical.
Cannot be used if any Subject Alternative Name extension is set via B<-reqexts>.
=item B<-san_nodefault>
When Subject Alternative Names are not given via B<-sans>
nor defined via B<-reqexts>,
they are copied by default from the reference certificate (see B<-oldcert>).
This can be disabled by giving the B<-san_nodefault> option.
=item B<-policies> I<name>
Name of section in OpenSSL config file defining policies to be set
as certificate request extension.
This option cannot be used together with B<-policy_oids>.
=item B<-policy_oids> I<names>
One or more OID(s), separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...")
to add as certificate policies request extension.
This option cannot be used together with B<-policies>.
=item B<-policy_oids_critical>
Flag the policies given with B<-policy_oids> as critical.
=item B<-popo> I<number>
Proof-of-possession (POPO) method to use for IR/CR/KUR; values: C<-1>..<2> where
C<-1> = NONE, C<0> = RAVERIFIED, C<1> = SIGNATURE (default), C<2> = KEYENC.
Note that a signature-based POPO can only be produced if a private key
is provided via the B<-newkey> or B<-key> options.
=item B<-csr> I<filename>
PKCS#10 CSR in PEM or DER format containing a certificate request.
With B<-cmd> I<p10cr> it is used directly in a legacy P10CR message.
When used with B<-cmd> I<ir>, I<cr>, or I<kur>,
it is transformed into the respective regular CMP request.
In this case, a private key must be provided (with B<-newkey> or B<-key>)
for the proof of possession (unless B<-popo> I<-1> or B<-popo> I<0> is used)
and the respective public key is placed in the certification request
(rather than taking over the public key contained in the PKCS#10 CSR).
PKCS#10 CSR input may also be used with B<-cmd> I<rr>
to specify the certificate to be revoked
via the included subject name and public key.
=item B<-out_trusted> I<filenames>|I<uris>
Trusted certificate(s) to use for validating the newly enrolled certificate.
During this verification, any certificate status checking is disabled.
Multiple sources may be given, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Each source may contain multiple certificates.
The certificate verification options
B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
only affect the certificate verification enabled via this option.
=item B<-implicit_confirm>
Request implicit confirmation of newly enrolled certificates.
=item B<-disable_confirm>
Do not send certificate confirmation message for newly enrolled certificate
without requesting implicit confirmation
to cope with broken servers not supporting implicit confirmation correctly.
B<WARNING:> This leads to behavior violating RFC 4210.
=item B<-certout> I<filename>
The file where the newly enrolled certificate should be saved.
=item B<-chainout> I<filename>
The file where the chain of the newly enrolled certificate should be saved.
=back
=head2 Certificate enrollment and revocation options
=over 4
=item B<-oldcert> I<filename>|I<uri>
The certificate to be updated (i.e., renewed or re-keyed) in Key Update Request
(KUR) messages or to be revoked in Revocation Request (RR) messages.
For KUR the certificate to be updated defaults to B<-cert>,
and the resulting certificate is called I<reference certificate>.
For RR the certificate to be revoked can also be specified using B<-csr>.
The reference certificate, if any, is also used for
deriving default subject DN and Subject Alternative Names and the
default issuer entry in the requested certificate template of an IR/CR/KUR.
Its public key is used as a fallback in the template of certification requests.
Its subject is used as sender of outgoing messages if B<-cert> is not given.
Its issuer is used as default recipient in CMP message headers
if neither B<-recipient>, B<-srvcert>, nor B<-issuer> is given.
=item B<-revreason> I<number>
Set CRLReason to be included in revocation request (RR); values: C<0>..C<10>
or C<-1> for none (which is the default).
Reason numbers defined in RFC 5280 are:
CRLReason ::= ENUMERATED {
unspecified (0),
keyCompromise (1),
cACompromise (2),
affiliationChanged (3),
superseded (4),
cessationOfOperation (5),
certificateHold (6),
-- value 7 is not used
removeFromCRL (8),
privilegeWithdrawn (9),
aACompromise (10)
}
=back
=head2 Message transfer options
=over 4
=item B<-server> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>
-The DNS hostname or IP address and optionally port
+The I<host> domain name or IP address and optionally I<port>
of the CMP server to connect to using HTTP(S).
+IP address may be for v4 or v6, such as C<127.0.0.1> or C<[::1]> for localhost.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
+
This option excludes I<-port> and I<-use_mock_srv>.
It is ignored if I<-rspin> is given with enough filename arguments.
The scheme C<https> may be given only if the B<-tls_used> option is used.
In this case the default port is 443, else 80.
The optional userinfo and fragment components are ignored.
Any given query component is handled as part of the path component.
If a path is included it provides the default value for the B<-path> option.
=item B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>
The HTTP(S) proxy server to use for reaching the CMP server unless B<-no_proxy>
applies, see below.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
The proxy port defaults to 80 or 443 if the scheme is C<https>; apart from that
the optional C<http://> or C<https://> prefix is ignored (note that TLS may be
selected by B<-tls_used>), as well as any path, userinfo, and query, and fragment
components.
Defaults to the environment variable C<http_proxy> if set, else C<HTTP_PROXY>
in case no TLS is used, otherwise C<https_proxy> if set, else C<HTTPS_PROXY>.
This option is ignored if I<-server> is not given.
=item B<-no_proxy> I<addresses>
List of IP addresses and/or DNS names of servers
not to use an HTTP(S) proxy for, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Default is from the environment variable C<no_proxy> if set, else C<NO_PROXY>.
This option is ignored if I<-server> is not given.
=item B<-recipient> I<name>
Distinguished Name (DN) to use in the recipient field of CMP request message
headers, i.e., the CMP server (usually the addressed CA).
The recipient field in the header of a CMP message is mandatory.
If not given explicitly the recipient is determined in the following order:
the subject of the CMP server certificate given with the B<-srvcert> option,
the B<-issuer> option,
the issuer of the certificate given with the B<-oldcert> option,
the issuer of the CMP client certificate (B<-cert> option),
as far as any of those is present, else the NULL-DN as last resort.
The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
For details see the description of the B<-subject> option.
=item B<-path> I<remote_path>
HTTP path at the CMP server (aka CMP alias) to use for POST requests.
Defaults to any path given with B<-server>, else C<"/">.
=item B<-keep_alive> I<value>
If the given value is 0 then HTTP connections are not kept open
after receiving a response, which is the default behavior for HTTP 1.0.
If the value is 1 or 2 then persistent connections are requested.
If the value is 2 then persistent connections are required,
i.e., in case the server does not grant them an error occurs.
The default value is 1, which means preferring to keep the connection open.
=item B<-msg_timeout> I<seconds>
Number of seconds a CMP request-response message round trip
is allowed to take before a timeout error is returned.
A value <= 0 means no limitation (waiting indefinitely).
Default is to use the B<-total_timeout> setting.
=item B<-total_timeout> I<seconds>
Maximum total number of seconds a transaction may take,
including polling etc.
A value <= 0 means no limitation (waiting indefinitely).
Default is 0.
=back
=head2 Server authentication options
=over 4
=item B<-trusted> I<filenames>|I<uris>
The certificate(s), typically of root CAs, the client shall use as trust anchors
when validating signature-based protection of CMP response messages.
This option is ignored if the B<-srvcert> option is given as well.
It provides more flexibility than B<-srvcert> because the CMP protection
certificate of the server is not pinned but may be any certificate
from which a chain to one of the given trust anchors can be constructed.
If none of B<-trusted>, B<-srvcert>, and B<-secret> is given, message validation
errors will be thrown unless B<-unprotected_errors> permits an exception.
Multiple sources may be given, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Each source may contain multiple certificates.
The certificate verification options
B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
have no effect on the certificate verification enabled via this option.
=item B<-untrusted> I<filenames>|I<uris>
Non-trusted intermediate CA certificate(s).
Any extra certificates given with the B<-cert> option are appended to it.
All these certificates may be useful for cert path construction
for the own CMP signer certificate (to include in the extraCerts field of
request messages) and for the TLS client certificate (if TLS is enabled)
as well as for chain building
when validating server certificates (checking signature-based
CMP message protection) and when validating newly enrolled certificates.
Multiple filenames or URLs may be given, separated by commas and/or whitespace.
Each source may contain multiple certificates.
=item B<-srvcert> I<filename>|I<uri>
The specific CMP server certificate to expect and directly trust (even if it is
expired) when verifying signature-based protection of CMP response messages.
This pins the accepted server and results in ignoring the B<-trusted> option.
If set, the subject of the certificate is also used
as default value for the recipient of CMP requests
and as default value for the expected sender of CMP responses.
=item B<-expect_sender> I<name>
Distinguished Name (DN) expected in the sender field of incoming CMP messages.
Defaults to the subject DN of the pinned B<-srvcert>, if any.
This can be used to make sure that only a particular entity is accepted as
CMP message signer, and attackers are not able to use arbitrary certificates
of a trusted PKI hierarchy to fraudulently pose as a CMP server.
Note that this option gives slightly more freedom than setting the B<-srvcert>,
which pins the server to the holder of a particular certificate, while the
expected sender name will continue to match after updates of the server cert.
The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
For details see the description of the B<-subject> option.
=item B<-ignore_keyusage>
Ignore key usage restrictions in CMP signer certificates when validating
signature-based protection of incoming CMP messages.
By default, C<digitalSignature> must be allowed by CMP signer certificates.
=item B<-unprotected_errors>
Accept missing or invalid protection of negative responses from the server.
This applies to the following message types and contents:
=over 4
=item * error messages
=item * negative certificate responses (IP/CP/KUP)
=item * negative revocation responses (RP)
=item * negative PKIConf messages
=back
B<WARNING:> This setting leads to unspecified behavior and it is meant
exclusively to allow interoperability with server implementations violating
RFC 4210, e.g.:
=over 4
=item * section 5.1.3.1 allows exceptions from protecting only for special
cases:
"There MAY be cases in which the PKIProtection BIT STRING is deliberately not
used to protect a message [...] because other protection, external to PKIX, will
be applied instead."
=item * section 5.3.21 is clear on ErrMsgContent: "The CA MUST always sign it
with a signature key."
=item * appendix D.4 shows PKIConf message having protection
=back
=item B<-extracertsout> I<filename>
The file where to save all certificates contained in the extraCerts field
of the last received response message (except for pollRep and PKIConf).
=item B<-cacertsout> I<filename>
The file where to save any CA certificates contained in the caPubs field of
the last received certificate response (i.e., IP, CP, or KUP) message.
=back
=head2 Client authentication options
=over 4
=item B<-ref> I<value>
Reference number/string/value to use as fallback senderKID; this is required
if no sender name can be determined from the B<-cert> or <-subject> options and
is typically used when authenticating with pre-shared key (password-based MAC).
=item B<-secret> I<arg>
Provides the source of a secret value to use with MAC-based message protection.
This takes precedence over the B<-cert> and B<-key> options.
The secret is used for creating MAC-based protection of outgoing messages
and for validating incoming messages that have MAC-based protection.
The algorithm used by default is Password-Based Message Authentication Code (PBM)
as defined in RFC 4210 section 5.1.3.1.
For more information about the format of I<arg> see
L<openssl-passphrase-options(1)>.
=item B<-cert> I<filename>|I<uri>
The client's current CMP signer certificate.
Requires the corresponding key to be given with B<-key>.
The subject and the public key contained in this certificate
serve as fallback values in the certificate template of IR/CR/KUR messages.
The subject of this certificate will be used as sender of outgoing CMP messages,
while the subject of B<-oldcert> or B<-subjectName> may provide fallback values.
The issuer of this certificate is used as one of the recipient fallback values
and as fallback issuer entry in the certificate template of IR/CR/KUR messages.
When performing signature-based message protection,
this "protection certificate", also called "signer certificate",
will be included first in the extraCerts field of outgoing messages
and the signature is done with the corresponding key.
In Initialization Request (IR) messages this can be used for authenticating
using an external entity certificate as defined in appendix E.7 of RFC 4210.
For Key Update Request (KUR) messages this is also used as
the certificate to be updated if the B<-oldcert> option is not given.
If the file includes further certs, they are appended to the untrusted certs
because they typically constitute the chain of the client certificate, which
is included in the extraCerts field in signature-protected request messages.
=item B<-own_trusted> I<filenames>|I<uris>
If this list of certificates is provided then the chain built for
the client-side CMP signer certificate given with the B<-cert> option
is verified using the given certificates as trust anchors.
Multiple sources may be given, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Each source may contain multiple certificates.
The certificate verification options
B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
have no effect on the certificate verification enabled via this option.
=item B<-key> I<filename>|I<uri>
The corresponding private key file for the client's current certificate given in
the B<-cert> option.
This will be used for signature-based message protection unless the B<-secret>
option indicating MAC-based protection or B<-unprotected_requests> is given.
It is also used as a fallback for the B<-newkey> option with IR/CR/KUR messages.
=item B<-keypass> I<arg>
Pass phrase source for the private key given with the B<-key> option.
Also used for B<-cert> and B<-oldcert> in case it is an encrypted PKCS#12 file.
If not given here, the password will be prompted for if needed.
For more information about the format of I<arg> see
L<openssl-passphrase-options(1)>.
=item B<-digest> I<name>
Specifies name of supported digest to use in RFC 4210's MSG_SIG_ALG
and as the one-way function (OWF) in C<MSG_MAC_ALG>.
If applicable, this is used for message protection and
proof-of-possession (POPO) signatures.
To see the list of supported digests, use C<openssl list -digest-commands>.
Defaults to C<sha256>.
=item B<-mac> I<name>
Specifies the name of the MAC algorithm in C<MSG_MAC_ALG>.
To get the names of supported MAC algorithms use C<openssl list -mac-algorithms>
and possibly combine such a name with the name of a supported digest algorithm,
e.g., hmacWithSHA256.
Defaults to C<hmac-sha1> as per RFC 4210.
=item B<-extracerts> I<filenames>|I<uris>
Certificates to append in the extraCerts field when sending messages.
They can be used as the default CMP signer certificate chain to include.
Multiple sources may be given, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Each source may contain multiple certificates.
=item B<-unprotected_requests>
Send request messages without CMP-level protection.
=back
=head2 Credentials format options
=over 4
=item B<-certform> I<PEM|DER>
File format to use when saving a certificate to a file.
Default value is PEM.
=item B<-keyform> I<PEM|DER|P12|ENGINE>
The format of the key input; unspecified by default.
See L<openssl(1)/Format Options> for details.
=item B<-otherpass> I<arg>
Pass phrase source for certificate given with the B<-trusted>, B<-untrusted>,
B<-own_trusted>, B<-srvcert>, B<-out_trusted>, B<-extracerts>,
B<-srv_trusted>, B<-srv_untrusted>, B<-rsp_extracerts>, B<-rsp_capubs>,
B<-tls_extra>, and B<-tls_trusted> options.
If not given here, the password will be prompted for if needed.
For more information about the format of I<arg> see
L<openssl-passphrase-options(1)>.
{- $OpenSSL::safe::opt_engine_item -}
{- output_off() if $disabled{"deprecated-3.0"}; "" -}
As an alternative to using this combination:
-engine {engineid} -key {keyid} -keyform ENGINE
... it's also possible to just give the key ID in URI form to B<-key>,
like this:
-key org.openssl.engine:{engineid}:{keyid}
This applies to all options specifying keys: B<-key>, B<-newkey>, and
B<-tls_key>.
{- output_on() if $disabled{"deprecated-3.0"}; "" -}
=back
=head2 Provider options
=over 4
{- $OpenSSL::safe::opt_provider_item -}
=back
=head2 Random state options
=over 4
{- $OpenSSL::safe::opt_r_item -}
=back
=head2 TLS connection options
=over 4
=item B<-tls_used>
Enable using TLS (even when other TLS-related options are not set)
for message exchange with CMP server via HTTP.
This option is not supported with the I<-port> option.
It is ignored if the I<-server> option is not given or I<-use_mock_srv> is given
or I<-rspin> is given with enough filename arguments.
The following TLS-related options are ignored
if B<-tls_used> is not given or does not take effect.
=item B<-tls_cert> I<filename>|I<uri>
Client's TLS certificate.
If the source includes further certs they are used (along with B<-untrusted>
certs) for constructing the client cert chain provided to the TLS server.
=item B<-tls_key> I<filename>|I<uri>
Private key for the client's TLS certificate.
=item B<-tls_keypass> I<arg>
Pass phrase source for client's private TLS key B<-tls_key>.
Also used for B<-tls_cert> in case it is an encrypted PKCS#12 file.
If not given here, the password will be prompted for if needed.
For more information about the format of I<arg> see
L<openssl-passphrase-options(1)>.
=item B<-tls_extra> I<filenames>|I<uris>
Extra certificates to provide to TLS server during TLS handshake
=item B<-tls_trusted> I<filenames>|I<uris>
Trusted certificate(s) to use for validating the TLS server certificate.
This implies hostname validation.
Multiple sources may be given, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Each source may contain multiple certificates.
The certificate verification options
B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
have no effect on the certificate verification enabled via this option.
=item B<-tls_host> I<name>
Address to be checked during hostname validation.
This may be a DNS name or an IP address.
If not given it defaults to the B<-server> address.
=back
=head2 Client-side debugging options
=over 4
=item B<-batch>
Do not interactively prompt for input, for instance when a password is needed.
This can be useful for batch processing and testing.
=item B<-repeat> I<number>
Invoke the command the given positive number of times with the same parameters.
Default is one invocation.
=item B<-reqin> I<filenames>
Take the sequence of CMP requests to send to the server from the given file(s)
rather than from the sequence of requests produced internally.
This option is ignored if the B<-rspin> option is given
because in the latter case no requests are actually sent.
Multiple filenames may be given, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
The files are read as far as needed to complete the transaction
and filenames have been provided. If more requests are needed,
the remaining ones are taken from the items at the respective position
in the sequence of requests produced internally.
The client needs to update the recipNonce field in the given requests (except
for the first one) in order to satisfy the checks to be performed by the server.
This causes re-protection (if protecting requests is required).
=item B<-reqin_new_tid>
Use a fresh transactionID for CMP request messages read using B<-reqin>,
which causes their reprotection (if protecting requests is required).
This may be needed in case the sequence of requests is reused
and the CMP server complains that the transaction ID has already been used.
=item B<-reqout> I<filenames>
Save the sequence of CMP requests created by the client to the given file(s).
These requests are not sent to the server if the B<-reqin> option is used, too.
Multiple filenames may be given, separated by commas and/or whitespace.
Files are written as far as needed to save the transaction
and filenames have been provided.
If the transaction contains more requests, the remaining ones are not saved.
=item B<-rspin> I<filenames>
Process the sequence of CMP responses provided in the given file(s),
not contacting any given server,
as long as enough filenames are provided to complete the transaction.
Multiple filenames may be given, separated by commas and/or whitespace.
Any server specified via the I<-server> or I<-use_mock_srv> options is contacted
only if more responses are needed to complete the transaction.
In this case the transaction will fail
unless the server has been prepared to continue the already started transaction.
=item B<-rspout> I<filenames>
Save the sequence of actually used CMP responses to the given file(s).
These have been received from the server unless B<-rspin> takes effect.
Multiple filenames may be given, separated by commas and/or whitespace.
Files are written as far as needed to save the responses
contained in the transaction and filenames have been provided.
If the transaction contains more responses, the remaining ones are not saved.
=item B<-use_mock_srv>
Test the client using the internal CMP server mock-up at API level,
bypassing socket-based transfer via HTTP.
This excludes the B<-server> and B<-port> options.
=back
=head2 Mock server options
=over 4
=item B<-port> I<number>
-Act as HTTP-based CMP server mock-up listening on the given port.
-This excludes the B<-server> and B<-use_mock_srv> options.
+Act as HTTP-based CMP server mock-up listening on the given local port.
+The client may address the server via, e.g., C<127.0.0.1> or C<[::1]>.
+This option excludes the B<-server> and B<-use_mock_srv> options.
The B<-rspin>, B<-rspout>, B<-reqin>, and B<-reqout> options
so far are not supported in this mode.
=item B<-max_msgs> I<number>
Maximum number of CMP (request) messages the CMP HTTP server mock-up
should handle, which must be nonnegative.
The default value is 0, which means that no limit is imposed.
In any case the server terminates on internal errors, but not when it
detects a CMP-level error that it can successfully answer with an error message.
=item B<-srv_ref> I<value>
Reference value to use as senderKID of server in case no B<-srv_cert> is given.
=item B<-srv_secret> I<arg>
Password source for server authentication with a pre-shared key (secret).
=item B<-srv_cert> I<filename>|I<uri>
Certificate of the server.
=item B<-srv_key> I<filename>|I<uri>
Private key used by the server for signing messages.
=item B<-srv_keypass> I<arg>
Server private key (and cert) file pass phrase source.
=item B<-srv_trusted> I<filenames>|I<uris>
Trusted certificates for client authentication.
The certificate verification options
B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
have no effect on the certificate verification enabled via this option.
=item B<-srv_untrusted> I<filenames>|I<uris>
Intermediate CA certs that may be useful when validating client certificates.
=item B<-rsp_cert> I<filename>|I<uri>
Certificate to be returned as mock enrollment result.
=item B<-rsp_extracerts> I<filenames>|I<uris>
Extra certificates to be included in mock certification responses.
=item B<-rsp_capubs> I<filenames>|I<uris>
CA certificates to be included in mock Initialization Response (IP) message.
=item B<-poll_count> I<number>
Number of times the client must poll before receiving a certificate.
=item B<-check_after> I<number>
The checkAfter value (number of seconds to wait) to include in poll response.
=item B<-grant_implicitconf>
Grant implicit confirmation of newly enrolled certificate.
=item B<-pkistatus> I<number>
PKIStatus to be included in server response.
Valid range is 0 (accepted) .. 6 (keyUpdateWarning).
=item B<-failure> I<number>
A single failure info bit number to be included in server response.
Valid range is 0 (badAlg) .. 26 (duplicateCertReq).
=item B<-failurebits> I<number>
Number representing failure bits to be included in server response.
Valid range is 0 .. 2^27 - 1.
=item B<-statusstring> I<arg>
Text to be included as status string in server response.
=item B<-send_error>
Force server to reply with error message.
=item B<-send_unprotected>
Send response messages without CMP-level protection.
=item B<-send_unprot_err>
In case of negative responses, server shall send unprotected error messages,
certificate responses (IP/CP/KUP), and revocation responses (RP).
WARNING: This setting leads to behavior violating RFC 4210.
=item B<-accept_unprotected>
Accept missing or invalid protection of requests.
=item B<-accept_unprot_err>
Accept unprotected error messages from client.
So far this has no effect because the server does not accept any error messages.
=item B<-accept_raverified>
Accept RAVERIFED as proof of possession (POPO).
=back
=head2 Certificate verification options, for both CMP and TLS
=over 4
{- $OpenSSL::safe::opt_v_item -}
The certificate verification options
B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
only affect the certificate verification enabled via the B<-out_trusted> option.
=back
=head1 NOTES
When a client obtains from a CMP server CA certificates that it is going to
trust, for instance via the C<caPubs> field of a certificate response,
authentication of the CMP server is particularly critical.
So special care must be taken setting up server authentication
using B<-trusted> and related options for certificate-based authentication
or B<-secret> for MAC-based protection.
When setting up CMP configurations and experimenting with enrollment options
typically various errors occur until the configuration is correct and complete.
When the CMP server reports an error the client will by default
check the protection of the CMP response message.
Yet some CMP services tend not to protect negative responses.
In this case the client will reject them, and thus their contents are not shown
although they usually contain hints that would be helpful for diagnostics.
For assisting in such cases the CMP client offers a workaround via the
B<-unprotected_errors> option, which allows accepting such negative messages.
=head1 EXAMPLES
=head2 Simple examples using the default OpenSSL configuration file
This CMP client implementation comes with demonstrative CMP sections
in the example configuration file F<openssl/apps/openssl.cnf>,
which can be used to interact conveniently with the Insta Demo CA.
In order to enroll an initial certificate from that CA it is sufficient
to issue the following shell commands.
export OPENSSL_CONF=/path/to/openssl/apps/openssl.cnf
=begin comment
wget 'http://pki.certificate.fi:8081/install-ca-cert.html/ca-certificate.crt\
?ca-id=632&download-certificate=1' -O insta.ca.crt
=end comment
openssl genrsa -out insta.priv.pem
openssl cmp -section insta
This should produce the file F<insta.cert.pem> containing a new certificate
for the private key held in F<insta.priv.pem>.
It can be viewed using, e.g.,
openssl x509 -noout -text -in insta.cert.pem
In case the network setup requires using an HTTP proxy it may be given as usual
via the environment variable B<http_proxy> or via the B<-proxy> option in the
configuration file or the CMP command-line argument B<-proxy>, for example
-proxy http://192.168.1.1:8080
In the Insta Demo CA scenario both clients and the server may use the pre-shared
secret I<insta> and the reference value I<3078> to authenticate to each other.
Alternatively, CMP messages may be protected in signature-based manner,
where the trust anchor in this case is F<insta.ca.crt>
and the client may use any certificate already obtained from that CA,
as specified in the B<[signature]> section of the example configuration.
This can be used in combination with the B<[insta]> section simply by
openssl cmp -section insta,signature
By default the CMP IR message type is used, yet CR works equally here.
This may be specified directly at the command line:
openssl cmp -section insta -cmd cr
or by referencing in addition the B<[cr]> section of the example configuration:
openssl cmp -section insta,cr
In order to update the enrolled certificate one may call
openssl cmp -section insta,kur
using MAC-based protection with PBM or
openssl cmp -section insta,kur,signature
using signature-based protection.
In a similar way any previously enrolled certificate may be revoked by
openssl cmp -section insta,rr -trusted insta.ca.crt
or
openssl cmp -section insta,rr,signature
Many more options can be given in the configuration file
and/or on the command line.
For instance, the B<-reqexts> CLI option may refer to a section in the
configuration file defining X.509 extensions to use in certificate requests,
such as C<v3_req> in F<openssl/apps/openssl.cnf>:
openssl cmp -section insta,cr -reqexts v3_req
=head2 Certificate enrollment
The following examples do not make use of a configuration file at first.
They assume that a CMP server can be contacted on the local TCP port 80
and accepts requests under the alias I</pkix/>.
For enrolling its very first certificate the client generates a client key
and sends an initial request message to the local CMP server
using a pre-shared secret key for mutual authentication.
In this example the client does not have the CA certificate yet,
so we specify the name of the CA with the B<-recipient> option
and save any CA certificates that we may receive in the C<capubs.pem> file.
In below command line usage examples the C<\> at line ends is used just
for formatting; each of the command invocations should be on a single line.
openssl genrsa -out cl_key.pem
openssl cmp -cmd ir -server 127.0.0.1:80/pkix/ -recipient "/CN=CMPserver" \
-ref 1234 -secret pass:1234-5678 \
-newkey cl_key.pem -subject "/CN=MyName" \
-cacertsout capubs.pem -certout cl_cert.pem
=head2 Certificate update
Then, when the client certificate and its related key pair needs to be updated,
the client can send a key update request taking the certs in C<capubs.pem>
as trusted for authenticating the server and using the previous cert and key
for its own authentication.
Then it can start using the new cert and key.
openssl genrsa -out cl_key_new.pem
openssl cmp -cmd kur -server 127.0.0.1:80/pkix/ \
-trusted capubs.pem \
-cert cl_cert.pem -key cl_key.pem \
-newkey cl_key_new.pem -certout cl_cert.pem
cp cl_key_new.pem cl_key.pem
This command sequence can be repeated as often as needed.
=head2 Requesting information from CMP server
Requesting "all relevant information" with an empty General Message.
This prints information about all received ITAV B<infoType>s to stdout.
openssl cmp -cmd genm -server 127.0.0.1/pkix/ -recipient "/CN=CMPserver" \
-ref 1234 -secret pass:1234-5678
=head2 Using a custom configuration file
For CMP client invocations, in particular for certificate enrollment,
usually many parameters need to be set, which is tedious and error-prone to do
on the command line.
Therefore, the client offers the possibility to read
options from sections of the OpenSSL config file, usually called F<openssl.cnf>.
The values found there can still be extended and even overridden by any
subsequently loaded sections and on the command line.
After including in the configuration file the following sections:
[cmp]
server = 127.0.0.1
path = pkix/
trusted = capubs.pem
cert = cl_cert.pem
key = cl_key.pem
newkey = cl_key.pem
certout = cl_cert.pem
[init]
recipient = "/CN=CMPserver"
trusted =
cert =
key =
ref = 1234
secret = pass:1234-5678-1234-567
subject = "/CN=MyName"
cacertsout = capubs.pem
the above enrollment transactions reduce to
openssl cmp -section cmp,init
openssl cmp -cmd kur -newkey cl_key_new.pem
and the above transaction using a general message reduces to
openssl cmp -section cmp,init -cmd genm
=head1 SEE ALSO
L<openssl-genrsa(1)>, L<openssl-ecparam(1)>, L<openssl-list(1)>,
L<openssl-req(1)>, L<openssl-x509(1)>, L<x509v3_config(5)>
=head1 HISTORY
The B<cmp> application was added in OpenSSL 3.0.
The B<-engine option> was deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-cms.pod.in b/crypto/openssl/doc/man1/openssl-cms.pod.in
index 65a61ee97f1d..f4d12312b7cb 100644
--- a/crypto/openssl/doc/man1/openssl-cms.pod.in
+++ b/crypto/openssl/doc/man1/openssl-cms.pod.in
@@ -1,912 +1,917 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-cms - CMS command
=head1 SYNOPSIS
B<openssl> B<cms>
[B<-help>]
General options:
[B<-in> I<filename>]
[B<-out> I<filename>]
{- $OpenSSL::safe::opt_config_synopsis -}
Operation options:
[B<-encrypt>]
[B<-decrypt>]
[B<-sign>]
[B<-verify>]
[B<-resign>]
[B<-sign_receipt>]
[B<-verify_receipt> I<receipt>]
[B<-digest_create>]
[B<-digest_verify>]
[B<-compress>]
[B<-uncompress>]
[B<-EncryptedData_encrypt>]
[B<-EncryptedData_decrypt>]
[B<-data_create>]
[B<-data_out>]
[B<-cmsout>]
File format options:
[B<-inform> B<DER>|B<PEM>|B<SMIME>]
[B<-outform> B<DER>|B<PEM>|B<SMIME>]
[B<-rctform> B<DER>|B<PEM>|B<SMIME>]
[B<-stream>]
[B<-indef>]
[B<-noindef>]
[B<-binary>]
[B<-crlfeol>]
[B<-asciicrlf>]
Keys and password options:
[B<-pwri_password> I<password>]
[B<-secretkey> I<key>]
[B<-secretkeyid> I<id>]
[B<-inkey> I<filename>|I<uri>]
[B<-passin> I<arg>]
[B<-keyopt> I<name>:I<parameter>]
[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
{- $OpenSSL::safe::opt_r_synopsis -}
Encryption options:
[B<-originator> I<file>]
[B<-recip> I<file>]
[I<recipient-cert> ...]
[B<-I<cipher>>]
[B<-wrap> I<cipher>]
[B<-aes128-wrap>]
[B<-aes192-wrap>]
[B<-aes256-wrap>]
[B<-des3-wrap>]
[B<-debug_decrypt>]
Signing options:
[B<-md> I<digest>]
[B<-signer> I<file>]
[B<-certfile> I<file>]
[B<-cades>]
[B<-nodetach>]
[B<-nocerts>]
[B<-noattr>]
[B<-nosmimecap>]
[B<-receipt_request_all>]
[B<-receipt_request_first>]
[B<-receipt_request_from> I<emailaddress>]
[B<-receipt_request_to> I<emailaddress>]
Verification options:
[B<-signer> I<file>]
[B<-content> I<filename>]
[B<-no_content_verify>]
[B<-no_attr_verify>]
[B<-nosigs>]
[B<-noverify>]
[B<-nointern>]
[B<-cades>]
[B<-verify_retcode>]
{- $OpenSSL::safe::opt_trust_synopsis -}
Output options:
[B<-keyid>]
[B<-econtent_type> I<type>]
[B<-text>]
[B<-certsout> I<file>]
[B<-to> I<addr>]
[B<-from> I<addr>]
[B<-subject> I<subj>]
Printing options:
[B<-noout>]
[B<-print>]
[B<-nameopt> I<option>]
[B<-receipt_request_print>]
Validation options:
{- $OpenSSL::safe::opt_v_synopsis -}
=head1 DESCRIPTION
This command handles data in CMS format such as S/MIME v3.1 email messages.
It can encrypt, decrypt, sign, verify, compress, uncompress, and print messages.
=head1 OPTIONS
There are a number of operation options that set the type of operation to be
performed: encrypt, decrypt, sign, verify, resign, sign_receipt, verify_receipt,
digest_create, digest_verify, compress, uncompress,
EncryptedData_encrypt, EncryptedData_decrypt, data_create, data_out, or cmsout.
The relevance of the other options depends on the operation type
and their meaning may vary according to it.
=over 4
=item B<-help>
Print out a usage message.
=back
=head2 General options
=over 4
=item B<-in> I<filename>
The input message to be encrypted or signed or the message to be decrypted
or verified.
=item B<-out> I<filename>
The message text that has been decrypted or verified or the output MIME
format message that has been signed or verified.
{- $OpenSSL::safe::opt_config_item -}
=back
=head2 Operation options
=over 4
=item B<-encrypt>
Encrypt data for the given recipient certificates. Input file is the message
to be encrypted. The output file is the encrypted data in MIME format. The
actual CMS type is B<EnvelopedData>.
Note that no revocation check is done for the recipient cert, so if that
key has been compromised, others may be able to decrypt the text.
=item B<-decrypt>
Decrypt data using the supplied certificate and private key. Expects
encrypted datain MIME format for the input file. The decrypted data
is written to the output file.
=item B<-sign>
Sign data using the supplied certificate and private key. Input file is
the message to be signed. The signed data in MIME format is written
to the output file.
=item B<-verify>
Verify signed data. Expects a signed data on input and outputs
the signed data. Both clear text and opaque signing is supported.
+By default, validation of signer certificates and their chain
+is done w.r.t. the S/MIME signing (C<smimesign>) purpose.
+For details see L<openssl-verification-options(1)/Certificate Extensions>.
+
=item B<-resign>
Resign a message: take an existing message and one or more new signers.
=item B<-sign_receipt>
Generate and output a signed receipt for the supplied message. The input
message B<must> contain a signed receipt request. Functionality is otherwise
similar to the B<-sign> operation.
=item B<-verify_receipt> I<receipt>
Verify a signed receipt in filename B<receipt>. The input message B<must>
contain the original receipt request. Functionality is otherwise similar
to the B<-verify> operation.
=item B<-digest_create>
Create a CMS B<DigestedData> type.
=item B<-digest_verify>
Verify a CMS B<DigestedData> type and output the content.
=item B<-compress>
Create a CMS B<CompressedData> type. OpenSSL must be compiled with B<zlib>
support for this option to work, otherwise it will output an error.
=item B<-uncompress>
Uncompress a CMS B<CompressedData> type and output the content. OpenSSL must be
compiled with B<zlib> support for this option to work, otherwise it will
output an error.
=item B<-EncryptedData_encrypt>
Encrypt content using supplied symmetric key and algorithm using a CMS
B<EncryptedData> type and output the content.
=item B<-EncryptedData_decrypt>
Decrypt content using supplied symmetric key and algorithm using a CMS
B<EncryptedData> type and output the content.
=item B<-data_create>
Create a CMS B<Data> type.
=item B<-data_out>
B<Data> type and output the content.
=item B<-cmsout>
Takes an input message and writes out a PEM encoded CMS structure.
=back
=head2 File format options
=over 4
=item B<-inform> B<DER>|B<PEM>|B<SMIME>
The input format of the CMS structure (if one is being read);
the default is B<SMIME>.
See L<openssl-format-options(1)> for details.
=item B<-outform> B<DER>|B<PEM>|B<SMIME>
The output format of the CMS structure (if one is being written);
the default is B<SMIME>.
See L<openssl-format-options(1)> for details.
=item B<-rctform> B<DER>|B<PEM>|B<SMIME>
The signed receipt format for use with the B<-receipt_verify>; the default
is B<SMIME>.
See L<openssl-format-options(1)> for details.
=item B<-stream>, B<-indef>
The B<-stream> and B<-indef> options are equivalent and enable streaming I/O
for encoding operations. This permits single pass processing of data without
the need to hold the entire contents in memory, potentially supporting very
large files. Streaming is automatically set for S/MIME signing with detached
data if the output format is B<SMIME> it is currently off by default for all
other operations.
=item B<-noindef>
Disable streaming I/O where it would produce and indefinite length constructed
encoding. This option currently has no effect. In future streaming will be
enabled by default on all relevant operations and this option will disable it.
=item B<-binary>
Normally the input message is converted to "canonical" format which is
effectively using CR and LF as end of line: as required by the S/MIME
specification. When this option is present no translation occurs. This
is useful when handling binary data which may not be in MIME format.
=item B<-crlfeol>
Normally the output file uses a single B<LF> as end of line. When this
option is present B<CRLF> is used instead.
=item B<-asciicrlf>
When signing use ASCII CRLF format canonicalisation. This strips trailing
whitespace from all lines, deletes trailing blank lines at EOF and sets
the encapsulated content type. This option is normally used with detached
content and an output signature format of DER. This option is not normally
needed when verifying as it is enabled automatically if the encapsulated
content format is detected.
=back
=head2 Keys and password options
=over 4
=item B<-pwri_password> I<password>
Specify password for recipient.
=item B<-secretkey> I<key>
Specify symmetric key to use. The key must be supplied in hex format and be
consistent with the algorithm used. Supported by the B<-EncryptedData_encrypt>
B<-EncryptedData_decrypt>, B<-encrypt> and B<-decrypt> options. When used
with B<-encrypt> or B<-decrypt> the supplied key is used to wrap or unwrap the
content encryption key using an AES key in the B<KEKRecipientInfo> type.
=item B<-secretkeyid> I<id>
The key identifier for the supplied symmetric key for B<KEKRecipientInfo> type.
This option B<must> be present if the B<-secretkey> option is used with
B<-encrypt>. With B<-decrypt> operations the I<id> is used to locate the
relevant key if it is not supplied then an attempt is used to decrypt any
B<KEKRecipientInfo> structures.
=item B<-inkey> I<filename>|I<uri>
The private key to use when signing or decrypting. This must match the
corresponding certificate. If this option is not specified then the
private key must be included in the certificate file specified with
the B<-recip> or B<-signer> file. When signing this option can be used
multiple times to specify successive keys.
=item B<-passin> I<arg>
The private key password source. For more information about the format of B<arg>
see L<openssl-passphrase-options(1)>.
=item B<-keyopt> I<name>:I<parameter>
For signing and encryption this option can be used multiple times to
set customised parameters for the preceding key or certificate. It can
currently be used to set RSA-PSS for signing, RSA-OAEP for encryption
or to modify default parameters for ECDH.
=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The format of the private key file; unspecified by default.
See L<openssl-format-options(1)> for details.
{- $OpenSSL::safe::opt_engine_item -}
{- $OpenSSL::safe::opt_provider_item -}
{- $OpenSSL::safe::opt_r_item -}
=back
=head2 Encryption and decryption options
=over 4
=item B<-originator> I<file>
A certificate of the originator of the encrypted message. Necessary for
-decryption when Key Agreement is in use for a shared key.
+decryption when Key Agreement is in use for a shared key. Currently, not
+allowed for encryption.
=item B<-recip> I<file>
When decrypting a message this specifies the certificate of the recipient.
The certificate must match one of the recipients of the message.
When encrypting a message this option may be used multiple times to specify
each recipient. This form B<must> be used if customised parameters are
required (for example to specify RSA-OAEP).
Only certificates carrying RSA, Diffie-Hellman or EC keys are supported by this
option.
=item I<recipient-cert> ...
This is an alternative to using the B<-recip> option when encrypting a message.
One or more certificate filenames may be given.
=item B<-I<cipher>>
The encryption algorithm to use. For example triple DES (168 bits) - B<-des3>
or 256 bit AES - B<-aes256>. Any standard algorithm name (as used by the
EVP_get_cipherbyname() function) can also be used preceded by a dash, for
example B<-aes-128-cbc>. See L<openssl-enc(1)> for a list of ciphers
supported by your version of OpenSSL.
Currently the AES variants with GCM mode are the only supported AEAD
algorithms.
If not specified triple DES is used. Only used with B<-encrypt> and
B<-EncryptedData_create> commands.
=item B<-wrap> I<cipher>
Cipher algorithm to use for key wrap when encrypting the message using Key
Agreement for key transport. The algorithm specified should be suitable for key
wrap.
=item B<-aes128-wrap>, B<-aes192-wrap>, B<-aes256-wrap>, B<-des3-wrap>
Use AES128, AES192, AES256, or 3DES-EDE, respectively, to wrap key.
Depending on the OpenSSL build options used, B<-des3-wrap> may not be supported.
=item B<-debug_decrypt>
This option sets the B<CMS_DEBUG_DECRYPT> flag. This option should be used
with caution: see the notes section below.
=back
=head2 Signing options
=over 4
=item B<-md> I<digest>
Digest algorithm to use when signing or resigning. If not present then the
default digest algorithm for the signing key will be used (usually SHA1).
=item B<-signer> I<file>
A signing certificate. When signing or resigning a message, this option can be
used multiple times if more than one signer is required.
=item B<-certfile> I<file>
Allows additional certificates to be specified. When signing these will
be included with the message. When verifying these will be searched for
the signers certificates.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-cades>
When used with B<-sign>,
add an ESS signingCertificate or ESS signingCertificateV2 signed-attribute
to the SignerInfo, in order to make the signature comply with the requirements
for a CAdES Basic Electronic Signature (CAdES-BES).
=item B<-nodetach>
When signing a message use opaque signing: this form is more resistant
to translation by mail relays but it cannot be read by mail agents that
do not support S/MIME. Without this option cleartext signing with
the MIME type multipart/signed is used.
=item B<-nocerts>
When signing a message the signer's certificate is normally included
with this option it is excluded. This will reduce the size of the
signed message but the verifier must have a copy of the signers certificate
available locally (passed using the B<-certfile> option for example).
=item B<-noattr>
Normally when a message is signed a set of attributes are included which
include the signing time and supported symmetric algorithms. With this
option they are not included.
=item B<-nosmimecap>
Exclude the list of supported algorithms from signed attributes, other options
such as signing time and content type are still included.
=item B<-receipt_request_all>, B<-receipt_request_first>
For B<-sign> option include a signed receipt request. Indicate requests should
be provided by all recipient or first tier recipients (those mailed directly
and not from a mailing list). Ignored it B<-receipt_request_from> is included.
=item B<-receipt_request_from> I<emailaddress>
For B<-sign> option include a signed receipt request. Add an explicit email
address where receipts should be supplied.
=item B<-receipt_request_to> I<emailaddress>
Add an explicit email address where signed receipts should be sent to. This
option B<must> but supplied if a signed receipt is requested.
=back
=head2 Verification options
=over 4
=item B<-signer> I<file>
If a message has been verified successfully then the signers certificate(s)
will be written to this file if the verification was successful.
=item B<-content> I<filename>
This specifies a file containing the detached content for operations taking
S/MIME input, such as the B<-verify> command. This is only usable if the CMS
structure is using the detached signature form where the content is
not included. This option will override any content if the input format
is S/MIME and it uses the multipart/signed MIME content type.
=item B<-no_content_verify>
Do not verify signed content signatures.
=item B<-no_attr_verify>
Do not verify signed attribute signatures.
=item B<-nosigs>
Don't verify message signature.
=item B<-noverify>
Do not verify the signers certificate of a signed message.
=item B<-nointern>
When verifying a message normally certificates (if any) included in
the message are searched for the signing certificate. With this option
only the certificates specified in the B<-certfile> option are used.
The supplied certificates can still be used as untrusted CAs however.
=item B<-cades>
When used with B<-verify>, require and check signer certificate digest.
See the NOTES section for more details.
=item B<-verify_retcode>
Exit nonzero on verification failure.
{- $OpenSSL::safe::opt_trust_item -}
=back
=head2 Output options
=over 4
=item B<-keyid>
Use subject key identifier to identify certificates instead of issuer name and
serial number. The supplied certificate B<must> include a subject key
identifier extension. Supported by B<-sign> and B<-encrypt> options.
=item B<-econtent_type> I<type>
Set the encapsulated content type to I<type> if not supplied the B<Data> type
is used. The I<type> argument can be any valid OID name in either text or
numerical format.
=item B<-text>
This option adds plain text (text/plain) MIME headers to the supplied
message if encrypting or signing. If decrypting or verifying it strips
off text headers: if the decrypted or verified message is not of MIME
type text/plain then an error occurs.
=item B<-certsout> I<file>
Any certificates contained in the input message are written to I<file>.
=item B<-to>, B<-from>, B<-subject>
The relevant email headers. These are included outside the signed
portion of a message so they may be included manually. If signing
then many S/MIME mail clients check the signers certificate's email
address matches that specified in the From: address.
=back
=head2 Printing options
=over 4
=item B<-noout>
For the B<-cmsout> operation do not output the parsed CMS structure.
This is useful if the syntax of the CMS structure is being checked.
=item B<-print>
For the B<-cmsout> operation print out all fields of the CMS structure.
This implies B<-noout>.
This is mainly useful for testing purposes.
=item B<-nameopt> I<option>
For the B<-cmsout> operation when B<-print> option is in use, specifies
printing options for string fields. For most cases B<utf8> is reasonable value.
See L<openssl-namedisplay-options(1)> for details.
=item B<-receipt_request_print>
For the B<-verify> operation print out the contents of any signed receipt
requests.
=back
=head2 Validation options
=over 4
{- $OpenSSL::safe::opt_v_item -}
Any validation errors cause the command to exit.
=back
=head1 NOTES
The MIME message must be sent without any blank lines between the
headers and the output. Some mail programs will automatically add
a blank line. Piping the mail directly to sendmail is one way to
achieve the correct format.
The supplied message to be signed or encrypted must include the
necessary MIME headers or many S/MIME clients won't display it
properly (if at all). You can use the B<-text> option to automatically
add plain text headers.
A "signed and encrypted" message is one where a signed message is
then encrypted. This can be produced by encrypting an already signed
message: see the examples section.
This version of the program only allows one signer per message but it
will verify multiple signers on received messages. Some S/MIME clients
choke if a message contains multiple signers. It is possible to sign
messages "in parallel" by signing an already signed message.
The options B<-encrypt> and B<-decrypt> reflect common usage in S/MIME
clients. Strictly speaking these process CMS enveloped data: CMS
encrypted data is used for other purposes.
The B<-resign> option uses an existing message digest when adding a new
signer. This means that attributes must be present in at least one existing
signer using the same message digest or this operation will fail.
The B<-stream> and B<-indef> options enable streaming I/O support.
As a result the encoding is BER using indefinite length constructed encoding
and no longer DER. Streaming is supported for the B<-encrypt> operation and the
B<-sign> operation if the content is not detached.
Streaming is always used for the B<-sign> operation with detached data but
since the content is no longer part of the CMS structure the encoding
remains DER.
If the B<-decrypt> option is used without a recipient certificate then an
attempt is made to locate the recipient by trying each potential recipient
in turn using the supplied private key. To thwart the MMA attack
(Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) all recipients are
tried whether they succeed or not and if no recipients match the message
is "decrypted" using a random key which will typically output garbage.
The B<-debug_decrypt> option can be used to disable the MMA attack protection
and return an error if no recipient can be found: this option should be used
with caution. For a fuller description see L<CMS_decrypt(3)>).
=head1 CADES BASIC ELECTRONIC SIGNATURE (CADES-BES)
A CAdES Basic Electronic Signature (CAdES-BES),
as defined in the European Standard ETSI EN 319 122-1 V1.1.1, contains:
=over 4
=item *
The signed user data as defined in CMS (RFC 3852);
=item *
Content-type of the EncapsulatedContentInfo value being signed;
=item *
Message-digest of the eContent OCTET STRING within encapContentInfo being signed;
=item *
An ESS signingCertificate or ESS signingCertificateV2 attribute,
as defined in Enhanced Security Services (ESS), RFC 2634 and RFC 5035.
An ESS signingCertificate attribute only allows for SHA-1 as digest algorithm.
An ESS signingCertificateV2 attribute allows for any digest algorithm.
=item *
The digital signature value computed on the user data and, when present, on the signed attributes.
NOTE that the B<-cades> option applies to the B<-sign> or B<-verify> operations.
With this option, the B<-verify> operation also requires that the
signingCertificate attribute is present and checks that the given identifiers
match the verification trust chain built during the verification process.
=back
=head1 EXIT CODES
=over 4
=item Z<>0
The operation was completely successfully.
=item Z<>1
An error occurred parsing the command options.
=item Z<>2
One of the input files could not be read.
=item Z<>3
An error occurred creating the CMS file or when reading the MIME
message.
=item Z<>4
An error occurred decrypting or verifying the message.
=item Z<>5
The message was verified correctly but an error occurred writing out
the signers certificates.
=back
=head1 COMPATIBILITY WITH PKCS#7 FORMAT
L<openssl-smime(1)> can only process the older B<PKCS#7> format.
B<openssl cms> supports Cryptographic Message Syntax format.
Use of some features will result in messages which cannot be processed by
applications which only support the older format. These are detailed below.
The use of the B<-keyid> option with B<-sign> or B<-encrypt>.
The B<-outform> I<PEM> option uses different headers.
The B<-compress> option.
The B<-secretkey> option when used with B<-encrypt>.
The use of PSS with B<-sign>.
The use of OAEP or non-RSA keys with B<-encrypt>.
Additionally the B<-EncryptedData_create> and B<-data_create> type cannot
be processed by the older L<openssl-smime(1)> command.
=head1 EXAMPLES
Create a cleartext signed message:
openssl cms -sign -in message.txt -text -out mail.msg \
-signer mycert.pem
Create an opaque signed message
openssl cms -sign -in message.txt -text -out mail.msg -nodetach \
-signer mycert.pem
Create a signed message, include some additional certificates and
read the private key from another file:
openssl cms -sign -in in.txt -text -out mail.msg \
-signer mycert.pem -inkey mykey.pem -certfile mycerts.pem
Create a signed message with two signers, use key identifier:
openssl cms -sign -in message.txt -text -out mail.msg \
-signer mycert.pem -signer othercert.pem -keyid
Send a signed message under Unix directly to sendmail, including headers:
openssl cms -sign -in in.txt -text -signer mycert.pem \
-from steve@openssl.org -to someone@somewhere \
-subject "Signed message" | sendmail someone@somewhere
Verify a message and extract the signer's certificate if successful:
openssl cms -verify -in mail.msg -signer user.pem -out signedtext.txt
Send encrypted mail using triple DES:
openssl cms -encrypt -in in.txt -from steve@openssl.org \
-to someone@somewhere -subject "Encrypted message" \
-des3 user.pem -out mail.msg
Sign and encrypt mail:
openssl cms -sign -in ml.txt -signer my.pem -text \
| openssl cms -encrypt -out mail.msg \
-from steve@openssl.org -to someone@somewhere \
-subject "Signed and Encrypted message" -des3 user.pem
Note: the encryption command does not include the B<-text> option because the
message being encrypted already has MIME headers.
Decrypt a message:
openssl cms -decrypt -in mail.msg -recip mycert.pem -inkey key.pem
The output from Netscape form signing is a PKCS#7 structure with the
detached signature format. You can use this program to verify the
signature by line wrapping the base64 encoded structure and surrounding
it with:
-----BEGIN PKCS7-----
-----END PKCS7-----
and using the command,
openssl cms -verify -inform PEM -in signature.pem -content content.txt
alternatively you can base64 decode the signature and use
openssl cms -verify -inform DER -in signature.der -content content.txt
Create an encrypted message using 128 bit Camellia:
openssl cms -encrypt -in plain.txt -camellia128 -out mail.msg cert.pem
Add a signer to an existing message:
openssl cms -resign -in mail.msg -signer newsign.pem -out mail2.msg
Sign a message using RSA-PSS:
openssl cms -sign -in message.txt -text -out mail.msg \
-signer mycert.pem -keyopt rsa_padding_mode:pss
Create an encrypted message using RSA-OAEP:
openssl cms -encrypt -in plain.txt -out mail.msg \
-recip cert.pem -keyopt rsa_padding_mode:oaep
Use SHA256 KDF with an ECDH certificate:
openssl cms -encrypt -in plain.txt -out mail.msg \
-recip ecdhcert.pem -keyopt ecdh_kdf_md:sha256
Print CMS signed binary data in human-readable form:
openssl cms -in signed.cms -binary -inform DER -cmsout -print
=head1 BUGS
The MIME parser isn't very clever: it seems to handle most messages that I've
thrown at it but it may choke on others.
The code currently will only write out the signer's certificate to a file: if
the signer has a separate encryption certificate this must be manually
extracted. There should be some heuristic that determines the correct
encryption certificate.
Ideally a database should be maintained of a certificates for each email
address.
The code doesn't currently take note of the permitted symmetric encryption
algorithms as supplied in the SMIMECapabilities signed attribute. this means the
user has to manually include the correct encryption algorithm. It should store
the list of permitted ciphers in a database and only use those.
No revocation checking is done on the signer's certificate.
=head1 SEE ALSO
L<ossl_store-file(7)>
=head1 HISTORY
The use of multiple B<-signer> options and the B<-resign> command were first
added in OpenSSL 1.0.0.
The B<-keyopt> option was added in OpenSSL 1.0.2.
Support for RSA-OAEP and RSA-PSS was added in OpenSSL 1.0.2.
The use of non-RSA keys with B<-encrypt> and B<-decrypt>
was added in OpenSSL 1.0.2.
The -no_alt_chains option was added in OpenSSL 1.0.2b.
The B<-nameopt> option was added in OpenSSL 3.0.0.
The B<-engine> option was deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-fipsinstall.pod.in b/crypto/openssl/doc/man1/openssl-fipsinstall.pod.in
index 97e2ae910c17..57758597cdae 100644
--- a/crypto/openssl/doc/man1/openssl-fipsinstall.pod.in
+++ b/crypto/openssl/doc/man1/openssl-fipsinstall.pod.in
@@ -1,251 +1,255 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-fipsinstall - perform FIPS configuration installation
=head1 SYNOPSIS
B<openssl fipsinstall>
[B<-help>]
[B<-in> I<configfilename>]
[B<-out> I<configfilename>]
[B<-module> I<modulefilename>]
[B<-provider_name> I<providername>]
[B<-section_name> I<sectionname>]
[B<-verify>]
[B<-mac_name> I<macname>]
[B<-macopt> I<nm>:I<v>]
[B<-noout>]
[B<-quiet>]
[B<-no_conditional_errors>]
[B<-no_security_checks>]
[B<-self_test_onload>]
[B<-corrupt_desc> I<selftest_description>]
[B<-corrupt_type> I<selftest_type>]
[B<-config> I<parent_config>]
=head1 DESCRIPTION
This command is used to generate a FIPS module configuration file.
This configuration file can be used each time a FIPS module is loaded
in order to pass data to the FIPS module self tests. The FIPS module always
verifies its MAC, but optionally only needs to run the KAT's once,
at installation.
The generated configuration file consists of:
=over 4
=item - A MAC of the FIPS module file.
=item - A test status indicator.
This indicates if the Known Answer Self Tests (KAT's) have successfully run.
=item - A MAC of the status indicator.
=item - A control for conditional self tests errors.
By default if a continuous test (e.g a key pair test) fails then the FIPS module
will enter an error state, and no services or cryptographic algorithms will be
able to be accessed after this point.
The default value of '1' will cause the fips module error state to be entered.
If the value is '0' then the module error state will not be entered.
Regardless of whether the error state is entered or not, the current operation
(e.g. key generation) will return an error. The user is responsible for retrying
the operation if the module error state is not entered.
=item - A control to indicate whether run-time security checks are done.
This indicates if run-time checks related to enforcement of security parameters
such as minimum security strength of keys and approved curve names are used.
The default value of '1' will perform the checks.
If the value is '0' the checks are not performed and FIPS compliance must
be done by procedures documented in the relevant Security Policy.
=back
This file is described in L<fips_config(5)>.
=head1 OPTIONS
=over 4
=item B<-help>
Print a usage message.
=item B<-module> I<filename>
Filename of the FIPS module to perform an integrity check on.
The path provided in the filename is used to load the module when it is
activated, and this overrides the environment variable B<OPENSSL_MODULES>.
=item B<-out> I<configfilename>
Filename to output the configuration data to; the default is standard output.
=item B<-in> I<configfilename>
Input filename to load configuration data from.
Must be used if the B<-verify> option is specified.
=item B<-verify>
Verify that the input configuration file contains the correct information.
=item B<-provider_name> I<providername>
Name of the provider inside the configuration file.
The default value is C<fips>.
=item B<-section_name> I<sectionname>
Name of the section inside the configuration file.
The default value is C<fips_sect>.
=item B<-mac_name> I<name>
Specifies the name of a supported MAC algorithm which will be used.
The MAC mechanisms that are available will depend on the options
used when building OpenSSL.
To see the list of supported MAC's use the command
C<openssl list -mac-algorithms>. The default is B<HMAC>.
=item B<-macopt> I<nm>:I<v>
Passes options to the MAC algorithm.
A comprehensive list of controls can be found in the EVP_MAC implementation
documentation.
Common control strings used for this command are:
=over 4
=item B<key>:I<string>
Specifies the MAC key as an alphanumeric string (use if the key contains
printable characters only).
The string length must conform to any restrictions of the MAC algorithm.
A key must be specified for every MAC algorithm.
If no key is provided, the default that was specified when OpenSSL was
configured is used.
=item B<hexkey>:I<string>
Specifies the MAC key in hexadecimal form (two hex digits per byte).
The key length must conform to any restrictions of the MAC algorithm.
A key must be specified for every MAC algorithm.
If no key is provided, the default that was specified when OpenSSL was
configured is used.
=item B<digest>:I<string>
Used by HMAC as an alphanumeric string (use if the key contains printable
characters only).
The string length must conform to any restrictions of the MAC algorithm.
To see the list of supported digests, use the command
C<openssl list -digest-commands>.
The default digest is SHA-256.
=back
=item B<-noout>
Disable logging of the self tests.
=item B<-no_conditional_errors>
Configure the module to not enter an error state if a conditional self test
fails as described above.
=item B<-no_security_checks>
Configure the module to not perform run-time security checks as described above.
=item B<-self_test_onload>
Do not write the two fields related to the "test status indicator" and
"MAC status indicator" to the output configuration file. Without these fields
the self tests KATS will run each time the module is loaded. This option could be
used for cross compiling, since the self tests need to run at least once on each
target machine. Once the self tests have run on the target machine the user
could possibly then add the 2 fields into the configuration using some other
mechanism.
=item B<-quiet>
Do not output pass/fail messages. Implies B<-noout>.
=item B<-corrupt_desc> I<selftest_description>,
B<-corrupt_type> I<selftest_type>
The corrupt options can be used to test failure of one or more self tests by
name.
Either option or both may be used to select the tests to corrupt.
Refer to the entries for B<st-desc> and B<st-type> in L<OSSL_PROVIDER-FIPS(7)> for
values that can be used.
=item B<-config> I<parent_config>
Test that a FIPS provider can be loaded from the specified configuration file.
A previous call to this application needs to generate the extra configuration
data that is included by the base C<parent_config> configuration file.
See L<config(5)> for further information on how to set up a provider section.
All other options are ignored if '-config' is used.
=back
=head1 NOTES
Self tests results are logged by default if the options B<-quiet> and B<-noout>
are not specified, or if either of the options B<-corrupt_desc> or
B<-corrupt_type> are used.
If the base configuration file is set up to autoload the fips module, then the
fips module will be loaded and self tested BEFORE the fipsinstall application
has a chance to set up its own self test callback. As a result of this the self
test output and the options B<-corrupt_desc> and B<-corrupt_type> will be ignored.
For normal usage the base configuration file should use the default provider
when generating the fips configuration file.
=head1 EXAMPLES
Calculate the mac of a FIPS module F<fips.so> and run a FIPS self test
for the module, and save the F<fips.cnf> configuration file:
openssl fipsinstall -module ./fips.so -out fips.cnf -provider_name fips
Verify that the configuration file F<fips.cnf> contains the correct info:
openssl fipsinstall -module ./fips.so -in fips.cnf -provider_name fips -verify
Corrupt any self tests which have the description C<SHA1>:
openssl fipsinstall -module ./fips.so -out fips.cnf -provider_name fips \
-corrupt_desc 'SHA1'
Validate that the fips module can be loaded from a base configuration file:
export OPENSSL_CONF_INCLUDE=<path of configuration files>
export OPENSSL_MODULES=<provider-path>
openssl fipsinstall -config' 'default.cnf'
=head1 SEE ALSO
L<config(5)>,
L<fips_config(5)>,
L<OSSL_PROVIDER-FIPS(7)>,
L<EVP_MAC(3)>
+=head1 HISTORY
+
+The B<openssl-fipsinstall> application was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-ocsp.pod.in b/crypto/openssl/doc/man1/openssl-ocsp.pod.in
index fbad5079af67..fd23a44df063 100644
--- a/crypto/openssl/doc/man1/openssl-ocsp.pod.in
+++ b/crypto/openssl/doc/man1/openssl-ocsp.pod.in
@@ -1,517 +1,525 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-ocsp - Online Certificate Status Protocol command
=head1 SYNOPSIS
=head2 OCSP Client
B<openssl> B<ocsp>
[B<-help>]
[B<-out> I<file>]
[B<-issuer> I<file>]
[B<-cert> I<file>]
[B<-no_certs>]
[B<-serial> I<n>]
[B<-signer> I<file>]
[B<-signkey> I<file>]
[B<-sign_other> I<file>]
[B<-nonce>]
[B<-no_nonce>]
[B<-req_text>]
[B<-resp_text>]
[B<-text>]
[B<-reqout> I<file>]
[B<-respout> I<file>]
[B<-reqin> I<file>]
[B<-respin> I<file>]
[B<-url> I<URL>]
[B<-host> I<host>:I<port>]
-[B<-path>]
-[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path]>]
+[B<-path> I<pathname>]
+[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>]
[B<-no_proxy> I<addresses>]
[B<-header>]
[B<-timeout> I<seconds>]
[B<-VAfile> I<file>]
[B<-validity_period> I<n>]
[B<-status_age> I<n>]
[B<-noverify>]
[B<-verify_other> I<file>]
[B<-trust_other>]
[B<-no_intern>]
[B<-no_signature_verify>]
[B<-no_cert_verify>]
[B<-no_chain>]
[B<-no_cert_checks>]
[B<-no_explicit>]
[B<-port> I<num>]
[B<-ignore_err>]
=head2 OCSP Server
B<openssl> B<ocsp>
[B<-index> I<file>]
[B<-CA> I<file>]
[B<-rsigner> I<file>]
[B<-rkey> I<file>]
[B<-passin> I<arg>]
[B<-rother> I<file>]
[B<-rsigopt> I<nm>:I<v>]
[B<-rmd> I<digest>]
[B<-badsig>]
[B<-resp_no_certs>]
[B<-nmin> I<n>]
[B<-ndays> I<n>]
[B<-resp_key_id>]
[B<-nrequest> I<n>]
[B<-multi> I<process-count>]
[B<-rcid> I<digest>]
[B<-I<digest>>]
{- $OpenSSL::safe::opt_trust_synopsis -}
{- $OpenSSL::safe::opt_v_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
=head1 DESCRIPTION
The Online Certificate Status Protocol (OCSP) enables applications to
determine the (revocation) state of an identified certificate (RFC 2560).
This command performs many common OCSP tasks. It can be used
to print out requests and responses, create requests and send queries
to an OCSP responder and behave like a mini OCSP server itself.
=head1 OPTIONS
This command operates as either a client or a server.
The options are described below, divided into those two modes.
=head2 OCSP Client Options
=over 4
=item B<-help>
Print out a usage message.
=item B<-out> I<filename>
specify output filename, default is standard output.
=item B<-issuer> I<filename>
This specifies the current issuer certificate. This option can be used
multiple times.
This option B<MUST> come before any B<-cert> options.
=item B<-cert> I<filename>
Add the certificate I<filename> to the request. The issuer certificate
is taken from the previous B<-issuer> option, or an error occurs if no
issuer certificate is specified.
=item B<-no_certs>
Don't include any certificates in signed request.
=item B<-serial> I<num>
Same as the B<-cert> option except the certificate with serial number
B<num> is added to the request. The serial number is interpreted as a
decimal integer unless preceded by C<0x>. Negative integers can also
be specified by preceding the value by a C<-> sign.
=item B<-signer> I<filename>, B<-signkey> I<filename>
Sign the OCSP request using the certificate specified in the B<-signer>
option and the private key specified by the B<-signkey> option. If
the B<-signkey> option is not present then the private key is read
from the same file as the certificate. If neither option is specified then
the OCSP request is not signed.
=item B<-sign_other> I<filename>
Additional certificates to include in the signed request.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-nonce>, B<-no_nonce>
Add an OCSP nonce extension to a request or disable OCSP nonce addition.
Normally if an OCSP request is input using the B<-reqin> option no
nonce is added: using the B<-nonce> option will force addition of a nonce.
If an OCSP request is being created (using B<-cert> and B<-serial> options)
a nonce is automatically added specifying B<-no_nonce> overrides this.
=item B<-req_text>, B<-resp_text>, B<-text>
Print out the text form of the OCSP request, response or both respectively.
=item B<-reqout> I<file>, B<-respout> I<file>
Write out the DER encoded certificate request or response to I<file>.
=item B<-reqin> I<file>, B<-respin> I<file>
Read OCSP request or response file from I<file>. These option are ignored
if OCSP request or response creation is implied by other options (for example
with B<-serial>, B<-cert> and B<-host> options).
=item B<-url> I<responder_url>
-Specify the responder URL. Both HTTP and HTTPS (SSL/TLS) URLs can be specified.
+Specify the responder host and optionally port and path via a URL.
+Both HTTP and HTTPS (SSL/TLS) URLs can be specified.
The optional userinfo and fragment components are ignored.
Any given query component is handled as part of the path component.
+For details, see the B<-host> and B<-path> options described next.
-=item B<-host> I<hostname>:I<port>, B<-path> I<pathname>
+=item B<-host> I<host>:I<port>, B<-path> I<pathname>
If the B<-host> option is present then the OCSP request is sent to the host
-I<hostname> on port I<port>. The B<-path> option specifies the HTTP pathname
-to use or "/" by default. This is equivalent to specifying B<-url> with scheme
-http:// and the given hostname, port, and pathname.
+I<host> on port I<port>.
+The I<host> may be a domain name or an IP (v4 or v6) address,
+such as C<127.0.0.1> or C<[::1]> for localhost.
+If it is an IPv6 address, it must be enclosed in C<[> and C<]>.
-=item B<-proxy> I<[http[s]://][userinfo@]host[:port][/path]>
+The B<-path> option specifies the HTTP pathname to use or "/" by default.
+This is equivalent to specifying B<-url> with scheme
+http:// and the given I<host>, I<port>, and optional I<pathname>.
+
+=item B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>
The HTTP(S) proxy server to use for reaching the OCSP server unless B<-no_proxy>
applies, see below.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
The proxy port defaults to 80 or 443 if the scheme is C<https>; apart from that
the optional C<http://> or C<https://> prefix is ignored,
-as well as any userinfo and path components.
+as well as any userinfo, path, query, and fragment components.
Defaults to the environment variable C<http_proxy> if set, else C<HTTP_PROXY>
in case no TLS is used, otherwise C<https_proxy> if set, else C<HTTPS_PROXY>.
=item B<-no_proxy> I<addresses>
List of IP addresses and/or DNS names of servers
not to use an HTTP(S) proxy for, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Default is from the environment variable C<no_proxy> if set, else C<NO_PROXY>.
=item B<-header> I<name>=I<value>
Adds the header I<name> with the specified I<value> to the OCSP request
that is sent to the responder.
This may be repeated.
=item B<-timeout> I<seconds>
Connection timeout to the OCSP responder in seconds.
On POSIX systems, when running as an OCSP responder, this option also limits
the time that the responder is willing to wait for the client request.
This time is measured from the time the responder accepts the connection until
the complete request is received.
=item B<-verify_other> I<file>
File or URI containing additional certificates to search
when attempting to locate
the OCSP response signing certificate. Some responders omit the actual signer's
certificate from the response: this option can be used to supply the necessary
certificate in such cases.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-trust_other>
The certificates specified by the B<-verify_other> option should be explicitly
trusted and no additional checks will be performed on them. This is useful
when the complete responder certificate chain is not available or trusting a
root CA is not appropriate.
=item B<-VAfile> I<file>
File or URI containing explicitly trusted responder certificates.
Equivalent to the B<-verify_other> and B<-trust_other> options.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-noverify>
Don't attempt to verify the OCSP response signature or the nonce
values. This option will normally only be used for debugging since it
disables all verification of the responders certificate.
=item B<-no_intern>
Ignore certificates contained in the OCSP response when searching for the
signers certificate. With this option the signers certificate must be specified
with either the B<-verify_other> or B<-VAfile> options.
=item B<-no_signature_verify>
Don't check the signature on the OCSP response. Since this option
tolerates invalid signatures on OCSP responses it will normally only be
used for testing purposes.
=item B<-no_cert_verify>
Don't verify the OCSP response signers certificate at all. Since this
option allows the OCSP response to be signed by any certificate it should
only be used for testing purposes.
=item B<-no_chain>
Do not use certificates in the response as additional untrusted CA
certificates.
=item B<-no_explicit>
Do not explicitly trust the root CA if it is set to be trusted for OCSP signing.
=item B<-no_cert_checks>
Don't perform any additional checks on the OCSP response signers certificate.
That is do not make any checks to see if the signers certificate is authorised
to provide the necessary status information: as a result this option should
only be used for testing purposes.
=item B<-validity_period> I<nsec>, B<-status_age> I<age>
These options specify the range of times, in seconds, which will be tolerated
in an OCSP response. Each certificate status response includes a B<notBefore>
time and an optional B<notAfter> time. The current time should fall between
these two values, but the interval between the two times may be only a few
seconds. In practice the OCSP responder and clients clocks may not be precisely
synchronised and so such a check may fail. To avoid this the
B<-validity_period> option can be used to specify an acceptable error range in
seconds, the default value is 5 minutes.
If the B<notAfter> time is omitted from a response then this means that new
status information is immediately available. In this case the age of the
B<notBefore> field is checked to see it is not older than I<age> seconds old.
By default this additional check is not performed.
=item B<-rcid> I<digest>
This option sets the digest algorithm to use for certificate identification
in the OCSP response. Any digest supported by the L<openssl-dgst(1)> command can
be used. The default is the same digest algorithm used in the request.
=item B<-I<digest>>
This option sets digest algorithm to use for certificate identification in the
OCSP request. Any digest supported by the OpenSSL B<dgst> command can be used.
The default is SHA-1. This option may be used multiple times to specify the
digest used by subsequent certificate identifiers.
{- $OpenSSL::safe::opt_trust_item -}
{- $OpenSSL::safe::opt_v_item -}
{- $OpenSSL::safe::opt_provider_item -}
=back
=head2 OCSP Server Options
=over 4
=item B<-index> I<indexfile>
The I<indexfile> parameter is the name of a text index file in B<ca>
format containing certificate revocation information.
If the B<-index> option is specified then this command switches to
responder mode, otherwise it is in client mode. The request(s) the responder
processes can be either specified on the command line (using B<-issuer>
and B<-serial> options), supplied in a file (using the B<-reqin> option)
or via external OCSP clients (if B<-port> or B<-url> is specified).
If the B<-index> option is present then the B<-CA> and B<-rsigner> options
must also be present.
=item B<-CA> I<file>
CA certificate corresponding to the revocation information in the index
file given with B<-index>.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-rsigner> I<file>
The certificate to sign OCSP responses with.
=item B<-rkey> I<file>
The private key to sign OCSP responses with: if not present the file
specified in the B<-rsigner> option is used.
=item B<-passin> I<arg>
The private key password source. For more information about the format of I<arg>
see L<openssl-passphrase-options(1)>.
=item B<-rother> I<file>
Additional certificates to include in the OCSP response.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-rsigopt> I<nm>:I<v>
Pass options to the signature algorithm when signing OCSP responses.
Names and values of these options are algorithm-specific.
=item B<-rmd> I<digest>
The digest to use when signing the response.
=item B<-badsig>
Corrupt the response signature before writing it; this can be useful
for testing.
=item B<-resp_no_certs>
Don't include any certificates in the OCSP response.
=item B<-resp_key_id>
Identify the signer certificate using the key ID, default is to use the
subject name.
=item B<-port> I<portnum>
-Port to listen for OCSP requests on. The port may also be specified
-using the B<url> option.
+Port to listen for OCSP requests on. Both IPv4 and IPv6 are possible.
+The port may also be specified using the B<-url> option.
A C<0> argument indicates that any available port shall be chosen automatically.
=item B<-ignore_err>
Ignore malformed requests or responses: When acting as an OCSP client, retry if
a malformed response is received. When acting as an OCSP responder, continue
running instead of terminating upon receiving a malformed request.
=item B<-nrequest> I<number>
The OCSP server will exit after receiving I<number> requests, default unlimited.
=item B<-multi> I<process-count>
Run the specified number of OCSP responder child processes, with the parent
process respawning child processes as needed.
Child processes will detect changes in the CA index file and automatically
reload it.
When running as a responder B<-timeout> option is recommended to limit the time
each child is willing to wait for the client's OCSP response.
This option is available on POSIX systems (that support the fork() and other
required unix system-calls).
=item B<-nmin> I<minutes>, B<-ndays> I<days>
Number of minutes or days when fresh revocation information is available:
used in the B<nextUpdate> field. If neither option is present then the
B<nextUpdate> field is omitted meaning fresh revocation information is
immediately available.
=back
=head1 OCSP RESPONSE VERIFICATION
OCSP Response follows the rules specified in RFC2560.
Initially the OCSP responder certificate is located and the signature on
the OCSP request checked using the responder certificate's public key.
Then a normal certificate verify is performed on the OCSP responder certificate
building up a certificate chain in the process. The locations of the trusted
certificates used to build the chain can be specified by the B<-CAfile>,
B<-CApath> or B<-CAstore> options or they will be looked for in the
standard OpenSSL certificates directory.
If the initial verify fails then the OCSP verify process halts with an
error.
Otherwise the issuing CA certificate in the request is compared to the OCSP
responder certificate: if there is a match then the OCSP verify succeeds.
Otherwise the OCSP responder certificate's CA is checked against the issuing
CA certificate in the request. If there is a match and the OCSPSigning
extended key usage is present in the OCSP responder certificate then the
OCSP verify succeeds.
Otherwise, if B<-no_explicit> is B<not> set the root CA of the OCSP responders
CA is checked to see if it is trusted for OCSP signing. If it is the OCSP
verify succeeds.
If none of these checks is successful then the OCSP verify fails.
What this effectively means if that if the OCSP responder certificate is
authorised directly by the CA it is issuing revocation information about
(and it is correctly configured) then verification will succeed.
If the OCSP responder is a "global responder" which can give details about
multiple CAs and has its own separate certificate chain then its root
CA can be trusted for OCSP signing. For example:
openssl x509 -in ocspCA.pem -addtrust OCSPSigning -out trustedCA.pem
Alternatively the responder certificate itself can be explicitly trusted
with the B<-VAfile> option.
=head1 NOTES
As noted, most of the verify options are for testing or debugging purposes.
Normally only the B<-CApath>, B<-CAfile>, B<-CAstore> and (if the responder
is a 'global VA') B<-VAfile> options need to be used.
The OCSP server is only useful for test and demonstration purposes: it is
not really usable as a full OCSP responder. It contains only a very
simple HTTP request handling and can only handle the POST form of OCSP
queries. It also handles requests serially meaning it cannot respond to
new requests until it has processed the current one. The text index file
format of revocation is also inefficient for large quantities of revocation
data.
It is possible to run this command in responder mode via a CGI
script using the B<-reqin> and B<-respout> options.
=head1 EXAMPLES
Create an OCSP request and write it to a file:
openssl ocsp -issuer issuer.pem -cert c1.pem -cert c2.pem -reqout req.der
Send a query to an OCSP responder with URL http://ocsp.myhost.com/ save the
response to a file, print it out in text form, and verify the response:
openssl ocsp -issuer issuer.pem -cert c1.pem -cert c2.pem \
-url http://ocsp.myhost.com/ -resp_text -respout resp.der
Read in an OCSP response and print out text form:
openssl ocsp -respin resp.der -text -noverify
OCSP server on port 8888 using a standard B<ca> configuration, and a separate
responder certificate. All requests and responses are printed to a file.
openssl ocsp -index demoCA/index.txt -port 8888 -rsigner rcert.pem -CA demoCA/cacert.pem
-text -out log.txt
As above but exit after processing one request:
openssl ocsp -index demoCA/index.txt -port 8888 -rsigner rcert.pem -CA demoCA/cacert.pem
-nrequest 1
Query status information using an internally generated request:
openssl ocsp -index demoCA/index.txt -rsigner rcert.pem -CA demoCA/cacert.pem
-issuer demoCA/cacert.pem -serial 1
Query status information using request read from a file, and write the response
to a second file.
openssl ocsp -index demoCA/index.txt -rsigner rcert.pem -CA demoCA/cacert.pem
-reqin req.der -respout resp.der
=head1 HISTORY
The -no_alt_chains option was added in OpenSSL 1.1.0.
=head1 COPYRIGHT
Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-pkeyutl.pod.in b/crypto/openssl/doc/man1/openssl-pkeyutl.pod.in
index cf3427a35c0b..2f6ef0021d14 100644
--- a/crypto/openssl/doc/man1/openssl-pkeyutl.pod.in
+++ b/crypto/openssl/doc/man1/openssl-pkeyutl.pod.in
@@ -1,430 +1,463 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-pkeyutl - public key algorithm command
=head1 SYNOPSIS
B<openssl> B<pkeyutl>
[B<-help>]
[B<-in> I<file>]
[B<-rawin>]
[B<-digest> I<algorithm>]
[B<-out> I<file>]
[B<-sigfile> I<file>]
[B<-inkey> I<filename>|I<uri>]
[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
[B<-passin> I<arg>]
[B<-peerkey> I<file>]
[B<-peerform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
[B<-pubin>]
[B<-certin>]
[B<-rev>]
[B<-sign>]
[B<-verify>]
[B<-verifyrecover>]
[B<-encrypt>]
[B<-decrypt>]
[B<-derive>]
[B<-kdf> I<algorithm>]
[B<-kdflen> I<length>]
[B<-pkeyopt> I<opt>:I<value>]
[B<-pkeyopt_passin> I<opt>[:I<passarg>]]
[B<-hexdump>]
[B<-asn1parse>]
{- $OpenSSL::safe::opt_engine_synopsis -}[B<-engine_impl>]
{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
{- $OpenSSL::safe::opt_config_synopsis -}
=head1 DESCRIPTION
This command can be used to perform low-level public key
operations using any supported algorithm.
+By default the signing operation (see B<-sign> option) is assumed.
+
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-in> I<filename>
This specifies the input filename to read data from or standard input
if this option is not specified.
=item B<-rawin>
-This indicates that the input data is raw data, which is not hashed by any
-message digest algorithm. The user can specify a digest algorithm by using
-the B<-digest> option. This option can only be used with B<-sign> and
-B<-verify> and must be used with the Ed25519 and Ed448 algorithms.
+This indicates that the signature or verification input data is raw data,
+which is not hashed by any message digest algorithm.
+Except with EdDSA,
+the user can specify a digest algorithm by using the B<-digest> option.
+For signature algorithms like RSA, DSA and ECDSA,
+the default digest algorithm is SHA-256. For SM2, it is SM3.
+
+This option can only be used with B<-sign> and B<-verify>.
+For EdDSA (the Ed25519 and Ed448 algorithms) this option is required.
=item B<-digest> I<algorithm>
-This specifies the digest algorithm which is used to hash the input data before
-signing or verifying it with the input key. This option could be omitted if the
-signature algorithm does not require one (for instance, EdDSA). If this option
-is omitted but the signature algorithm requires one, a default value will be
-used. For signature algorithms like RSA, DSA and ECDSA, SHA-256 will be the
-default digest algorithm. For SM2, it will be SM3. If this option is present,
-then the B<-rawin> option must be also specified.
+This option can only be used with B<-sign> and B<-verify>.
+It specifies the digest algorithm that is used to hash the input data
+before signing or verifying it with the input key. This option could be omitted
+if the signature algorithm does not require preprocessing the input through
+a pluggable hash function before signing (for instance, EdDSA). If this option
+is omitted but the signature algorithm requires one and the B<-rawin> option
+is given, a default value will be used (see B<-rawin> for details).
+If this option is present, then the B<-rawin> option is required.
+
+At this time, HashEdDSA (the ph or "prehash" variant of EdDSA) is not supported,
+so the B<-digest> option cannot be used with EdDSA.
=item B<-out> I<filename>
Specifies the output filename to write to or standard output by
default.
=item B<-sigfile> I<file>
-Signature file, required for B<-verify> operations only
+Signature file, required and allowed for B<-verify> operations only
=item B<-inkey> I<filename>|I<uri>
The input key, by default it should be a private key.
=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The key format; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-passin> I<arg>
The input key password source. For more information about the format of I<arg>
see L<openssl-passphrase-options(1)>.
=item B<-peerkey> I<file>
The peer key file, used by key derivation (agreement) operations.
=item B<-peerform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The peer key format; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-pubin>
The input file is a public key.
=item B<-certin>
The input is a certificate containing a public key.
=item B<-rev>
Reverse the order of the input buffer. This is useful for some libraries
-(such as CryptoAPI) which represent the buffer in little endian format.
+(such as CryptoAPI) which represent the buffer in little-endian format.
+This cannot be used in conjunction with B<-rawin>.
=item B<-sign>
-Sign the input data (which must be a hash) and output the signed result. This
-requires a private key.
+Sign the input data and output the signed result. This requires a private key.
+Using a message digest operation along with this is recommended,
+when applicable, see the B<-rawin> and B<-digest> options for details.
+Otherwise, the input data given with the B<-in> option is assumed to already
+be a digest, but this may then require an additional B<-pkeyopt> C<digest:>I<md>
+in some cases (e.g., RSA with the default PKCS#1 padding mode).
+Even for other algorithms like ECDSA, where the additional B<-pkeyopt> option
+does not affect signature output, it is recommended, as it enables
+checking that the input length is consistent with the intended digest.
=item B<-verify>
-Verify the input data (which must be a hash) against the signature file and
-indicate if the verification succeeded or failed.
+Verify the input data against the signature given with the B<-sigfile> option
+and indicate if the verification succeeded or failed.
+The input data given with the B<-in> option is assumed to be a hash value
+unless the B<-rawin> option is specified or implied.
+With raw data, when a digest algorithm is applicable, though it may be inferred
+from the signature or take a default value, it should also be specified.
=item B<-verifyrecover>
-Verify the input data (which must be a hash) and output the recovered data.
+Verify the given signature and output the recovered data (signature payload).
+For example, in case of RSA PKCS#1 the recovered data is the B<EMSA-PKCS-v1_5>
+DER encoding of the digest algorithm OID and value as specified in
+L<RFC8017 Section 9.2|https://datatracker.ietf.org/doc/html/rfc8017#section-9.2>.
+
+Note that here the input given with the B<-in> option is not a signature input
+(as with the B<-sign> and B<-verify> options) but a signature output value,
+typically produced using the B<-sign> option.
+
+This option is available only for use with RSA keys.
=item B<-encrypt>
Encrypt the input data using a public key.
=item B<-decrypt>
Decrypt the input data using a private key.
=item B<-derive>
Derive a shared secret using the peer key.
=item B<-kdf> I<algorithm>
Use key derivation function I<algorithm>. The supported algorithms are
at present B<TLS1-PRF> and B<HKDF>.
Note: additional parameters and the KDF output length will normally have to be
set for this to work.
See L<EVP_PKEY_CTX_set_hkdf_md(3)> and L<EVP_PKEY_CTX_set_tls1_prf_md(3)>
for the supported string parameters of each algorithm.
=item B<-kdflen> I<length>
Set the output length for KDF.
=item B<-pkeyopt> I<opt>:I<value>
Public key options specified as opt:value. See NOTES below for more details.
=item B<-pkeyopt_passin> I<opt>[:I<passarg>]
Allows reading a public key option I<opt> from stdin or a password source.
If only I<opt> is specified, the user will be prompted to enter a password on
stdin. Alternatively, I<passarg> can be specified which can be any value
supported by L<openssl-passphrase-options(1)>.
=item B<-hexdump>
hex dump the output data.
=item B<-asn1parse>
-Parse the ASN.1 output data, this is useful when combined with the
-B<-verifyrecover> option when an ASN1 structure is signed.
+Parse the ASN.1 output data to check its DER encoding and print any errors.
+When combined with the B<-verifyrecover> option, this may be useful only in case
+an ASN.1 DER-encoded structure had been signed directly (without hashing it).
{- $OpenSSL::safe::opt_engine_item -}
{- output_off() if $disabled{"deprecated-3.0"}; "" -}
=item B<-engine_impl>
When used with the B<-engine> option, it specifies to also use
engine I<id> for crypto operations.
{- output_on() if $disabled{"deprecated-3.0"}; "" -}
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_provider_item -}
{- $OpenSSL::safe::opt_config_item -}
=back
=head1 NOTES
The operations and options supported vary according to the key algorithm
and its implementation. The OpenSSL operations and options are indicated below.
-Unless otherwise mentioned all algorithms support the B<digest:>I<alg> option
-which specifies the digest in use for sign, verify and verifyrecover operations.
+Unless otherwise mentioned, all algorithms support the B<digest:>I<alg> option,
+which specifies the digest in use for the signing and verification operations.
The value I<alg> should represent a digest name as used in the
EVP_get_digestbyname() function for example B<sha1>. This value is not used to
hash the input data. It is used (by some algorithms) for sanity-checking the
lengths of data passed in and for creating the structures that make up the
signature (e.g. B<DigestInfo> in RSASSA PKCS#1 v1.5 signatures).
This command does not hash the input data (except where -rawin is used) but
rather it will use the data directly as input to the signature algorithm.
Depending on the key type, signature type, and mode of padding, the maximum
acceptable lengths of input data differ. The signed data can't be longer than
the key modulus with RSA. In case of ECDSA and DSA the data shouldn't be longer
than the field size, otherwise it will be silently truncated to the field size.
In any event the input size must not be larger than the largest supported digest
size.
In other words, if the value of digest is B<sha1> the input should be the 20
bytes long binary encoding of the SHA-1 hash function output.
=head1 RSA ALGORITHM
The RSA algorithm generally supports the encrypt, decrypt, sign,
verify and verifyrecover operations. However, some padding modes
support only a subset of these operations. The following additional
B<pkeyopt> values are supported:
=over 4
=item B<rsa_padding_mode:>I<mode>
This sets the RSA padding mode. Acceptable values for I<mode> are B<pkcs1> for
PKCS#1 padding, B<none> for no padding, B<oaep>
for B<OAEP> mode, B<x931> for X9.31 mode and B<pss> for PSS.
In PKCS#1 padding, if the message digest is not set, then the supplied data is
signed or verified directly instead of using a B<DigestInfo> structure. If a
digest is set, then the B<DigestInfo> structure is used and its length
must correspond to the digest type.
For B<oaep> mode only encryption and decryption is supported.
For B<x931> if the digest type is set it is used to format the block data
otherwise the first byte is used to specify the X9.31 digest ID. Sign,
verify and verifyrecover are can be performed in this mode.
For B<pss> mode only sign and verify are supported and the digest type must be
specified.
=item B<rsa_pss_saltlen:>I<len>
For B<pss> mode only this option specifies the salt length. Three special
values are supported: B<digest> sets the salt length to the digest length,
B<max> sets the salt length to the maximum permissible value. When verifying
B<auto> causes the salt length to be automatically determined based on the
B<PSS> block structure.
=item B<rsa_mgf1_md:>I<digest>
For PSS and OAEP padding sets the MGF1 digest. If the MGF1 digest is not
explicitly set in PSS mode then the signing digest is used.
=item B<rsa_oaep_md:>I<digest>
Sets the digest used for the OAEP hash function. If not explicitly set then
SHA1 is used.
=back
=head1 RSA-PSS ALGORITHM
The RSA-PSS algorithm is a restricted version of the RSA algorithm which only
supports the sign and verify operations with PSS padding. The following
additional B<-pkeyopt> values are supported:
=over 4
=item B<rsa_padding_mode:>I<mode>, B<rsa_pss_saltlen:>I<len>,
B<rsa_mgf1_md:>I<digest>
These have the same meaning as the B<RSA> algorithm with some additional
restrictions. The padding mode can only be set to B<pss> which is the
default value.
If the key has parameter restrictions than the digest, MGF1
digest and salt length are set to the values specified in the parameters.
The digest and MG cannot be changed and the salt length cannot be set to a
value less than the minimum restriction.
=back
=head1 DSA ALGORITHM
The DSA algorithm supports signing and verification operations only. Currently
there are no additional B<-pkeyopt> options other than B<digest>. The SHA1
digest is assumed by default.
=head1 DH ALGORITHM
The DH algorithm only supports the derivation operation and no additional
B<-pkeyopt> options.
=head1 EC ALGORITHM
The EC algorithm supports sign, verify and derive operations. The sign and
verify operations use ECDSA and derive uses ECDH. SHA1 is assumed by default for
the B<-pkeyopt> B<digest> option.
=head1 X25519 AND X448 ALGORITHMS
The X25519 and X448 algorithms support key derivation only. Currently there are
no additional options.
=head1 ED25519 AND ED448 ALGORITHMS
These algorithms only support signing and verifying. OpenSSL only implements the
"pure" variants of these algorithms so raw data can be passed directly to them
without hashing them first. The option B<-rawin> must be used with these
algorithms with no B<-digest> specified. Additionally OpenSSL only supports
"oneshot" operation with these algorithms. This means that the entire file to
be signed/verified must be read into memory before processing it. Signing or
Verifying very large files should be avoided. Additionally the size of the file
must be known for this to work. If the size of the file cannot be determined
(for example if the input is stdin) then the sign or verify operation will fail.
=head1 SM2
The SM2 algorithm supports sign, verify, encrypt and decrypt operations. For
the sign and verify operations, SM2 requires an Distinguishing ID string to
be passed in. The following B<-pkeyopt> value is supported:
=over 4
=item B<distid:>I<string>
This sets the ID string used in SM2 sign or verify operations. While verifying
an SM2 signature, the ID string must be the same one used when signing the data.
Otherwise the verification will fail.
=item B<hexdistid:>I<hex_string>
This sets the ID string used in SM2 sign or verify operations. While verifying
an SM2 signature, the ID string must be the same one used when signing the data.
Otherwise the verification will fail. The ID string provided with this option
should be a valid hexadecimal value.
=back
=head1 EXAMPLES
Sign some data using a private key:
openssl pkeyutl -sign -in file -inkey key.pem -out sig
Recover the signed data (e.g. if an RSA key is used):
openssl pkeyutl -verifyrecover -in sig -inkey key.pem
Verify the signature (e.g. a DSA key):
openssl pkeyutl -verify -in file -sigfile sig -inkey key.pem
Sign data using a message digest value (this is currently only valid for RSA):
openssl pkeyutl -sign -in file -inkey key.pem -out sig -pkeyopt digest:sha256
Derive a shared secret value:
openssl pkeyutl -derive -inkey key.pem -peerkey pubkey.pem -out secret
Hexdump 48 bytes of TLS1 PRF using digest B<SHA256> and shared secret and
seed consisting of the single byte 0xFF:
openssl pkeyutl -kdf TLS1-PRF -kdflen 48 -pkeyopt md:SHA256 \
-pkeyopt hexsecret:ff -pkeyopt hexseed:ff -hexdump
Derive a key using B<scrypt> where the password is read from command line:
openssl pkeyutl -kdf scrypt -kdflen 16 -pkeyopt_passin pass \
-pkeyopt hexsalt:aabbcc -pkeyopt N:16384 -pkeyopt r:8 -pkeyopt p:1
Derive using the same algorithm, but read key from environment variable MYPASS:
openssl pkeyutl -kdf scrypt -kdflen 16 -pkeyopt_passin pass:env:MYPASS \
-pkeyopt hexsalt:aabbcc -pkeyopt N:16384 -pkeyopt r:8 -pkeyopt p:1
Sign some data using an L<SM2(7)> private key and a specific ID:
openssl pkeyutl -sign -in file -inkey sm2.key -out sig -rawin -digest sm3 \
-pkeyopt distid:someid
Verify some data using an L<SM2(7)> certificate and a specific ID:
openssl pkeyutl -verify -certin -in file -inkey sm2.cert -sigfile sig \
-rawin -digest sm3 -pkeyopt distid:someid
Decrypt some data using a private key with OAEP padding using SHA256:
openssl pkeyutl -decrypt -in file -inkey key.pem -out secret \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
=head1 SEE ALSO
L<openssl(1)>,
L<openssl-genpkey(1)>,
L<openssl-pkey(1)>,
L<openssl-rsautl(1)>
L<openssl-dgst(1)>,
L<openssl-rsa(1)>,
L<openssl-genrsa(1)>,
L<openssl-kdf(1)>
L<EVP_PKEY_CTX_set_hkdf_md(3)>,
L<EVP_PKEY_CTX_set_tls1_prf_md(3)>,
=head1 HISTORY
The B<-engine> option was deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-req.pod.in b/crypto/openssl/doc/man1/openssl-req.pod.in
index a56f548de8ee..7ba599b54a06 100644
--- a/crypto/openssl/doc/man1/openssl-req.pod.in
+++ b/crypto/openssl/doc/man1/openssl-req.pod.in
@@ -1,788 +1,788 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-req - PKCS#10 certificate request and certificate generating command
=head1 SYNOPSIS
B<openssl> B<req>
[B<-help>]
[B<-inform> B<DER>|B<PEM>]
[B<-outform> B<DER>|B<PEM>]
[B<-in> I<filename>]
[B<-passin> I<arg>]
[B<-out> I<filename>]
[B<-passout> I<arg>]
[B<-text>]
[B<-pubkey>]
[B<-noout>]
[B<-verify>]
[B<-modulus>]
[B<-new>]
[B<-newkey> I<arg>]
[B<-pkeyopt> I<opt>:I<value>]
[B<-noenc>]
[B<-nodes>]
[B<-key> I<filename>|I<uri>]
[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
[B<-keyout> I<filename>]
[B<-keygen_engine> I<id>]
[B<-I<digest>>]
[B<-config> I<filename>]
[B<-section> I<name>]
[B<-x509>]
[B<-CA> I<filename>|I<uri>]
[B<-CAkey> I<filename>|I<uri>]
[B<-days> I<n>]
[B<-set_serial> I<n>]
[B<-newhdr>]
[B<-copy_extensions> I<arg>]
[B<-addext> I<ext>]
[B<-extensions> I<section>]
[B<-reqexts> I<section>]
[B<-precert>]
[B<-utf8>]
[B<-reqopt>]
[B<-subject>]
[B<-subj> I<arg>]
[B<-multivalue-rdn>]
[B<-sigopt> I<nm>:I<v>]
[B<-vfyopt> I<nm>:I<v>]
[B<-batch>]
[B<-verbose>]
{- $OpenSSL::safe::opt_name_synopsis -}
{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
=head1 DESCRIPTION
This command primarily creates and processes certificate requests (CSRs)
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> B<DER>|B<PEM>, B<-outform> B<DER>|B<PEM>
The input and output formats; unspecified by default.
See L<openssl-format-options(1)> for details.
The data is a PKCS#10 object.
=item B<-in> I<filename>
This specifies the input filename to read a request from.
This defaults to standard input unless B<-x509> or B<-CA> is specified.
A request is only read if the creation options
(B<-new> or B<-newkey> or B<-precert>) are not specified.
=item B<-sigopt> I<nm>:I<v>
Pass options to the signature algorithm during sign operations.
Names and values of these options are algorithm-specific.
=item B<-vfyopt> I<nm>:I<v>
Pass options to the signature algorithm during verify operations.
Names and values of these options are algorithm-specific.
=begin comment
Maybe it would be preferable to only have -opts instead of -sigopt and
-vfyopt? They are both present here to be compatible with L<openssl-ca(1)>,
which supports both options for good reasons.
=end comment
=item B<-passin> I<arg>
The password source for private key and certificate input.
For more information about the format of B<arg>
see L<openssl-passphrase-options(1)>.
=item B<-passout> I<arg>
The password source for the output file.
For more information about the format of B<arg>
see L<openssl-passphrase-options(1)>.
=item B<-out> I<filename>
This specifies the output filename to write to or standard output by default.
=item B<-text>
Prints out the certificate request in text form.
=item B<-subject>
Prints out the certificate request subject
(or certificate subject if B<-x509> is in use).
=item B<-pubkey>
Prints out the public key.
=item B<-noout>
This option prevents output of the encoded version of the certificate request.
=item B<-modulus>
Prints out the value of the modulus of the public key contained in the request.
=item B<-verify>
Verifies the self-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 given it will generate a new private key
using information specified in the configuration file or given with
the B<-newkey> and B<-pkeyopt> options,
else by default an RSA key with 2048 bits length.
=item B<-newkey> I<arg>
This option is used to generate a new private key unless B<-key> is given.
It is subsequently used as if it was given using the B<-key> option.
This option implies the B<-new> flag to create a new certificate request
or a new certificate in case B<-x509> is given.
The argument takes one of several forms.
[B<rsa:>]I<nbits> generates an RSA key I<nbits> in size.
If I<nbits> is omitted, i.e., B<-newkey> B<rsa> is specified,
the default key size specified in the configuration file
with the B<default_bits> option is used if present, else 2048.
All other algorithms support the B<-newkey> I<algname>:I<file> form, where
I<file> is an algorithm parameter file, created with C<openssl genpkey -genparam>
or an X.509 certificate for a key with appropriate algorithm.
B<param:>I<file> generates a key using the parameter file or certificate
I<file>, the algorithm is determined by the parameters.
I<algname>[:I<file>] generates a key using the given algorithm I<algname>.
If a parameter file I<file> is given then the parameters specified there
are used, where the algorithm parameters must match I<algname>.
If algorithm parameters are not given,
any necessary parameters should be specified via the B<-pkeyopt> option.
B<dsa:>I<filename> generates a DSA key using the parameters
in the file I<filename>. B<ec:>I<filename> generates EC key (usable both with
ECDSA or ECDH algorithms), B<gost2001:>I<filename> generates GOST R
34.10-2001 key (requires B<gost> engine configured in the configuration
file). If just B<gost2001> is specified a parameter set should be
specified by B<-pkeyopt> I<paramset:X>
=item B<-pkeyopt> I<opt>:I<value>
Set the public key algorithm option I<opt> to I<value>. The precise set of
options supported depends on the public key algorithm used and its
implementation.
See L<openssl-genpkey(1)/KEY GENERATION OPTIONS> for more details.
=item B<-key> I<filename>|I<uri>
This option provides the private key for signing a new certificate or
certificate request.
Unless B<-in> is given, the corresponding public key is placed in
the new certificate or certificate request, resulting in a self-signature.
For certificate signing this option is overridden by the B<-CA> option.
This option also accepts PKCS#8 format private keys for PEM format files.
=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The format of the private key; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-keyout> I<filename>
This gives the filename to write any private key to that has been newly created
or read from B<-key>. If neither the B<-keyout> option nor the B<-key> option
are given then the filename specified in the configuration file with the
B<default_keyfile> option is used, if present. Thus, if you want to write the
private key and the B<-key> option is provided, you should provide the
B<-keyout> option explicitly. If a new key is generated and no filename is
specified the key is written to standard output.
=item B<-noenc>
If this option is specified then if a private key is created it
will not be encrypted.
=item B<-nodes>
This option is deprecated since OpenSSL 3.0; use B<-noenc> instead.
=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> I<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<-section> I<name>
Specifies the name of the section to use; the default is B<req>.
=item B<-subj> I<arg>
Sets subject name for new request or supersedes the subject name
when processing a certificate request.
The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
Special characters may be escaped by C<\> (backslash), whitespace is retained.
Empty values are permitted, but the corresponding type will not be included
in the request.
Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
between the AttributeValueAssertions (AVAs) that specify the members of the set.
Example:
C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
=item B<-multivalue-rdn>
This option has been deprecated and has no effect.
=item B<-x509>
This option outputs a certificate instead of a certificate request.
This is typically used to generate test certificates.
It is implied by the B<-CA> option.
This option implies the B<-new> flag if B<-in> is not given.
If an existing request is specified with the B<-in> option, it is converted
to a certificate; otherwise a request is created from scratch.
Unless specified using the B<-set_serial> option,
a large random number will be used for the serial number.
Unless the B<-copy_extensions> option is used,
X.509 extensions are not copied from any provided request input file.
X.509 extensions to be added can be specified in the configuration file
or using the B<-addext> option.
=item B<-CA> I<filename>|I<uri>
Specifies the "CA" certificate to be used for signing a new certificate
and implies use of B<-x509>.
When present, this behaves like a "micro CA" as follows:
The subject name of the "CA" certificate is placed as issuer name in the new
certificate, which is then signed using the "CA" key given as specified below.
=item B<-CAkey> I<filename>|I<uri>
Sets the "CA" private key to sign a certificate with.
The private key must match the public key of the certificate given with B<-CA>.
If this option is not provided then the key must be present in the B<-CA> input.
=item B<-days> I<n>
When B<-x509> is in use this specifies the number of
days to certify the certificate for, otherwise it is ignored. I<n> should
be a positive integer. The default is 30 days.
=item B<-set_serial> I<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 C<0x>.
If not given, a large random number will be used.
=item B<-copy_extensions> I<arg>
Determines how X.509 extensions in certificate requests should be handled
when B<-x509> is in use.
If I<arg> is B<none> or this option is not present then extensions are ignored.
If I<arg> is B<copy> or B<copyall> then
all extensions in the request are copied to the certificate.
The main use of this option is to allow a certificate request to supply
values for certain extensions such as subjectAltName.
=item B<-addext> I<ext>
Add a specific extension to the certificate (if B<-x509> is in use)
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> I<section>
=item B<-reqexts> I<section>
These options specify alternative sections to include certificate
extensions (if B<-x509> is in use) 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<-reqopt> I<option>
Customise the printing format used with B<-text>. The I<option> argument can be
a single option or multiple options separated by commas.
See discussion of the B<-certopt> parameter in the L<openssl-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<-keygen_engine> I<id>
Specifies an engine (by its unique I<id> string) which would be used
for key generation operations.
{- $OpenSSL::safe::opt_name_item -}
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_engine_item -}
{- $OpenSSL::safe::opt_provider_item -}
=back
=head1 CONFIGURATION FILE FORMAT
The configuration options are specified in the B<req> section of
the configuration file. An alternate name be specified by using the
B<-section> option.
As with all configuration files, if no
value is specified in the specific section 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>, B<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 whitespace then the short name followed
by whitespace 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<-noenc> 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:
=over 4
=item B<utf8only>
- only UTF8Strings are used (this is the default value)
=item B<pkix>
- any string type except T61Strings
=item B<nombstr>
- any string type except BMPStrings and UTF8Strings
=item B<default>
- any kind of string type
=back
Note that B<utf8only> is the PKIX recommendation in RFC2459 after 2003, and the
default B<string_mask>; B<default> is not the default option. The B<nombstr>
value is a workaround for some software that has problems with variable-sized
BMPStrings and UTF8Strings.
=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 B<-x509> is in use.
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 this command. 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 included 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
Create an SM2 private key and then generate a certificate request from it:
openssl ecparam -genkey -name SM2 -out sm2.key
openssl req -new -key sm2.key -out sm2.csr -sm3 -sigopt "distid:1234567812345678"
Examine and verify an SM2 certificate request:
openssl req -verify -in sm2.csr -sm3 -vfyopt "distid:1234567812345678"
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
+ dirstring_type = nombstr
[ 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:
[ 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 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 B<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<openssl(1)>,
L<openssl-x509(1)>,
L<openssl-ca(1)>,
L<openssl-genrsa(1)>,
L<openssl-gendsa(1)>,
L<config(5)>,
L<x509v3_config(5)>
=head1 HISTORY
The B<-section> option was added in OpenSSL 3.0.0.
The B<-multivalue-rdn> option has become obsolete in OpenSSL 3.0.0 and
has no effect.
The B<-engine> option was deprecated in OpenSSL 3.0.
The <-nodes> option was deprecated in OpenSSL 3.0, too; use B<-noenc> instead.
=head1 COPYRIGHT
-Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-s_client.pod.in b/crypto/openssl/doc/man1/openssl-s_client.pod.in
index bd6171aa265c..caebe10bffb8 100644
--- a/crypto/openssl/doc/man1/openssl-s_client.pod.in
+++ b/crypto/openssl/doc/man1/openssl-s_client.pod.in
@@ -1,924 +1,981 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-s_client - SSL/TLS client program
=head1 SYNOPSIS
B<openssl> B<s_client>
[B<-help>]
[B<-ssl_config> I<section>]
-[B<-connect> I<host:port>]
+[B<-connect> I<host>:I<port>]
[B<-host> I<hostname>]
[B<-port> I<port>]
-[B<-bind> I<host:port>]
-[B<-proxy> I<host:port>]
+[B<-bind> I<host>:I<port>]
+[B<-proxy> I<host>:I<port>]
[B<-proxy_user> I<userid>]
[B<-proxy_pass> I<arg>]
[B<-unix> I<path>]
[B<-4>]
[B<-6>]
[B<-servername> I<name>]
[B<-noservername>]
[B<-verify> I<depth>]
[B<-verify_return_error>]
[B<-verify_quiet>]
[B<-verifyCAfile> I<filename>]
[B<-verifyCApath> I<dir>]
[B<-verifyCAstore> I<uri>]
[B<-cert> I<filename>]
[B<-certform> B<DER>|B<PEM>|B<P12>]
[B<-cert_chain> I<filename>]
[B<-build_chain>]
[B<-CRL> I<filename>]
[B<-CRLform> B<DER>|B<PEM>]
[B<-crl_download>]
[B<-key> I<filename>|I<uri>]
[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
[B<-pass> I<arg>]
[B<-chainCAfile> I<filename>]
[B<-chainCApath> I<directory>]
[B<-chainCAstore> I<uri>]
[B<-requestCAfile> I<filename>]
[B<-dane_tlsa_domain> I<domain>]
[B<-dane_tlsa_rrdata> I<rrdata>]
[B<-dane_ee_no_namechecks>]
[B<-reconnect>]
[B<-showcerts>]
[B<-prexit>]
[B<-debug>]
[B<-trace>]
[B<-nocommands>]
[B<-security_debug>]
[B<-security_debug_verbose>]
[B<-msg>]
[B<-timeout>]
[B<-mtu> I<size>]
[B<-no_etm>]
[B<-keymatexport> I<label>]
[B<-keymatexportlen> I<len>]
[B<-msgfile> I<filename>]
[B<-nbio_test>]
[B<-state>]
[B<-nbio>]
[B<-crlf>]
[B<-ign_eof>]
[B<-no_ign_eof>]
[B<-psk_identity> I<identity>]
[B<-psk> I<key>]
[B<-psk_session> I<file>]
[B<-quiet>]
[B<-sctp>]
[B<-sctp_label_bug>]
[B<-fallback_scsv>]
[B<-async>]
[B<-maxfraglen> I<len>]
[B<-max_send_frag>]
[B<-split_send_frag>]
[B<-max_pipelines>]
[B<-read_buf>]
[B<-ignore_unexpected_eof>]
[B<-bugs>]
[B<-comp>]
[B<-no_comp>]
[B<-brief>]
[B<-legacy_server_connect>]
[B<-no_legacy_server_connect>]
[B<-allow_no_dhe_kex>]
[B<-sigalgs> I<sigalglist>]
[B<-curves> I<curvelist>]
[B<-cipher> I<cipherlist>]
[B<-ciphersuites> I<val>]
[B<-serverpref>]
[B<-starttls> I<protocol>]
[B<-name> I<hostname>]
[B<-xmpphost> I<hostname>]
[B<-name> I<hostname>]
[B<-tlsextdebug>]
[B<-no_ticket>]
[B<-sess_out> I<filename>]
[B<-serverinfo> I<types>]
[B<-sess_in> I<filename>]
[B<-serverinfo> I<types>]
[B<-status>]
[B<-alpn> I<protocols>]
[B<-nextprotoneg> I<protocols>]
[B<-ct>]
[B<-noct>]
[B<-ctlogfile>]
[B<-keylogfile> I<file>]
[B<-early_data> I<file>]
[B<-enable_pha>]
[B<-use_srtp> I<value>]
[B<-srpuser> I<value>]
[B<-srppass> I<value>]
[B<-srp_lateuser>]
[B<-srp_moregroups>]
[B<-srp_strength> I<number>]
{- $OpenSSL::safe::opt_name_synopsis -}
{- $OpenSSL::safe::opt_version_synopsis -}
{- $OpenSSL::safe::opt_x_synopsis -}
{- $OpenSSL::safe::opt_trust_synopsis -}
{- $OpenSSL::safe::opt_s_synopsis -}
{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
{- $OpenSSL::safe::opt_engine_synopsis -}[B<-ssl_client_engine> I<id>]
{- $OpenSSL::safe::opt_v_synopsis -}
[I<host>:I<port>]
=head1 DESCRIPTION
This command implements a generic SSL/TLS client which
connects to a remote host using SSL/TLS. It is a I<very> useful diagnostic
tool for SSL servers.
=head1 OPTIONS
In addition to the options below, this command also supports the
common and client only options documented
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<-ssl_config> I<section>
Use the specified section of the configuration file to configure the B<SSL_CTX> object.
=item B<-connect> I<host>:I<port>
This specifies the host and optional port to connect to. It is possible to
select the host and port using the optional target positional argument instead.
If neither this nor the target positional argument are specified then an attempt
is made to connect to the local host on port 4433.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
=item B<-host> I<hostname>
Host to connect to; use B<-connect> instead.
=item B<-port> I<port>
Connect to the specified port; use B<-connect> instead.
-=item B<-bind> I<host:port>
+=item B<-bind> I<host>:I<port>
This specifies the host address and or port to bind as the source for the
connection. For Unix-domain sockets the port is ignored and the host is
used as the source socket address.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
-=item B<-proxy> I<host:port>
+=item B<-proxy> I<host>:I<port>
When used with the B<-connect> flag, the program uses the host and port
specified with this flag and issues an HTTP CONNECT command to connect
to the desired server.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
=item B<-proxy_user> I<userid>
When used with the B<-proxy> flag, the program will attempt to authenticate
with the specified proxy using basic (base64) authentication.
NB: Basic authentication is insecure; the credentials are sent to the proxy
in easily reversible base64 encoding before any TLS/SSL session is established.
Therefore, these credentials are easily recovered by anyone able to sniff/trace
the network. Use with caution.
=item B<-proxy_pass> I<arg>
The proxy password source, used with the B<-proxy_user> flag.
For more information about the format of B<arg>
see L<openssl-passphrase-options(1)>.
=item B<-unix> I<path>
Connect over the specified Unix-domain socket.
=item B<-4>
Use IPv4 only.
=item B<-6>
Use IPv6 only.
=item B<-servername> I<name>
Set the TLS SNI (Server Name Indication) extension in the ClientHello message to
the given value.
If B<-servername> is not provided, the TLS SNI extension will be populated with
the name given to B<-connect> if it follows a DNS name format. If B<-connect> is
not provided either, the SNI is set to "localhost".
This is the default since OpenSSL 1.1.1.
Even though SNI should normally be a DNS name and not an IP address, if
B<-servername> is provided then that name will be sent, regardless of whether
it is a DNS name or not.
This option cannot be used in conjunction with B<-noservername>.
=item B<-noservername>
Suppresses sending of the SNI (Server Name Indication) extension in the
ClientHello message. Cannot be used in conjunction with the B<-servername> or
B<-dane_tlsa_domain> options.
=item B<-cert> I<filename>
The client certificate to use, if one is requested by the server.
The default is not to use a certificate.
The chain for the client certificate may be specified using B<-cert_chain>.
=item B<-certform> B<DER>|B<PEM>|B<P12>
The client certificate file format to use; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-cert_chain>
A file or URI of untrusted certificates to use when attempting to build the
certificate chain related to the certificate specified via the B<-cert> option.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-build_chain>
Specify whether the application should build the client certificate chain to be
provided to the server.
=item B<-CRL> I<filename>
CRL file to use to check the server's certificate.
=item B<-CRLform> B<DER>|B<PEM>
The CRL file format; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-crl_download>
-Download CRL from distribution points in the certificate.
+Download CRL from distribution points in the certificate. Note that this option
+is ignored if B<-crl_check> option is not provided. Note that the maximum size
+of CRL is limited by L<X509_CRL_load_http(3)> function.
=item B<-key> I<filename>|I<uri>
The client private key to use.
If not specified then the certificate file will be used to read also the key.
=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The key format; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-pass> I<arg>
the private key and certificate file password source.
For more information about the format of I<arg>
see L<openssl-passphrase-options(1)>.
=item B<-verify> I<depth>
The verify depth to use. This specifies the maximum length of the
server certificate chain and turns on server certificate verification.
-Currently the verify operation continues after errors so all the problems
+Unless the B<-verify_return_error> option is given,
+the verify operation continues after errors so all the problems
with a certificate chain can be seen. As a side effect the connection
will never fail due to a server certificate verify failure.
+By default, validation of server certificates and their chain
+is done w.r.t. the (D)TLS Server (C<sslserver>) purpose.
+For details see L<openssl-verification-options(1)/Certificate Extensions>.
+
=item B<-verify_return_error>
-Return verification errors instead of continuing. This will typically
-abort the handshake with a fatal error.
+Turns on server certificate verification, like with B<-verify>,
+but returns verification errors instead of continuing.
+This will typically abort the handshake with a fatal error.
=item B<-verify_quiet>
Limit verify output to only errors.
=item B<-verifyCAfile> I<filename>
A file in PEM format containing trusted certificates to use
for verifying the server's certificate.
=item B<-verifyCApath> I<dir>
A directory containing trusted certificates to use
for verifying the server's certificate.
This directory must be in "hash format",
see L<openssl-verify(1)> for more information.
=item B<-verifyCAstore> I<uri>
The URI of a store containing trusted certificates to use
for verifying the server's certificate.
=item B<-chainCAfile> I<file>
A file in PEM format containing trusted certificates to use
when attempting to build the client certificate chain.
=item B<-chainCApath> I<directory>
A directory containing trusted certificates to use
for building the client certificate chain provided to the server.
This directory must be in "hash format",
see L<openssl-verify(1)> for more information.
=item B<-chainCAstore> I<uri>
The URI of a store containing trusted certificates to use
when attempting to build the client certificate chain.
The URI may indicate a single certificate, as well as a collection of them.
With URIs in the C<file:> scheme, this acts as B<-chainCAfile> or
B<-chainCApath>, depending on if the URI indicates a directory or a
single file.
See L<ossl_store-file(7)> for more information on the C<file:> scheme.
=item B<-requestCAfile> I<file>
A file containing a list of certificates whose subject names will be sent
to the server in the B<certificate_authorities> extension. Only supported
for TLS 1.3
=item B<-dane_tlsa_domain> I<domain>
Enable RFC6698/RFC7671 DANE TLSA authentication and specify the
TLSA base domain which becomes the default SNI hint and the primary
reference identifier for hostname checks. This must be used in
combination with at least one instance of the B<-dane_tlsa_rrdata>
option below.
When DANE authentication succeeds, the diagnostic output will include
the lowest (closest to 0) depth at which a TLSA record authenticated
a chain certificate. When that TLSA record is a "2 1 0" trust
anchor public key that signed (rather than matched) the top-most
certificate of the chain, the result is reported as "TA public key
verified". Otherwise, either the TLSA record "matched TA certificate"
at a positive depth or else "matched EE certificate" at depth 0.
=item B<-dane_tlsa_rrdata> I<rrdata>
Use one or more times to specify the RRDATA fields of the DANE TLSA
RRset associated with the target service. The I<rrdata> value is
specified in "presentation form", that is four whitespace separated
fields that specify the usage, selector, matching type and associated
data, with the last of these encoded in hexadecimal. Optional
whitespace is ignored in the associated data field. For example:
$ openssl s_client -brief -starttls smtp \
-connect smtp.example.com:25 \
-dane_tlsa_domain smtp.example.com \
-dane_tlsa_rrdata "2 1 1
B111DD8A1C2091A89BD4FD60C57F0716CCE50FEEFF8137CDBEE0326E 02CF362B" \
-dane_tlsa_rrdata "2 1 1
60B87575447DCBA2A36B7D11AC09FB24A9DB406FEE12D2CC90180517 616E8A18"
...
Verification: OK
Verified peername: smtp.example.com
DANE TLSA 2 1 1 ...ee12d2cc90180517616e8a18 matched TA certificate at depth 1
...
=item B<-dane_ee_no_namechecks>
This disables server name checks when authenticating via DANE-EE(3) TLSA
records.
For some applications, primarily web browsers, it is not safe to disable name
checks due to "unknown key share" attacks, in which a malicious server can
convince a client that a connection to a victim server is instead a secure
connection to the malicious server.
The malicious server may then be able to violate cross-origin scripting
restrictions.
Thus, despite the text of RFC7671, name checks are by default enabled for
DANE-EE(3) TLSA records, and can be disabled in applications where it is safe
to do so.
In particular, SMTP and XMPP clients should set this option as SRV and MX
records already make it possible for a remote domain to redirect client
connections to any server of its choice, and in any case SMTP and XMPP clients
do not execute scripts downloaded from remote servers.
=item B<-reconnect>
Reconnects to the same server 5 times using the same session ID, this can
be used as a test that session caching is working.
=item B<-showcerts>
Displays the server certificate list as sent by the server: it only consists of
certificates the server has sent (in the order the server has sent them). It is
B<not> a verified chain.
=item B<-prexit>
Print session information when the program exits. This will always attempt
to print out information even if the connection fails. Normally information
will only be printed out once if the connection succeeds. This option is useful
because the cipher in use may be renegotiated or the connection may fail
because a client certificate is required or is requested only after an
attempt is made to access a certain URL. Note: the output produced by this
option is not always accurate because a connection might never have been
established.
=item B<-state>
Prints out the SSL session states.
=item B<-debug>
Print extensive debugging information including a hex dump of all traffic.
=item B<-nocommands>
Do not use interactive command letters.
=item B<-security_debug>
Enable security debug messages.
=item B<-security_debug_verbose>
Output more security debug output.
=item B<-msg>
Show protocol messages.
=item B<-timeout>
Enable send/receive timeout on DTLS connections.
=item B<-mtu> I<size>
Set MTU of the link layer to the specified size.
=item B<-no_etm>
Disable Encrypt-then-MAC negotiation.
=item B<-keymatexport> I<label>
Export keying material using the specified label.
=item B<-keymatexportlen> I<len>
Export the specified number of bytes of keying material; default is 20.
Show all protocol messages with hex dump.
=item B<-trace>
Show verbose trace output of protocol messages.
=item B<-msgfile> I<filename>
File to send output of B<-msg> or B<-trace> to, default standard output.
=item B<-nbio_test>
Tests nonblocking I/O
=item B<-nbio>
Turns on nonblocking I/O
=item B<-crlf>
This option translated a line feed from the terminal into CR+LF as required
by some servers.
=item B<-ign_eof>
Inhibit shutting down the connection when end of file is reached in the
input.
=item B<-quiet>
Inhibit printing of session and certificate information. This implicitly
turns on B<-ign_eof> as well.
=item B<-no_ign_eof>
Shut down the connection when end of file is reached in the input.
Can be used to override the implicit B<-ign_eof> after B<-quiet>.
=item B<-psk_identity> I<identity>
Use the PSK identity I<identity> when using a PSK cipher suite.
The default value is "Client_identity" (without the quotes).
=item B<-psk> I<key>
Use the PSK key I<key> when using a PSK cipher suite. The key is
given as a hexadecimal number without leading 0x, for example -psk
1a2b3c4d.
This option must be provided in order to use a PSK cipher.
=item B<-psk_session> I<file>
Use the pem encoded SSL_SESSION data stored in I<file> as the basis of a PSK.
Note that this will only work if TLSv1.3 is negotiated.
=item B<-sctp>
Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
available where OpenSSL has support for SCTP enabled.
=item B<-sctp_label_bug>
Use the incorrect behaviour of older OpenSSL implementations when computing
endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
older broken implementations but breaks interoperability with correct
implementations. Must be used in conjunction with B<-sctp>. This option is only
available where OpenSSL has support for SCTP enabled.
=item B<-fallback_scsv>
Send TLS_FALLBACK_SCSV in the ClientHello.
=item B<-async>
Switch on asynchronous mode. Cryptographic operations will be performed
asynchronously. This will only have an effect if an asynchronous capable engine
is also used via the B<-engine> option. For test purposes the dummy async engine
(dasync) can be used (if available).
=item B<-maxfraglen> I<len>
Enable Maximum Fragment Length Negotiation; allowed values are
C<512>, C<1024>, C<2048>, and C<4096>.
=item B<-max_send_frag> I<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> I<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> I<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> I<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<-ignore_unexpected_eof>
Some TLS implementations do not send the mandatory close_notify alert on
shutdown. If the application tries to wait for the close_notify alert but the
peer closes the connection without sending it, an error is generated. When this
option is enabled the peer does not need to send the close_notify alert and a
closed connection will be treated as if the close_notify alert was received.
For more information on shutting down a connection, see L<SSL_shutdown(3)>.
=item B<-bugs>
There are several known bugs in SSL and TLS implementations. Adding this
option enables various workarounds.
=item B<-comp>
Enables support for SSL/TLS compression.
This option was introduced in OpenSSL 1.1.0.
TLS compression is not recommended and is off by default as of
OpenSSL 1.1.0.
=item B<-no_comp>
Disables support for SSL/TLS compression.
TLS compression is not recommended and is off by default as of
OpenSSL 1.1.0.
=item B<-brief>
Only provide a brief summary of connection parameters instead of the
normal verbose output.
=item B<-sigalgs> I<sigalglist>
Specifies the list of signature algorithms that are sent by the client.
The server selects one entry in the list based on its preferences.
For example strings, see L<SSL_CTX_set1_sigalgs(3)>
=item B<-curves> I<curvelist>
Specifies the list of supported curves to be sent by the client. The curve is
ultimately selected by the server.
The list of all supported groups includes named EC parameters as well as X25519
and X448 or FFDHE groups, and may also include groups implemented in 3rd-party
providers. For a list of named EC parameters, use:
$ openssl ecparam -list_curves
=item B<-cipher> I<cipherlist>
This allows the TLSv1.2 and below cipher list sent by the client to be modified.
This list will be combined with any TLSv1.3 ciphersuites that have been
configured. Although the server determines which ciphersuite is used it should
take the first supported cipher in the list sent by the client. See
L<openssl-ciphers(1)> for more information.
=item B<-ciphersuites> I<val>
This allows the TLSv1.3 ciphersuites sent by the client to be modified. This
list will be combined with any TLSv1.2 and below ciphersuites that have been
configured. Although the server determines which cipher suite is used it should
take the first supported cipher in the list sent by the client. See
L<openssl-ciphers(1)> for more information. The format for this list is a simple
colon (":") separated list of TLSv1.3 ciphersuite names.
=item B<-starttls> I<protocol>
Send the protocol-specific message(s) to switch to TLS for communication.
I<protocol> is a keyword for the intended protocol. Currently, the only
supported keywords are "smtp", "pop3", "imap", "ftp", "xmpp", "xmpp-server",
"irc", "postgres", "mysql", "lmtp", "nntp", "sieve" and "ldap".
=item B<-xmpphost> I<hostname>
This option, when used with "-starttls xmpp" or "-starttls xmpp-server",
specifies the host for the "to" attribute of the stream element.
If this option is not specified, then the host specified with "-connect"
will be used.
This option is an alias of the B<-name> option for "xmpp" and "xmpp-server".
=item B<-name> I<hostname>
This option is used to specify hostname information for various protocols
used with B<-starttls> option. Currently only "xmpp", "xmpp-server",
"smtp" and "lmtp" can utilize this B<-name> option.
If this option is used with "-starttls xmpp" or "-starttls xmpp-server",
if specifies the host for the "to" attribute of the stream element. If this
option is not specified, then the host specified with "-connect" will be used.
If this option is used with "-starttls lmtp" or "-starttls smtp", it specifies
the name to use in the "LMTP LHLO" or "SMTP EHLO" message, respectively. If
this option is not specified, then "mail.example.com" will be used.
=item B<-tlsextdebug>
Print out a hex dump of any TLS extensions received from the server.
=item B<-no_ticket>
Disable RFC4507bis session ticket support.
=item B<-sess_out> I<filename>
Output SSL session to I<filename>.
=item B<-sess_in> I<filename>
Load SSL session from I<filename>. The client will attempt to resume a
connection from this session.
=item B<-serverinfo> I<types>
A list of comma-separated TLS Extension Types (numbers between 0 and
65535). Each type will be sent as an empty ClientHello TLS Extension.
The server's response (if any) will be encoded and displayed as a PEM
file.
=item B<-status>
Sends a certificate status request to the server (OCSP stapling). The server
response (if any) is printed out.
=item B<-alpn> I<protocols>, B<-nextprotoneg> I<protocols>
These flags enable the Enable the Application-Layer Protocol Negotiation
or Next Protocol Negotiation (NPN) extension, respectively. ALPN is the
IETF standard and replaces NPN.
The I<protocols> list is a comma-separated list of protocol names that
the client should advertise support for. The list should contain the most
desirable protocols first. Protocol names are printable ASCII strings,
for example "http/1.1" or "spdy/3".
An empty list of protocols is treated specially and will cause the
client to advertise support for the TLS extension but disconnect just
after receiving ServerHello with a list of server supported protocols.
The flag B<-nextprotoneg> cannot be specified if B<-tls1_3> is used.
=item B<-ct>, B<-noct>
Use one of these two options to control whether Certificate Transparency (CT)
is enabled (B<-ct>) or disabled (B<-noct>).
If CT is enabled, signed certificate timestamps (SCTs) will be requested from
the server and reported at handshake completion.
Enabling CT also enables OCSP stapling, as this is one possible delivery method
for SCTs.
=item B<-ctlogfile>
A file containing a list of known Certificate Transparency logs. See
L<SSL_CTX_set_ctlog_list_file(3)> for the expected file format.
=item B<-keylogfile> I<file>
Appends TLS secrets to the specified keylog file such that external programs
(like Wireshark) can decrypt TLS connections.
=item B<-early_data> I<file>
Reads the contents of the specified file and attempts to send it as early data
to the server. This will only work with resumed sessions that support early
data and when the server accepts the early data.
=item B<-enable_pha>
For TLSv1.3 only, send the Post-Handshake Authentication extension. This will
happen whether or not a certificate has been provided via B<-cert>.
=item B<-use_srtp> I<value>
Offer SRTP key management, where B<value> is a colon-separated profile list.
=item B<-srpuser> I<value>
Set the SRP username to the specified value. This option is deprecated.
=item B<-srppass> I<value>
Set the SRP password to the specified value. This option is deprecated.
=item B<-srp_lateuser>
SRP username for the second ClientHello message. This option is deprecated.
=item B<-srp_moregroups> This option is deprecated.
Tolerate other than the known B<g> and B<N> values.
=item B<-srp_strength> I<number>
Set the minimal acceptable length, in bits, for B<N>. This option is
deprecated.
{- $OpenSSL::safe::opt_version_item -}
{- $OpenSSL::safe::opt_name_item -}
{- $OpenSSL::safe::opt_x_item -}
{- $OpenSSL::safe::opt_trust_item -}
{- $OpenSSL::safe::opt_s_item -}
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_provider_item -}
{- $OpenSSL::safe::opt_engine_item -}
{- output_off() if $disabled{"deprecated-3.0"}; "" -}
=item B<-ssl_client_engine> I<id>
Specify engine to be used for client certificate operations.
{- output_on() if $disabled{"deprecated-3.0"}; "" -}
{- $OpenSSL::safe::opt_v_item -}
Verification errors are displayed, for debugging, but the command will
proceed unless the B<-verify_return_error> option is used.
=item I<host>:I<port>
-Rather than providing B<-connect>, the target hostname and optional port may
+Rather than providing B<-connect>, the target host and optional port may
be provided as a single positional argument after all options. If neither this
nor B<-connect> are provided, falls back to attempting to connect to
I<localhost> on port I<4433>.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
=back
=head1 CONNECTED COMMANDS
If a connection is established with an SSL server then any data received
from the server is displayed and any key presses will be sent to the
server. If end of file is reached then the connection will be closed down. When
used interactively (which means neither B<-quiet> nor B<-ign_eof> have been
given), then certain commands are also recognized which perform special
operations. These commands are a letter which must appear at the start of a
line. They are listed below.
=over 4
=item B<Q>
End the current SSL connection and exit.
=item B<R>
Renegotiate the SSL session (TLSv1.2 and below only).
=item B<k>
Send a key update message to the server (TLSv1.3 only)
=item B<K>
Send a key update message to the server and request one back (TLSv1.3 only)
=back
=head1 NOTES
This command can be used to debug SSL servers. To connect to an SSL HTTP
server the command:
openssl s_client -connect servername:443
would typically be used (https uses port 443). If the connection succeeds
then an HTTP command can be given such as "GET /" to retrieve a web page.
If the handshake fails then there are several possible causes, if it is
nothing obvious like no client certificate then the B<-bugs>,
B<-ssl3>, B<-tls1>, B<-no_ssl3>, B<-no_tls1> options can be tried
in case it is a buggy server. In particular you should play with these
options B<before> submitting a bug report to an OpenSSL mailing list.
A frequent problem when attempting to get client certificates working
is that a web client complains it has no certificates or gives an empty
list to choose from. This is normally because the server is not sending
the clients certificate authority in its "acceptable CA list" when it
requests a certificate. By using this command, the CA list can be viewed
and checked. However, some servers only request client authentication
after a specific URL is requested. To obtain the list in this case it
is necessary to use the B<-prexit> option and send an HTTP request
for an appropriate page.
If a certificate is specified on the command line using the B<-cert>
option it will not be used unless the server specifically requests
a client certificate. Therefore, merely including a client certificate
on the command line is no guarantee that the certificate works.
If there are problems verifying a server certificate then the
B<-showcerts> option can be used to show all the certificates sent by the
server.
This command is a test tool and is designed to continue the
handshake after any certificate verification errors. As a result it will
accept any certificate chain (trusted or not) sent by the peer. Non-test
applications should B<not> do this as it makes them vulnerable to a MITM
attack. This behaviour can be changed by with the B<-verify_return_error>
option: any verify errors are then returned aborting the handshake.
The B<-bind> option may be useful if the server or a firewall requires
connections to come from some particular address and or port.
+=head2 Note on Non-Interactive Use
+
+When B<s_client> is run in a non-interactive environment (e.g., a cron job or
+a script without a valid I<stdin>), it may close the connection prematurely,
+especially with TLS 1.3. To prevent this, you can use the B<-ign_eof> flag,
+which keeps B<s_client> running even after reaching EOF from I<stdin>.
+
+For example:
+
+ openssl s_client -connect <server address>:443 -tls1_3
+ -sess_out /path/to/tls_session_params_file
+ -ign_eof </dev/null
+
+However, relying solely on B<-ign_eof> can lead to issues if the server keeps
+the connection open, expecting the client to close first. In such cases, the
+client may hang indefinitely. This behavior is not uncommon, particularly with
+protocols where the server waits for a graceful disconnect from the client.
+
+For example, when connecting to an SMTP server, the session may pause if the
+server expects a QUIT command before closing:
+
+ $ openssl s_client -brief -ign_eof -starttls smtp
+ -connect <server address>:25 </dev/null
+ CONNECTION ESTABLISHED
+ Protocol version: TLSv1.3
+ Ciphersuite: TLS_AES_256_GCM_SHA384
+ ...
+ 250 CHUNKING
+ [long pause]
+
+To avoid such hangs, it's better to use an application-level command to
+initiate a clean disconnect. For SMTP, you can send a QUIT command:
+
+ printf 'QUIT\r\n' | openssl s_client -connect <server address>:25
+ -starttls smtp -brief -ign_eof
+
+Similarly, for HTTP/1.1 connections, including a `Connection: close` header
+ensures the server closes the connection after responding:
+
+ printf 'GET / HTTP/1.1\r\nHost: <server address>\r\nConnection: close\r\n\r\n'
+ | openssl s_client -connect <server address>:443 -brief
+
+These approaches help manage the connection closure gracefully and prevent
+hangs caused by the server waiting for the client to initiate the disconnect.
+
=head1 BUGS
Because this program has a lot of options and also because some of the
techniques used are rather old, the C source for this command is rather
hard to read and not a model of how things should be done.
A typical SSL client program would be much simpler.
The B<-prexit> option is a bit of a hack. We should really report
information whenever a session is renegotiated.
=head1 SEE ALSO
L<openssl(1)>,
L<openssl-sess_id(1)>,
L<openssl-s_server(1)>,
L<openssl-ciphers(1)>,
L<SSL_CONF_cmd(3)>,
L<SSL_CTX_set_max_send_fragment(3)>,
L<SSL_CTX_set_split_send_fragment(3)>,
L<SSL_CTX_set_max_pipelines(3)>,
L<ossl_store-file(7)>
=head1 HISTORY
The B<-no_alt_chains> option was added in OpenSSL 1.1.0.
The B<-name> option was added in OpenSSL 1.1.1.
The B<-certform> option has become obsolete in OpenSSL 3.0.0 and has no effect.
The B<-engine> option was deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-s_server.pod.in b/crypto/openssl/doc/man1/openssl-s_server.pod.in
index 99a252a82254..f0825ad33d1f 100644
--- a/crypto/openssl/doc/man1/openssl-s_server.pod.in
+++ b/crypto/openssl/doc/man1/openssl-s_server.pod.in
@@ -1,943 +1,948 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-s_server - SSL/TLS server program
=head1 SYNOPSIS
B<openssl> B<s_server>
[B<-help>]
[B<-port> I<+int>]
[B<-accept> I<val>]
[B<-unix> I<val>]
[B<-4>]
[B<-6>]
[B<-unlink>]
[B<-context> I<val>]
[B<-verify> I<int>]
[B<-Verify> I<int>]
[B<-cert> I<infile>]
[B<-cert2> I<infile>]
[B<-certform> B<DER>|B<PEM>|B<P12>]
[B<-cert_chain> I<infile>]
[B<-build_chain>]
[B<-serverinfo> I<val>]
[B<-key> I<filename>|I<uri>]
[B<-key2> I<filename>|I<uri>]
[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
[B<-pass> I<val>]
[B<-dcert> I<infile>]
[B<-dcertform> B<DER>|B<PEM>|B<P12>]
[B<-dcert_chain> I<infile>]
[B<-dkey> I<filename>|I<uri>]
[B<-dkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
[B<-dpass> I<val>]
[B<-nbio_test>]
[B<-crlf>]
[B<-debug>]
[B<-msg>]
[B<-msgfile> I<outfile>]
[B<-state>]
[B<-nocert>]
[B<-quiet>]
[B<-no_resume_ephemeral>]
[B<-www>]
[B<-WWW>]
[B<-http_server_binmode>]
[B<-no_ca_names>]
[B<-ignore_unexpected_eof>]
[B<-servername>]
[B<-servername_fatal>]
[B<-tlsextdebug>]
[B<-HTTP>]
[B<-id_prefix> I<val>]
[B<-keymatexport> I<val>]
[B<-keymatexportlen> I<+int>]
[B<-CRL> I<infile>]
[B<-CRLform> B<DER>|B<PEM>]
[B<-crl_download>]
[B<-chainCAfile> I<infile>]
[B<-chainCApath> I<dir>]
[B<-chainCAstore> I<uri>]
[B<-verifyCAfile> I<infile>]
[B<-verifyCApath> I<dir>]
[B<-verifyCAstore> I<uri>]
[B<-no_cache>]
[B<-ext_cache>]
[B<-verify_return_error>]
[B<-verify_quiet>]
[B<-ign_eof>]
[B<-no_ign_eof>]
[B<-no_etm>]
[B<-status>]
[B<-status_verbose>]
[B<-status_timeout> I<int>]
-[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path]>]
+[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>]
[B<-no_proxy> I<addresses>]
[B<-status_url> I<val>]
[B<-status_file> I<infile>]
[B<-ssl_config> I<val>]
[B<-trace>]
[B<-security_debug>]
[B<-security_debug_verbose>]
[B<-brief>]
[B<-rev>]
[B<-async>]
[B<-max_send_frag> I<+int>]
[B<-split_send_frag> I<+int>]
[B<-max_pipelines> I<+int>]
[B<-naccept> I<+int>]
[B<-read_buf> I<+int>]
[B<-bugs>]
[B<-no_comp>]
[B<-comp>]
[B<-no_ticket>]
[B<-serverpref>]
[B<-legacy_renegotiation>]
[B<-no_renegotiation>]
[B<-no_resumption_on_reneg>]
[B<-allow_no_dhe_kex>]
[B<-prioritize_chacha>]
[B<-strict>]
[B<-sigalgs> I<val>]
[B<-client_sigalgs> I<val>]
[B<-groups> I<val>]
[B<-curves> I<val>]
[B<-named_curve> I<val>]
[B<-cipher> I<val>]
[B<-ciphersuites> I<val>]
[B<-dhparam> I<infile>]
[B<-record_padding> I<val>]
[B<-debug_broken_protocol>]
[B<-nbio>]
[B<-psk_identity> I<val>]
[B<-psk_hint> I<val>]
[B<-psk> I<val>]
[B<-psk_session> I<file>]
[B<-srpvfile> I<infile>]
[B<-srpuserseed> I<val>]
[B<-timeout>]
[B<-mtu> I<+int>]
[B<-listen>]
[B<-sctp>]
[B<-sctp_label_bug>]
[B<-use_srtp> I<val>]
[B<-no_dhe>]
[B<-nextprotoneg> I<val>]
[B<-alpn> I<val>]
[B<-sendfile>]
[B<-keylogfile> I<outfile>]
[B<-recv_max_early_data> I<int>]
[B<-max_early_data> I<int>]
[B<-early_data>]
[B<-stateless>]
[B<-anti_replay>]
[B<-no_anti_replay>]
[B<-num_tickets>]
{- $OpenSSL::safe::opt_name_synopsis -}
{- $OpenSSL::safe::opt_version_synopsis -}
{- $OpenSSL::safe::opt_v_synopsis -}
{- $OpenSSL::safe::opt_s_synopsis -}
{- $OpenSSL::safe::opt_x_synopsis -}
{- $OpenSSL::safe::opt_trust_synopsis -}
{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
=head1 DESCRIPTION
This 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, this command also supports
the common and server only options documented
L<SSL_CONF_cmd(3)/Supported Command Line Commands>
=over 4
=item B<-help>
Print out a usage message.
=item B<-port> I<+int>
The TCP port to listen on for connections. If not specified 4433 is used.
=item B<-accept> I<val>
The optional TCP host and port to listen on for connections. If not specified, *:4433 is used.
=item B<-unix> I<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> I<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> I<int>, B<-Verify> I<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.
+By default, validation of any supplied client certificate and its chain
+is done w.r.t. the (D)TLS Client (C<sslclient>) purpose.
+For details see L<openssl-verification-options(1)/Certificate Extensions>.
+
=item B<-cert> I<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 F<server.pem> will be used.
=item B<-cert2> I<infile>
The certificate file to use for servername; default is C<server2.pem>.
=item B<-certform> B<DER>|B<PEM>|B<P12>
The server certificate file format; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-cert_chain>
A file or URI of untrusted certificates to use when attempting to build the
certificate chain related to the certificate specified via the B<-cert> option.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-build_chain>
Specify whether the application should build the server certificate chain to be
provided to the client.
=item B<-serverinfo> I<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<-key> I<filename>|I<uri>
The private key to use. If not specified then the certificate file will
be used.
=item B<-key2> I<filename>|I<uri>
The private Key file to use for servername if not given via B<-cert2>.
=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The key format; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-pass> I<val>
The private key and certificate file password source.
For more information about the format of I<val>,
see L<openssl-passphrase-options(1)>.
=item B<-dcert> I<infile>, B<-dkey> I<filename>|I<uri>
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 or URI of untrusted certificates to use when attempting to build the
server certificate chain when a certificate specified via the B<-dcert> option
is in use.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-dcertform> B<DER>|B<PEM>|B<P12>
The format of the additional certificate file; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-dkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The format of the additional private key; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-dpass> I<val>
The passphrase for the additional private key and certificate.
For more information about the format of I<val>,
see L<openssl-passphrase-options(1)>.
=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<-security_debug>
Print output from SSL/TLS security framework.
=item B<-security_debug_verbose>
Print more output from SSL/TLS security framework
=item B<-msg>
Show all protocol messages with hex dump.
=item B<-msgfile> I<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<-CRL> I<infile>
The CRL file to use.
=item B<-CRLform> B<DER>|B<PEM>
The CRL file format; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-crl_download>
Download CRLs from distribution points given in CDP extensions of certificates
=item B<-verifyCAfile> I<filename>
A file in PEM format CA containing trusted certificates to use
for verifying client certificates.
=item B<-verifyCApath> I<dir>
A directory containing trusted certificates to use
for verifying client certificates.
This directory must be in "hash format",
see L<openssl-verify(1)> for more information.
=item B<-verifyCAstore> I<uri>
The URI of a store containing trusted certificates to use
for verifying client certificates.
=item B<-chainCAfile> I<file>
A file in PEM format containing trusted certificates to use
when attempting to build the server certificate chain.
=item B<-chainCApath> I<dir>
A directory containing trusted certificates to use
for building the server certificate chain provided to the client.
This directory must be in "hash format",
see L<openssl-verify(1)> for more information.
=item B<-chainCAstore> I<uri>
The URI of a store containing trusted certificates to use
for building the server certificate chain provided to the client.
The URI may indicate a single certificate, as well as a collection of them.
With URIs in the C<file:> scheme, this acts as B<-chainCAfile> or
B<-chainCApath>, depending on if the URI indicates a directory or a
single file.
See L<ossl_store-file(7)> for more information on the C<file:> scheme.
=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<-no_resume_ephemeral>
Disable caching and tickets if ephemeral (EC)DH is used.
=item B<-tlsextdebug>
Print a hex dump of any TLS extensions received from the server.
=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 can be used with a web browser.
The special URL C</renegcert> turns on client cert validation, and C</reneg>
tells the server to request renegotiation.
The B<-early_data> option cannot be used with this option.
=item B<-WWW>, B<-HTTP>
Emulates a simple web server. Pages will be resolved relative to the
current directory, for example if the URL C<https://myhost/page.html> is
requested the file F<./page.html> will be sent.
If the B<-HTTP> flag is used, the files are sent directly, and should contain
any HTTP response headers (including status response line).
If the B<-WWW> option is used,
the response headers are generated by the server, and the file extension is
examined to determine the B<Content-Type> header.
Extensions of C<html>, C<htm>, and C<php> are C<text/html> and all others are
C<text/plain>.
In addition, the special URL C</stats> will return status
information like the B<-www> option.
Neither of these options can be used in conjunction with B<-early_data>.
=item B<-http_server_binmode>
When acting as web-server (using option B<-WWW> or B<-HTTP>) open files requested
by the client in binary mode.
=item B<-no_ca_names>
Disable TLS Extension CA Names. You may want to disable it for security reasons
or for compatibility with some Windows TLS implementations crashing when this
extension is larger than 1024 bytes.
=item B<-ignore_unexpected_eof>
Some TLS implementations do not send the mandatory close_notify alert on
shutdown. If the application tries to wait for the close_notify alert but the
peer closes the connection without sending it, an error is generated. When this
option is enabled the peer does not need to send the close_notify alert and a
closed connection will be treated as if the close_notify alert was received.
For more information on shutting down a connection, see L<SSL_shutdown(3)>.
=item B<-servername>
Servername for HostName TLS extension.
=item B<-servername_fatal>
On servername mismatch send fatal alert (default: warning alert).
=item B<-id_prefix> I<val>
Generate SSL/TLS session IDs prefixed by I<val>. This is mostly useful
for testing any SSL/TLS code (e.g. proxies) that wish to deal with multiple
servers, when each of which might be generating a unique range of session
IDs (e.g. with a certain prefix).
=item B<-keymatexport>
Export keying material using label.
=item B<-keymatexportlen>
Export the given number of bytes of keying material; default 20.
=item B<-no_cache>
Disable session cache.
=item B<-ext_cache>.
Disable internal cache, set up and use external cache.
=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<-verify_quiet>
No verify output except verify errors.
=item B<-ign_eof>
Ignore input EOF (default: when B<-quiet>).
=item B<-no_ign_eof>
Do not ignore input EOF.
=item B<-no_etm>
Disable Encrypt-then-MAC negotiation.
=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> I<int>
Sets the timeout for OCSP response to I<int> seconds.
-=item B<-proxy> I<[http[s]://][userinfo@]host[:port][/path]>
+=item B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>
The HTTP(S) proxy server to use for reaching the OCSP server unless B<-no_proxy>
applies, see below.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
The proxy port defaults to 80 or 443 if the scheme is C<https>; apart from that
the optional C<http://> or C<https://> prefix is ignored,
-as well as any userinfo and path components.
+as well as any userinfo, path, query, and fragment components.
Defaults to the environment variable C<http_proxy> if set, else C<HTTP_PROXY>
in case no TLS is used, otherwise C<https_proxy> if set, else C<HTTPS_PROXY>.
=item B<-no_proxy> I<addresses>
List of IP addresses and/or DNS names of servers
not to use an HTTP(S) proxy for, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
Default is from the environment variable C<no_proxy> if set, else C<NO_PROXY>.
=item B<-status_url> I<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.
The optional userinfo and fragment URL components are ignored.
Any given query component is handled as part of the path component.
=item B<-status_file> I<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<-ssl_config> I<val>
Configure SSL_CTX using the given configuration value.
=item B<-trace>
Show verbose trace output of protocol messages.
=item B<-brief>
Provide a brief summary of connection parameters instead of the normal verbose
output.
=item B<-rev>
Simple echo server that sends back received text reversed. 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> I<+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> I<+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> I<+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<-naccept> I<+int>
The server will exit after receiving the specified number of connections,
default unlimited.
=item B<-read_buf> I<+int>
The default read buffer size to be used for connections. This will only have an
effect if the buffer size is larger than the size that would otherwise be used
and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
further information).
=item B<-bugs>
There are several known bugs in SSL and TLS implementations. Adding this
option enables various workarounds.
=item B<-no_comp>
Disable negotiation of TLS compression.
TLS compression is not recommended and is off by default as of
OpenSSL 1.1.0.
=item B<-comp>
Enable negotiation of TLS compression.
This option was introduced in OpenSSL 1.1.0.
TLS compression is not recommended and is off by default as of
OpenSSL 1.1.0.
=item B<-no_ticket>
Disable RFC4507bis session ticket support. This option has no effect if TLSv1.3
is negotiated. See B<-num_tickets>.
=item B<-num_tickets>
Control the number of tickets that will be sent to the client after a full
handshake in TLSv1.3. The default number of tickets is 2. This option does not
affect the number of tickets sent after a resumption handshake.
=item B<-serverpref>
Use the server's cipher preferences, rather than the client's preferences.
=item B<-prioritize_chacha>
Prioritize ChaCha ciphers when preferred by clients. Requires B<-serverpref>.
=item B<-no_resumption_on_reneg>
Set the B<SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION> option.
=item B<-client_sigalgs> I<val>
Signature algorithms to support for client certificate authentication
(colon-separated list).
=item B<-named_curve> I<val>
Specifies the elliptic curve to use. NOTE: this is single curve, not a list.
The list of all supported groups includes named EC parameters as well as X25519
and X448 or FFDHE groups, and may also include groups implemented in 3rd-party
providers. For a list of named EC parameters, use:
$ openssl ecparam -list_curves
=item B<-cipher> I<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
L<openssl-ciphers(1)> for more information.
=item B<-ciphersuites> I<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
L<openssl-ciphers(1)> command for more information. The format for this list is
a simple colon (":") separated list of TLSv1.3 ciphersuite names.
=item B<-dhparam> I<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 this command
will be used.
=item B<-nbio>
Turns on non blocking I/O.
=item B<-timeout>
Enable timeouts.
=item B<-mtu>
Set link-layer MTU.
=item B<-psk_identity> I<val>
Expect the client to send PSK identity I<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> I<val>
Use the PSK identity hint I<val> when using a PSK cipher suite.
=item B<-psk> I<val>
Use the PSK key I<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> I<file>
Use the pem encoded SSL_SESSION data stored in I<file> as the basis of a PSK.
Note that this will only work if TLSv1.3 is negotiated.
=item B<-srpvfile>
The verifier file for SRP.
This option is deprecated.
=item B<-srpuserseed>
A seed string for a default user salt.
This option is deprecated.
=item B<-listen>
This option can only be used in conjunction with one of the DTLS options above.
With this option, this command 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 this command will
connect to that peer and complete the handshake.
=item B<-sctp>
Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
available where OpenSSL has support for SCTP enabled.
=item B<-sctp_label_bug>
Use the incorrect behaviour of older OpenSSL implementations when computing
endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
older broken implementations but breaks interoperability with correct
implementations. Must be used in conjunction with B<-sctp>. This option is only
available where OpenSSL has support for SCTP enabled.
=item B<-use_srtp>
Offer SRTP key management with a colon-separated profile list.
=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> I<val>, B<-nextprotoneg> I<val>
These flags enable the Application-Layer Protocol Negotiation
or Next Protocol Negotiation (NPN) extension, respectively. ALPN is the
IETF standard and replaces NPN.
The I<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<-sendfile>
If this option is set and KTLS is enabled, SSL_sendfile() will be used
instead of BIO_write() to send the HTTP response requested by a client.
This option is only valid if B<-WWW> or B<-HTTP> is specified.
=item B<-keylogfile> I<outfile>
Appends TLS secrets to the specified keylog file such that external programs
(like Wireshark) can decrypt TLS connections.
=item B<-max_early_data> I<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<-recv_max_early_data> I<int>
Specify the hard limit on the maximum number of early data bytes that will
be accepted.
=item B<-early_data>
Accept early data where possible. Cannot be used in conjunction with B<-www>,
B<-WWW>, B<-HTTP> or B<-rev>.
=item B<-stateless>
Require TLSv1.3 cookies.
=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.
{- $OpenSSL::safe::opt_name_item -}
{- $OpenSSL::safe::opt_version_item -}
{- $OpenSSL::safe::opt_s_item -}
{- $OpenSSL::safe::opt_x_item -}
{- $OpenSSL::safe::opt_trust_item -}
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_engine_item -}
{- $OpenSSL::safe::opt_provider_item -}
{- $OpenSSL::safe::opt_v_item -}
If the server requests a client certificate, then
verification errors are displayed, for debugging, but the command will
proceed unless the B<-verify_return_error> option is used.
=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<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
This command 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 L<openssl-sess_id(1)> command.
=head1 BUGS
Because this program has a lot of options and also because some of the
techniques used are rather old, the C source for this command 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 this command to print out details
of any unknown cipher suites a client says it supports.
=head1 SEE ALSO
L<openssl(1)>,
L<openssl-sess_id(1)>,
L<openssl-s_client(1)>,
L<openssl-ciphers(1)>,
L<SSL_CONF_cmd(3)>,
L<SSL_CTX_set_max_send_fragment(3)>,
L<SSL_CTX_set_split_send_fragment(3)>,
L<SSL_CTX_set_max_pipelines(3)>,
L<ossl_store-file(7)>
=head1 HISTORY
The -no_alt_chains option was added in OpenSSL 1.1.0.
The
-allow-no-dhe-kex and -prioritize_chacha options were added in OpenSSL 1.1.1.
The B<-srpvfile>, B<-srpuserseed>, and B<-engine>
option were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-s_time.pod.in b/crypto/openssl/doc/man1/openssl-s_time.pod.in
index 2b82cf1e9837..ca41f59362f9 100644
--- a/crypto/openssl/doc/man1/openssl-s_time.pod.in
+++ b/crypto/openssl/doc/man1/openssl-s_time.pod.in
@@ -1,198 +1,199 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-s_time - SSL/TLS performance timing program
=head1 SYNOPSIS
B<openssl> B<s_time>
[B<-help>]
[B<-connect> I<host>:I<port>]
[B<-www> I<page>]
[B<-cert> I<filename>]
[B<-key> I<filename>]
[B<-reuse>]
[B<-new>]
[B<-verify> I<depth>]
[B<-time> I<seconds>]
[B<-ssl3>]
[B<-tls1>]
[B<-tls1_1>]
[B<-tls1_2>]
[B<-tls1_3>]
[B<-bugs>]
[B<-cipher> I<cipherlist>]
[B<-ciphersuites> I<val>]
{- $OpenSSL::safe::opt_name_synopsis -}
[B<-cafile> I<file>]
{- $OpenSSL::safe::opt_trust_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
=head1 DESCRIPTION
This command implements a generic SSL/TLS client which
connects to a remote host using SSL/TLS. It can request a page from the server
and includes the time to transfer the payload data in its timing measurements.
It measures the number of connections within a given timeframe, the amount of
data transferred (if any), and calculates the average time spent for one
connection.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-connect> I<host>:I<port>
This specifies the host and optional port to connect to.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
=item B<-www> I<page>
This specifies the page to GET from the server. A value of '/' gets the
F<index.html> page. If this parameter is not specified, then this command
will only perform the handshake to establish SSL connections but not transfer
any payload data.
=item B<-cert> I<certname>
The certificate to use, if one is requested by the server. The default is
not to use a certificate. The file is in PEM format.
=item B<-key> I<keyfile>
The private key to use. If not specified then the certificate file will
be used. The file is in PEM format.
=item B<-verify> I<depth>
The verify depth to use. This specifies the maximum length of the
server certificate chain and turns on server certificate verification.
Currently the verify operation continues after errors so all the problems
with a certificate chain can be seen. As a side effect the connection
will never fail due to a server certificate verify failure.
=item B<-new>
Performs the timing test using a new session ID for each connection.
If neither B<-new> nor B<-reuse> are specified, they are both on by default
and executed in sequence.
=item B<-reuse>
Performs the timing test using the same session ID; this can be used as a test
that session caching is working. If neither B<-new> nor B<-reuse> are
specified, they are both on by default and executed in sequence.
=item B<-bugs>
There are several known bugs in SSL and TLS implementations. Adding this
option enables various workarounds.
=item B<-cipher> I<cipherlist>
This allows the TLSv1.2 and below cipher list sent by the client to be modified.
This list will be combined with any TLSv1.3 ciphersuites that have been
configured. Although the server determines which cipher suite is used it should
take the first supported cipher in the list sent by the client. See
L<openssl-ciphers(1)> for more information.
=item B<-ciphersuites> I<val>
This allows the TLSv1.3 ciphersuites sent by the client to be modified. This
list will be combined with any TLSv1.2 and below ciphersuites that have been
configured. Although the server determines which cipher suite is used it should
take the first supported cipher in the list sent by the client. See
L<openssl-ciphers(1)> for more information. The format for this list is a
simple colon (":") separated list of TLSv1.3 ciphersuite names.
=item B<-time> I<length>
Specifies how long (in seconds) this command should establish connections
and optionally transfer payload data from a server. Server and client
performance and the link speed determine how many connections it
can establish.
{- $OpenSSL::safe::opt_name_item -}
{- $OpenSSL::safe::opt_trust_item -}
{- $OpenSSL::safe::opt_provider_item -}
=item B<-cafile> I<file>
This is an obsolete synonym for B<-CAfile>.
=item B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>
See L<openssl(1)/TLS Version Options>.
=back
=head1 NOTES
This command can be used to measure the performance of an SSL connection.
To connect to an SSL HTTP server and get the default page the command
openssl s_time -connect servername:443 -www / -CApath yourdir -CAfile yourfile.pem -cipher commoncipher [-ssl3]
would typically be used (https uses port 443). I<commoncipher> is a cipher to
which both client and server can agree, see the L<openssl-ciphers(1)> command
for details.
If the handshake fails then there are several possible causes, if it is
nothing obvious like no client certificate then the B<-bugs> and
B<-ssl3> options can be tried
in case it is a buggy server. In particular you should play with these
options B<before> submitting a bug report to an OpenSSL mailing list.
A frequent problem when attempting to get client certificates working
is that a web client complains it has no certificates or gives an empty
list to choose from. This is normally because the server is not sending
the clients certificate authority in its "acceptable CA list" when it
requests a certificate. By using L<openssl-s_client(1)> the CA list can be
viewed and checked. However, some servers only request client authentication
after a specific URL is requested. To obtain the list in this case it
is necessary to use the B<-prexit> option of L<openssl-s_client(1)> and
send an HTTP request for an appropriate page.
If a certificate is specified on the command line using the B<-cert>
option it will not be used unless the server specifically requests
a client certificate. Therefore, merely including a client certificate
on the command line is no guarantee that the certificate works.
=head1 BUGS
Because this program does not have all the options of the
L<openssl-s_client(1)> program to turn protocols on and off, you may not
be able to measure the performance of all protocols with all servers.
The B<-verify> option should really exit if the server verification
fails.
=head1 HISTORY
The B<-cafile> option was deprecated in OpenSSL 3.0.
=head1 SEE ALSO
L<openssl(1)>,
L<openssl-s_client(1)>,
L<openssl-s_server(1)>,
L<openssl-ciphers(1)>,
L<ossl_store-file(7)>
=head1 COPYRIGHT
Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-smime.pod.in b/crypto/openssl/doc/man1/openssl-smime.pod.in
index 0b5dbb5df8f7..ffd09704f834 100644
--- a/crypto/openssl/doc/man1/openssl-smime.pod.in
+++ b/crypto/openssl/doc/man1/openssl-smime.pod.in
@@ -1,484 +1,484 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-smime - S/MIME command
=head1 SYNOPSIS
B<openssl> B<smime>
[B<-help>]
[B<-encrypt>]
[B<-decrypt>]
[B<-sign>]
[B<-resign>]
[B<-verify>]
[B<-pk7out>]
[B<-binary>]
[B<-crlfeol>]
[B<-I<cipher>>]
[B<-in> I<file>]
[B<-certfile> I<file>]
[B<-signer> I<file>]
[B<-nointern>]
[B<-noverify>]
[B<-nochain>]
[B<-nosigs>]
[B<-nocerts>]
[B<-noattr>]
[B<-nodetach>]
[B<-nosmimecap>]
[B<-recip> I< file>]
[B<-inform> B<DER>|B<PEM>|B<SMIME>]
[B<-outform> B<DER>|B<PEM>|B<SMIME>]
[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
[B<-passin> I<arg>]
[B<-inkey> I<filename>|I<uri>]
[B<-out> I<file>]
[B<-content> I<file>]
[B<-to> I<addr>]
[B<-from> I<ad>]
[B<-subject> I<s>]
[B<-text>]
[B<-indef>]
[B<-noindef>]
[B<-stream>]
[B<-md> I<digest>]
{- $OpenSSL::safe::opt_trust_synopsis -}
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_v_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
{- $OpenSSL::safe::opt_config_synopsis -}
I<recipcert> ...
=head1 DESCRIPTION
This command handles S/MIME mail. It can encrypt, decrypt, sign
and verify S/MIME messages.
=head1 OPTIONS
There are six operation options that set the type of operation to be performed.
The meaning of the other options varies according to the operation type.
=over 4
=item B<-help>
Print out a usage message.
=item B<-encrypt>
Encrypt mail for the given recipient certificates. Input file is the message
to be encrypted. The output file is the encrypted mail in MIME format.
Note that no revocation check is done for the recipient cert, so if that
key has been compromised, others may be able to decrypt the text.
=item B<-decrypt>
Decrypt mail using the supplied certificate and private key. Expects an
encrypted mail message in MIME format for the input file. The decrypted mail
is written to the output file.
=item B<-sign>
Sign mail using the supplied certificate and private key. Input file is
the message to be signed. The signed message in MIME format is written
to the output file.
=item B<-verify>
Verify signed mail. Expects a signed mail message on input and outputs
the signed data. Both clear text and opaque signing is supported.
=item B<-pk7out>
Takes an input message and writes out a PEM encoded PKCS#7 structure.
=item B<-resign>
Resign a message: take an existing message and one or more new signers.
=item B<-in> I<filename>
The input message to be encrypted or signed or the MIME message to
be decrypted or verified.
=item B<-out> I<filename>
The message text that has been decrypted or verified or the output MIME
format message that has been signed or verified.
=item B<-inform> B<DER>|B<PEM>|B<SMIME>
The input format of the PKCS#7 (S/MIME) structure (if one is being read);
the default is B<SMIME>.
See L<openssl-format-options(1)> for details.
=item B<-outform> B<DER>|B<PEM>|B<SMIME>
The output format of the PKCS#7 (S/MIME) structure (if one is being written);
the default is B<SMIME>.
See L<openssl-format-options(1)> for details.
=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
The key format; unspecified by default.
See L<openssl-format-options(1)> for details.
=item B<-stream>, B<-indef>, B<-noindef>
The B<-stream> and B<-indef> options are equivalent and enable streaming I/O
for encoding operations. This permits single pass processing of data without
the need to hold the entire contents in memory, potentially supporting very
large files. Streaming is automatically set for S/MIME signing with detached
data if the output format is B<SMIME> it is currently off by default for all
other operations.
=item B<-noindef>
Disable streaming I/O where it would produce and indefinite length constructed
encoding. This option currently has no effect. In future streaming will be
enabled by default on all relevant operations and this option will disable it.
=item B<-content> I<filename>
This specifies a file containing the detached content, this is only
useful with the B<-verify> command. This is only usable if the PKCS#7
structure is using the detached signature form where the content is
not included. This option will override any content if the input format
is S/MIME and it uses the multipart/signed MIME content type.
=item B<-text>
This option adds plain text (text/plain) MIME headers to the supplied
message if encrypting or signing. If decrypting or verifying it strips
off text headers: if the decrypted or verified message is not of MIME
type text/plain then an error occurs.
=item B<-md> I<digest>
Digest algorithm to use when signing or resigning. If not present then the
default digest algorithm for the signing key will be used (usually SHA1).
=item B<-I<cipher>>
The encryption algorithm to use. For example DES (56 bits) - B<-des>,
triple DES (168 bits) - B<-des3>,
EVP_get_cipherbyname() function) can also be used preceded by a dash, for
example B<-aes-128-cbc>. See L<openssl-enc(1)> for list of ciphers
supported by your version of OpenSSL.
If not specified triple DES is used. Only used with B<-encrypt>.
=item B<-nointern>
When verifying a message normally certificates (if any) included in
the message are searched for the signing certificate. With this option
only the certificates specified in the B<-certfile> option are used.
The supplied certificates can still be used as untrusted CAs however.
=item B<-noverify>
Do not verify the signers certificate of a signed message.
=item B<-nochain>
Do not do chain verification of signers certificates; that is, do not
use the certificates in the signed message as untrusted CAs.
=item B<-nosigs>
Don't try to verify the signatures on the message.
=item B<-nocerts>
When signing a message, the signer's certificate is normally included.
With this option it is excluded. This will reduce the size of the
signed message, but the verifier must have a copy of the signers certificate
available locally (passed using the B<-certfile> option for example).
=item B<-noattr>
Normally, when a message is signed, a set of attributes are included which
include the signing time and supported symmetric algorithms. With this
option they are not included.
=item B<-nodetach>
When signing a message use opaque signing. This form is more resistant
to translation by mail relays but it cannot be read by mail agents that
do not support S/MIME. Without this option cleartext signing with
the MIME type multipart/signed is used.
=item B<-nosmimecap>
When signing a message, do not include the B<SMIMECapabilities> attribute.
=item B<-binary>
Normally the input message is converted to "canonical" format which is
effectively using CR and LF as end of line: as required by the S/MIME
specification. When this option is present no translation occurs. This
is useful when handling binary data which may not be in MIME format.
=item B<-crlfeol>
Normally the output file uses a single B<LF> as end of line. When this
option is present B<CRLF> is used instead.
=item B<-certfile> I<file>
Allows additional certificates to be specified. When signing these will
be included with the message. When verifying these will be searched for
the signers certificates.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-signer> I<file>
A signing certificate when signing or resigning a message, this option can be
used multiple times if more than one signer is required. If a message is being
verified then the signers certificates will be written to this file if the
verification was successful.
=item B<-recip> I<file>
The recipients certificate when decrypting a message. This certificate
must match one of the recipients of the message or an error occurs.
=item B<-inkey> I<filename>|I<uri>
The private key to use when signing or decrypting. This must match the
corresponding certificate. If this option is not specified then the
private key must be included in the certificate file specified with
the B<-recip> or B<-signer> file. When signing this option can be used
multiple times to specify successive keys.
=item B<-passin> I<arg>
The private key password source. For more information about the format of I<arg>
see L<openssl-passphrase-options(1)>.
=item B<-to>, B<-from>, B<-subject>
The relevant mail headers. These are included outside the signed
portion of a message so they may be included manually. If signing
then many S/MIME mail clients check the signers certificate's email
address matches that specified in the From: address.
{- $OpenSSL::safe::opt_v_item -}
Any verification errors cause the command to exit.
{- $OpenSSL::safe::opt_trust_item -}
{- $OpenSSL::safe::opt_engine_item -}
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_provider_item -}
{- $OpenSSL::safe::opt_config_item -}
=item I<recipcert> ...
One or more certificates of message recipients, used when encrypting
a message.
=back
=head1 NOTES
The MIME message must be sent without any blank lines between the
headers and the output. Some mail programs will automatically add
a blank line. Piping the mail directly to sendmail is one way to
achieve the correct format.
The supplied message to be signed or encrypted must include the
necessary MIME headers or many S/MIME clients won't display it
properly (if at all). You can use the B<-text> option to automatically
add plain text headers.
A "signed and encrypted" message is one where a signed message is
then encrypted. This can be produced by encrypting an already signed
message: see the examples section.
This version of the program only allows one signer per message but it
will verify multiple signers on received messages. Some S/MIME clients
choke if a message contains multiple signers. It is possible to sign
messages "in parallel" by signing an already signed message.
The options B<-encrypt> and B<-decrypt> reflect common usage in S/MIME
clients. Strictly speaking these process PKCS#7 enveloped data: PKCS#7
encrypted data is used for other purposes.
The B<-resign> option uses an existing message digest when adding a new
signer. This means that attributes must be present in at least one existing
signer using the same message digest or this operation will fail.
The B<-stream> and B<-indef> options enable streaming I/O support.
As a result the encoding is BER using indefinite length constructed encoding
and no longer DER. Streaming is supported for the B<-encrypt> operation and the
B<-sign> operation if the content is not detached.
Streaming is always used for the B<-sign> operation with detached data but
since the content is no longer part of the PKCS#7 structure the encoding
remains DER.
=head1 EXIT CODES
=over 4
=item Z<>0
The operation was completely successfully.
=item Z<>1
An error occurred parsing the command options.
=item Z<>2
One of the input files could not be read.
=item Z<>3
An error occurred creating the PKCS#7 file or when reading the MIME
message.
=item Z<>4
An error occurred decrypting or verifying the message.
=item Z<>5
The message was verified correctly but an error occurred writing out
the signers certificates.
=back
=head1 EXAMPLES
Create a cleartext signed message:
openssl smime -sign -in message.txt -text -out mail.msg \
-signer mycert.pem
Create an opaque signed message:
openssl smime -sign -in message.txt -text -out mail.msg -nodetach \
-signer mycert.pem
Create a signed message, include some additional certificates and
read the private key from another file:
openssl smime -sign -in in.txt -text -out mail.msg \
-signer mycert.pem -inkey mykey.pem -certfile mycerts.pem
Create a signed message with two signers:
openssl smime -sign -in message.txt -text -out mail.msg \
-signer mycert.pem -signer othercert.pem
Send a signed message under Unix directly to sendmail, including headers:
openssl smime -sign -in in.txt -text -signer mycert.pem \
-from steve@openssl.org -to someone@somewhere \
-subject "Signed message" | sendmail someone@somewhere
Verify a message and extract the signer's certificate if successful:
openssl smime -verify -in mail.msg -signer user.pem -out signedtext.txt
Send encrypted mail using triple DES:
- openssl smime -encrypt -in in.txt -from steve@openssl.org \
+ openssl smime -encrypt -in in.txt -out mail.msg -from steve@openssl.org \
-to someone@somewhere -subject "Encrypted message" \
- -des3 user.pem -out mail.msg
+ -des3 user.pem
Sign and encrypt mail:
openssl smime -sign -in ml.txt -signer my.pem -text \
| openssl smime -encrypt -out mail.msg \
-from steve@openssl.org -to someone@somewhere \
-subject "Signed and Encrypted message" -des3 user.pem
Note: the encryption command does not include the B<-text> option because the
message being encrypted already has MIME headers.
Decrypt mail:
openssl smime -decrypt -in mail.msg -recip mycert.pem -inkey key.pem
The output from Netscape form signing is a PKCS#7 structure with the
detached signature format. You can use this program to verify the
signature by line wrapping the base64 encoded structure and surrounding
it with:
-----BEGIN PKCS7-----
-----END PKCS7-----
and using the command:
openssl smime -verify -inform PEM -in signature.pem -content content.txt
Alternatively you can base64 decode the signature and use:
openssl smime -verify -inform DER -in signature.der -content content.txt
Create an encrypted message using 128 bit Camellia:
openssl smime -encrypt -in plain.txt -camellia128 -out mail.msg cert.pem
Add a signer to an existing message:
openssl smime -resign -in mail.msg -signer newsign.pem -out mail2.msg
=head1 BUGS
The MIME parser isn't very clever: it seems to handle most messages that I've
thrown at it but it may choke on others.
The code currently will only write out the signer's certificate to a file: if
the signer has a separate encryption certificate this must be manually
extracted. There should be some heuristic that determines the correct
encryption certificate.
Ideally a database should be maintained of a certificates for each email
address.
The code doesn't currently take note of the permitted symmetric encryption
algorithms as supplied in the SMIMECapabilities signed attribute. This means the
user has to manually include the correct encryption algorithm. It should store
the list of permitted ciphers in a database and only use those.
No revocation checking is done on the signer's certificate.
The current code can only handle S/MIME v2 messages, the more complex S/MIME v3
structures may cause parsing errors.
=head1 SEE ALSO
L<ossl_store-file(7)>
=head1 HISTORY
The use of multiple B<-signer> options and the B<-resign> command were first
added in OpenSSL 1.0.0
The -no_alt_chains option was added in OpenSSL 1.1.0.
The B<-engine> option was deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-ts.pod.in b/crypto/openssl/doc/man1/openssl-ts.pod.in
index 5f4895b34d6c..cd6dfd5305f0 100644
--- a/crypto/openssl/doc/man1/openssl-ts.pod.in
+++ b/crypto/openssl/doc/man1/openssl-ts.pod.in
@@ -1,662 +1,664 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-ts - Time Stamping Authority command
=head1 SYNOPSIS
B<openssl> B<ts>
B<-help>
B<openssl> B<ts>
B<-query>
[B<-config> I<configfile>]
[B<-data> I<file_to_hash>]
[B<-digest> I<digest_bytes>]
[B<-I<digest>>]
[B<-tspolicy> I<object_id>]
[B<-no_nonce>]
[B<-cert>]
[B<-in> I<request.tsq>]
[B<-out> I<request.tsq>]
[B<-text>]
{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
B<openssl> B<ts>
B<-reply>
[B<-config> I<configfile>]
[B<-section> I<tsa_section>]
[B<-queryfile> I<request.tsq>]
[B<-passin> I<password_src>]
[B<-signer> I<tsa_cert.pem>]
[B<-inkey> I<filename>|I<uri>]
[B<-I<digest>>]
[B<-chain> I<certs_file.pem>]
[B<-tspolicy> I<object_id>]
[B<-in> I<response.tsr>]
[B<-token_in>]
[B<-out> I<response.tsr>]
[B<-token_out>]
[B<-text>]
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
B<openssl> B<ts>
B<-verify>
[B<-data> I<file_to_hash>]
[B<-digest> I<digest_bytes>]
[B<-queryfile> I<request.tsq>]
[B<-in> I<response.tsr>]
[B<-token_in>]
[B<-untrusted> I<files>|I<uris>]
[B<-CAfile> I<file>]
[B<-CApath> I<dir>]
[B<-CAstore> I<uri>]
{- $OpenSSL::safe::opt_v_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
=head1 DESCRIPTION
This command is a basic Time Stamping Authority (TSA) client and
server application as specified in RFC 3161 (Time-Stamp Protocol, TSP). A
TSA can be part of a PKI deployment and its role is to provide long
term proof of the existence of a certain datum before a particular
time. Here is a brief description of the protocol:
=over 4
=item 1.
The TSA client computes a one-way hash value for a data file and sends
the hash to the TSA.
=item 2.
The TSA attaches the current date and time to the received hash value,
signs them and sends the timestamp token back to the client. By
creating this token the TSA certifies the existence of the original
data file at the time of response generation.
=item 3.
The TSA client receives the timestamp token and verifies the
signature on it. It also checks if the token contains the same hash
value that it had sent to the TSA.
=back
There is one DER encoded protocol data unit defined for transporting a
timestamp request to the TSA and one for sending the timestamp response
back to the client. This command has three main functions:
creating a timestamp request based on a data file,
creating a timestamp response based on a request, verifying if a
response corresponds to a particular request or a data file.
There is no support for sending the requests/responses automatically
over HTTP or TCP yet as suggested in RFC 3161. The users must send the
requests either by ftp or e-mail.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-query>
Generate a TS query. For details see L</Timestamp Request generation>.
=item B<-reply>
Generate a TS reply. For details see L</Timestamp Response generation>.
=item B<-verify>
Verify a TS response. For details see L</Timestamp Response verification>.
=back
=head2 Timestamp Request generation
The B<-query> command can be used for creating and printing a timestamp
request with the following options:
=over 4
=item B<-config> I<configfile>
The configuration file to use.
Optional; for a description of the default value,
see L<openssl(1)/COMMAND SUMMARY>.
=item B<-data> I<file_to_hash>
The data file for which the timestamp request needs to be
created. stdin is the default if neither the B<-data> nor the B<-digest>
parameter is specified. (Optional)
=item B<-digest> I<digest_bytes>
It is possible to specify the message imprint explicitly without the data
file. The imprint must be specified in a hexadecimal format, two characters
per byte, the bytes optionally separated by colons (e.g. 1A:F6:01:... or
1AF601...). The number of bytes must match the message digest algorithm
in use. (Optional)
=item B<-I<digest>>
The message digest to apply to the data file.
Any digest supported by the L<openssl-dgst(1)> command can be used.
The default is SHA-256. (Optional)
=item B<-tspolicy> I<object_id>
The policy that the client expects the TSA to use for creating the
timestamp token. Either the dotted OID notation or OID names defined
in the config file can be used. If no policy is requested the TSA will
use its own default policy. (Optional)
=item B<-no_nonce>
No nonce is specified in the request if this option is
given. Otherwise, a 64-bit long pseudo-random nonce is
included in the request. It is recommended to use a nonce to
protect against replay attacks. (Optional)
=item B<-cert>
The TSA is expected to include its signing certificate in the
response. (Optional)
=item B<-in> I<request.tsq>
This option specifies a previously created timestamp request in DER
format that will be printed into the output file. Useful when you need
to examine the content of a request in human-readable
format. (Optional)
=item B<-out> I<request.tsq>
Name of the output file to which the request will be written. Default
is stdout. (Optional)
=item B<-text>
If this option is specified the output is human-readable text format
instead of DER. (Optional)
{- $OpenSSL::safe::opt_r_item -}
=back
=head2 Timestamp Response generation
A timestamp response (TimeStampResp) consists of a response status
and the timestamp token itself (ContentInfo), if the token generation was
successful. The B<-reply> command is for creating a timestamp
response or timestamp token based on a request and printing the
response/token in human-readable format. If B<-token_out> is not
specified the output is always a timestamp response (TimeStampResp),
otherwise it is a timestamp token (ContentInfo).
=over 4
=item B<-config> I<configfile>
The configuration file to use.
Optional; for a description of the default value,
see L<openssl(1)/COMMAND SUMMARY>.
See L</CONFIGURATION FILE OPTIONS> for configurable variables.
=item B<-section> I<tsa_section>
The name of the config file section containing the settings for the
response generation. If not specified the default TSA section is
used, see L</CONFIGURATION FILE OPTIONS> for details. (Optional)
=item B<-queryfile> I<request.tsq>
The name of the file containing a DER encoded timestamp request. (Optional)
=item B<-passin> I<password_src>
Specifies the password source for the private key of the TSA. See
description in L<openssl(1)>. (Optional)
=item B<-signer> I<tsa_cert.pem>
The signer certificate of the TSA in PEM format. The TSA signing
certificate must have exactly one extended key usage assigned to it:
timeStamping. The extended key usage must also be critical, otherwise
the certificate is going to be refused. Overrides the B<signer_cert>
variable of the config file. (Optional)
=item B<-inkey> I<filename>|I<uri>
The signer private key of the TSA in PEM format. Overrides the
B<signer_key> config file option. (Optional)
=item B<-I<digest>>
Signing digest to use. Overrides the B<signer_digest> config file
option. (Mandatory unless specified in the config file)
=item B<-chain> I<certs_file.pem>
The collection of certificates in PEM format that will all
be included in the response in addition to the signer certificate if
the B<-cert> option was used for the request. This file is supposed to
contain the certificate chain for the signer certificate from its
issuer upwards. The B<-reply> command does not build a certificate
chain automatically. (Optional)
=item B<-tspolicy> I<object_id>
The default policy to use for the response unless the client
explicitly requires a particular TSA policy. The OID can be specified
either in dotted notation or with its name. Overrides the
B<default_policy> config file option. (Optional)
=item B<-in> I<response.tsr>
Specifies a previously created timestamp response or timestamp token
(if B<-token_in> is also specified) in DER format that will be written
to the output file. This option does not require a request, it is
useful e.g. when you need to examine the content of a response or
token or you want to extract the timestamp token from a response. If
the input is a token and the output is a timestamp response a default
'granted' status info is added to the token. (Optional)
=item B<-token_in>
This flag can be used together with the B<-in> option and indicates
that the input is a DER encoded timestamp token (ContentInfo) instead
of a timestamp response (TimeStampResp). (Optional)
=item B<-out> I<response.tsr>
The response is written to this file. The format and content of the
file depends on other options (see B<-text>, B<-token_out>). The default is
stdout. (Optional)
=item B<-token_out>
The output is a timestamp token (ContentInfo) instead of timestamp
response (TimeStampResp). (Optional)
=item B<-text>
If this option is specified the output is human-readable text format
instead of DER. (Optional)
{- $OpenSSL::safe::opt_engine_item -}
{- $OpenSSL::safe::opt_provider_item -}
=back
=head2 Timestamp Response verification
The B<-verify> command is for verifying if a timestamp response or
timestamp token is valid and matches a particular timestamp request or
data file. The B<-verify> command does not use the configuration file.
=over 4
=item B<-data> I<file_to_hash>
The response or token must be verified against file_to_hash. The file
is hashed with the message digest algorithm specified in the token.
The B<-digest> and B<-queryfile> options must not be specified with this one.
(Optional)
=item B<-digest> I<digest_bytes>
The response or token must be verified against the message digest specified
with this option. The number of bytes must match the message digest algorithm
specified in the token. The B<-data> and B<-queryfile> options must not be
specified with this one. (Optional)
=item B<-queryfile> I<request.tsq>
The original timestamp request in DER format. The B<-data> and B<-digest>
options must not be specified with this one. (Optional)
=item B<-in> I<response.tsr>
The timestamp response that needs to be verified in DER format. (Mandatory)
=item B<-token_in>
This flag can be used together with the B<-in> option and indicates
that the input is a DER encoded timestamp token (ContentInfo) instead
of a timestamp response (TimeStampResp). (Optional)
=item B<-untrusted> I<files>|I<uris>
A set of additional untrusted certificates which may be
needed when building the certificate chain for the TSA's signing certificate.
These do not need to contain the TSA signing certificate and intermediate CA
certificates as far as the response already includes them.
(Optional)
Multiple sources may be given, separated by commas and/or whitespace.
Each file may contain multiple certificates.
=item B<-CAfile> I<file>, B<-CApath> I<dir>, B<-CAstore> I<uri>
See L<openssl-verification-options(1)/Trusted Certificate Options> for details.
At least one of B<-CAfile>, B<-CApath> or B<-CAstore> must be specified.
{- $OpenSSL::safe::opt_v_item -}
Any verification errors cause the command to exit.
=back
=head1 CONFIGURATION FILE OPTIONS
The B<-query> and B<-reply> commands make use of a configuration file.
See L<config(5)>
for a general description of the syntax of the config file. The
B<-query> command uses only the symbolic OID names section
and it can work without it. However, the B<-reply> command needs the
config file for its operation.
When there is a command line switch equivalent of a variable the
switch always overrides the settings in the config file.
=over 4
=item B<tsa> section, B<default_tsa>
This is the main section and it specifies the name of another section
that contains all the options for the B<-reply> command. This default
section can be overridden with the B<-section> command line switch. (Optional)
=item B<oid_file>
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 whitespace then the short name followed
by whitespace and finally the long name. (Optional)
=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. (Optional)
=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. (Note: Using a RANDFILE is
not necessary anymore, see the L</HISTORY> section.
=item B<serial>
The name of the file containing the hexadecimal serial number of the
last timestamp response created. This number is incremented by 1 for
each response. If the file does not exist at the time of response
generation a new file is created with serial number 1. (Mandatory)
=item B<crypto_device>
Specifies the OpenSSL engine that will be set as the default for
all available algorithms. The default value is built-in, you can specify
any other engines supported by OpenSSL (e.g. use chil for the NCipher HSM).
(Optional)
=item B<signer_cert>
TSA signing certificate in PEM format. The same as the B<-signer>
command line option. (Optional)
=item B<certs>
A file containing a set of PEM encoded certificates that need to be
included in the response. The same as the B<-chain> command line
option. (Optional)
=item B<signer_key>
The private key of the TSA in PEM format. The same as the B<-inkey>
command line option. (Optional)
=item B<signer_digest>
Signing digest to use. The same as the
B<-I<digest>> command line option. (Mandatory unless specified on the command
line)
=item B<default_policy>
The default policy to use when the request does not mandate any
policy. The same as the B<-tspolicy> command line option. (Optional)
=item B<other_policies>
Comma separated list of policies that are also acceptable by the TSA
and used only if the request explicitly specifies one of them. (Optional)
=item B<digests>
The list of message digest algorithms that the TSA accepts. At least
one algorithm must be specified. (Mandatory)
=item B<accuracy>
The accuracy of the time source of the TSA in seconds, milliseconds
and microseconds. E.g. secs:1, millisecs:500, microsecs:100. If any of
the components is missing zero is assumed for that field. (Optional)
=item B<clock_precision_digits>
Specifies the maximum number of digits, which represent the fraction of
seconds, that need to be included in the time field. The trailing zeros
must be removed from the time, so there might actually be fewer digits,
or no fraction of seconds at all. Supported only on UNIX platforms.
The maximum value is 6, default is 0.
(Optional)
=item B<ordering>
If this option is yes the responses generated by this TSA can always
be ordered, even if the time difference between two responses is less
than the sum of their accuracies. Default is no. (Optional)
=item B<tsa_name>
Set this option to yes if the subject name of the TSA must be included in
the TSA name field of the response. Default is no. (Optional)
=item B<ess_cert_id_chain>
The SignedData objects created by the TSA always contain the
certificate identifier of the signing certificate in a signed
attribute (see RFC 2634, Enhanced Security Services).
If this variable is set to no, only this signing certificate identifier
is included in the SigningCertificate signed attribute.
If this variable is set to yes and the B<certs> variable or the B<-chain> option
is specified then the certificate identifiers of the chain will also
be included, where the B<-chain> option overrides the B<certs> variable.
Default is no. (Optional)
=item B<ess_cert_id_alg>
This option specifies the hash function to be used to calculate the TSA's
public key certificate identifier. Default is sha1. (Optional)
=back
=head1 EXAMPLES
All the examples below presume that B<OPENSSL_CONF> is set to a proper
configuration file, e.g. the example configuration file
F<openssl/apps/openssl.cnf> will do.
=head2 Timestamp Request
To create a timestamp request for F<design1.txt> with SHA-256 digest,
without nonce and policy, and without requirement for a certificate
in the response:
openssl ts -query -data design1.txt -no_nonce \
-out design1.tsq
To create a similar timestamp request with specifying the message imprint
explicitly:
openssl ts -query -digest b7e5d3f93198b38379852f2c04e78d73abdd0f4b \
-no_nonce -out design1.tsq
To print the content of the previous request in human readable format:
openssl ts -query -in design1.tsq -text
To create a timestamp request which includes the SHA-512 digest
of F<design2.txt>, requests the signer certificate and nonce, and
specifies a policy id (assuming the tsa_policy1 name is defined in the
OID section of the config file):
openssl ts -query -data design2.txt -sha512 \
-tspolicy tsa_policy1 -cert -out design2.tsq
=head2 Timestamp Response
Before generating a response a signing certificate must be created for
the TSA that contains the B<timeStamping> critical extended key usage extension
without any other key usage extensions. You can add this line to the
user certificate section of the config file to generate a proper certificate;
extendedKeyUsage = critical,timeStamping
See L<openssl-req(1)>, L<openssl-ca(1)>, and L<openssl-x509(1)> for
instructions. The examples below assume that F<cacert.pem> contains the
certificate of the CA, F<tsacert.pem> is the signing certificate issued
by F<cacert.pem> and F<tsakey.pem> is the private key of the TSA.
To create a timestamp response for a request:
openssl ts -reply -queryfile design1.tsq -inkey tsakey.pem \
-signer tsacert.pem -out design1.tsr
If you want to use the settings in the config file you could just write:
openssl ts -reply -queryfile design1.tsq -out design1.tsr
To print a timestamp reply to stdout in human readable format:
openssl ts -reply -in design1.tsr -text
To create a timestamp token instead of timestamp response:
openssl ts -reply -queryfile design1.tsq -out design1_token.der -token_out
To print a timestamp token to stdout in human readable format:
openssl ts -reply -in design1_token.der -token_in -text -token_out
To extract the timestamp token from a response:
openssl ts -reply -in design1.tsr -out design1_token.der -token_out
To add 'granted' status info to a timestamp token thereby creating a
valid response:
openssl ts -reply -in design1_token.der -token_in -out design1.tsr
=head2 Timestamp Verification
To verify a timestamp reply against a request:
openssl ts -verify -queryfile design1.tsq -in design1.tsr \
-CAfile cacert.pem -untrusted tsacert.pem
To verify a timestamp reply that includes the certificate chain:
openssl ts -verify -queryfile design2.tsq -in design2.tsr \
-CAfile cacert.pem
To verify a timestamp token against the original data file:
+
openssl ts -verify -data design2.txt -in design2.tsr \
-CAfile cacert.pem
To verify a timestamp token against a message imprint:
+
openssl ts -verify -digest b7e5d3f93198b38379852f2c04e78d73abdd0f4b \
-in design2.tsr -CAfile cacert.pem
You could also look at the 'test' directory for more examples.
=head1 BUGS
=for openssl foreign manual procmail(1) perl(1)
=over 2
=item *
No support for timestamps over SMTP, though it is quite easy
to implement an automatic e-mail based TSA with L<procmail(1)>
and L<perl(1)>. HTTP server support is provided in the form of
a separate apache module. HTTP client support is provided by
L<tsget(1)>. Pure TCP/IP protocol is not supported.
=item *
The file containing the last serial number of the TSA is not
locked when being read or written. This is a problem if more than one
instance of L<openssl(1)> is trying to create a timestamp
response at the same time. This is not an issue when using the apache
server module, it does proper locking.
=item *
Look for the FIXME word in the source files.
=item *
The source code should really be reviewed by somebody else, too.
=item *
More testing is needed, I have done only some basic tests (see
test/testtsa).
=back
=head1 HISTORY
OpenSSL 1.1.1 introduced a new random generator (CSPRNG) with an improved
seeding mechanism. The new seeding mechanism makes it unnecessary to
define a RANDFILE for saving and restoring randomness. This option is
retained mainly for compatibility reasons.
The B<-engine> option was deprecated in OpenSSL 3.0.
=head1 SEE ALSO
L<openssl(1)>,
L<tsget(1)>,
L<openssl-req(1)>,
L<openssl-x509(1)>,
L<openssl-ca(1)>,
L<openssl-genrsa(1)>,
L<config(5)>,
L<ossl_store-file(7)>
=head1 COPYRIGHT
Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl-verification-options.pod b/crypto/openssl/doc/man1/openssl-verification-options.pod
index bf9ed9c1a62e..17fcd4eb79f5 100644
--- a/crypto/openssl/doc/man1/openssl-verification-options.pod
+++ b/crypto/openssl/doc/man1/openssl-verification-options.pod
@@ -1,696 +1,732 @@
=pod
=head1 NAME
openssl-verification-options - generic X.509 certificate verification options
=head1 SYNOPSIS
B<openssl>
I<command>
[ I<options> ... ]
[ I<parameters> ... ]
=head1 DESCRIPTION
There are many situations where X.509 certificates are verified
within the OpenSSL libraries and in various OpenSSL commands.
Certificate verification is implemented by L<X509_verify_cert(3)>.
It is a complicated process consisting of a number of steps
and depending on numerous options.
The most important of them are detailed in the following sections.
In a nutshell, a valid chain of certificates needs to be built up and verified
starting from the I<target certificate> that is to be verified
and ending in a certificate that due to some policy is trusted.
-Verification is done relative to the given I<purpose>, which is the intended use
-of the target certificate, such as SSL server, or by default for any purpose.
+Certificate validation can be performed in the context of a I<purpose>, which
+is a high-level specification of the intended use of the target certificate,
+such as C<sslserver> for TLS servers, or (by default) for any purpose.
The details of how each OpenSSL command handles errors
are documented on the specific command page.
DANE support is documented in L<openssl-s_client(1)>,
L<SSL_CTX_dane_enable(3)>, L<SSL_set1_host(3)>,
L<X509_VERIFY_PARAM_set_flags(3)>, and L<X509_check_host(3)>.
=head2 Trust Anchors
In general, according to RFC 4158 and RFC 5280, a I<trust anchor> is
any public key and related subject distinguished name (DN) that
for some reason is considered trusted
and thus is acceptable as the root of a chain of certificates.
In practice, trust anchors are given in the form of certificates,
where their essential fields are the public key and the subject DN.
In addition to the requirements in RFC 5280,
OpenSSL checks the validity period of such certificates
and makes use of some further fields.
In particular, the subject key identifier extension, if present,
is used for matching trust anchors during chain building.
In the most simple and common case, trust anchors are by default
all self-signed "root" CA certificates that are placed in the I<trust store>,
which is a collection of certificates that are trusted for certain uses.
This is akin to what is used in the trust stores of Mozilla Firefox,
or Apple's and Microsoft's certificate stores, ...
From the OpenSSL perspective, a trust anchor is a certificate
that should be augmented with an explicit designation for which
uses of a target certificate the certificate may serve as a trust anchor.
In PEM encoding, this is indicated by the C<TRUSTED CERTIFICATE> string.
Such a designation provides a set of positive trust attributes
explicitly stating trust for the listed purposes
and/or a set of negative trust attributes
explicitly rejecting the use for the listed purposes.
The purposes are encoded using the values defined for the extended key usages
(EKUs) that may be given in X.509 extensions of end-entity certificates.
See also the L</Extended Key Usage> section below.
The currently recognized uses are
B<clientAuth> (SSL client use), B<serverAuth> (SSL server use),
B<emailProtection> (S/MIME email use), B<codeSigning> (object signer use),
B<OCSPSigning> (OCSP responder use), B<OCSP> (OCSP request use),
B<timeStamping> (TSA server use), and B<anyExtendedKeyUsage>.
As of OpenSSL 1.1.0, the last of these blocks all uses when rejected or
enables all uses when trusted.
A certificate, which may be CA certificate or an end-entity certificate,
is considered a trust anchor for the given use
if and only if all the following conditions hold:
=over 4
=item *
It is an an element of the trust store.
=item *
It does not have a negative trust attribute rejecting the given use.
=item *
It has a positive trust attribute accepting the given use
or (by default) one of the following compatibility conditions apply:
It is self-signed or the B<-partial_chain> option is given
(which corresponds to the B<X509_V_FLAG_PARTIAL_CHAIN> flag being set).
=back
=head2 Certification Path Building
First, a certificate chain is built up starting from the target certificate
and ending in a trust anchor.
The chain is built up iteratively, looking up in turn
a certificate with suitable key usage that
matches as an issuer of the current "subject" certificate as described below.
If there is such a certificate, the first one found that is currently valid
is taken, otherwise the one that expired most recently of all such certificates.
For efficiency, no backtracking is performed, thus
any further candidate issuer certificates that would match equally are ignored.
When a self-signed certificate has been added, chain construction stops.
In this case it must fully match a trust anchor, otherwise chain building fails.
A candidate issuer certificate matches a subject certificate
if all of the following conditions hold:
=over 4
=item *
Its subject name matches the issuer name of the subject certificate.
=item *
If the subject certificate has an authority key identifier extension,
each of its sub-fields equals the corresponding subject key identifier, serial
number, and issuer field of the candidate issuer certificate,
as far as the respective fields are present in both certificates.
=item *
The certificate signature algorithm used to sign the subject certificate
is supported and
equals the public key algorithm of the candidate issuer certificate.
=back
The lookup first searches for issuer certificates in the trust store.
If it does not find a match there it consults
the list of untrusted ("intermediate" CA) certificates, if provided.
=head2 Certification Path Validation
When the certificate chain building process was successful
the chain components and their links are checked thoroughly.
The first step is to check that each certificate is well-formed.
Part of these checks are enabled only if the B<-x509_strict> option is given.
-The second step is to check the extensions of every untrusted certificate
-for consistency with the supplied purpose.
-If the B<-purpose> option is not given then no such checks are done
-except for SSL/TLS connection setup,
-where by default C<sslserver> or C<sslclient>, are checked.
-The target or "leaf" certificate, as well as any other untrusted certificates,
-must have extensions compatible with the specified purpose.
-All certificates except the target or "leaf" must also be valid CA certificates.
-The precise extensions required are described in more detail in
-L<openssl-x509(1)/CERTIFICATE EXTENSIONS>.
+The second step is to check the X.509v3 extensions of every certificate
+for consistency with the intended specific purpose, if any.
+If the B<-purpose> option is not given then no such checks are done except for
+CMS signature checking, where by default C<smimesign> is checked, and SSL/(D)TLS
+connection setup, where by default C<sslserver> or C<sslclient> are checked.
+The X.509v3 extensions of the target or "leaf" certificate
+must be compatible with the specified purpose.
+All other certificates down the chain are checked to be valid CA certificates,
+and possibly also further non-standard checks are performed.
+The precise extensions required are described in detail
+in the L</Certificate Extensions> section below.
The third step is to check the trust settings on the last certificate
(which typically is a self-signed root CA certificate).
It must be trusted for the given use.
For compatibility with previous versions of OpenSSL, a self-signed certificate
with no trust attributes is considered to be valid for all uses.
The fourth, and final, step is to check the validity of the certificate chain.
For each element in the chain, including the root CA certificate,
the validity period as specified by the C<notBefore> and C<notAfter> fields
is checked against the current system time.
The B<-attime> flag may be used to use a reference time other than "now."
The certificate signature is checked as well
(except for the signature of the typically self-signed root CA certificate,
which is verified only if the B<-check_ss_sig> option is given).
When verifying a certificate signature
the keyUsage extension (if present) of the candidate issuer certificate
is checked to permit digitalSignature for signing proxy certificates
or to permit keyCertSign for signing other certificates, respectively.
If all operations complete successfully then certificate is considered
valid. If any operation fails then the certificate is not valid.
=head1 OPTIONS
=head2 Trusted Certificate Options
The following options specify how to supply the certificates
that can be used as trust anchors for certain uses.
As mentioned, a collection of such certificates is called a I<trust store>.
Note that OpenSSL does not provide a default set of trust anchors. Many
Linux distributions include a system default and configure OpenSSL to point
to that. Mozilla maintains an influential trust store that can be found at
L<https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/>.
The certificates to add to the trust store
can be specified using following options.
=over 4
=item B<-CAfile> I<file>
Load the specified file which contains a certificate
or several of them in case the input is in PEM or PKCS#12 format.
PEM-encoded certificates may also have trust attributes set.
=item B<-no-CAfile>
Do not load the default file of trusted certificates.
=item B<-CApath> I<dir>
Use the specified directory as a collection of trusted certificates,
i.e., a trust store.
Files should be named with the hash value of the X.509 SubjectName of each
certificate. This is so that the library can extract the IssuerName,
hash it, and directly lookup the file to get the issuer certificate.
See L<openssl-rehash(1)> for information on creating this type of directory.
=item B<-no-CApath>
Do not use the default directory of trusted certificates.
=item B<-CAstore> I<uri>
Use I<uri> as a store of CA certificates.
The URI may indicate a single certificate, as well as a collection of them.
With URIs in the C<file:> scheme, this acts as B<-CAfile> or
B<-CApath>, depending on if the URI indicates a single file or
directory.
See L<ossl_store-file(7)> for more information on the C<file:> scheme.
These certificates are also used when building the server certificate
chain (for example with L<openssl-s_server(1)>) or client certificate
chain (for example with L<openssl-s_time(1)>).
=item B<-no-CAstore>
Do not use the default store of trusted CA certificates.
=back
=head2 Verification Options
The certificate verification can be fine-tuned with the following flags.
=over 4
=item B<-verbose>
Print extra information about the operations being performed.
=item B<-attime> I<timestamp>
Perform validation checks using time specified by I<timestamp> and not
current system time. I<timestamp> is the number of seconds since
January 1, 1970 (i.e., the Unix Epoch).
=item B<-no_check_time>
This option suppresses checking the validity period of certificates and CRLs
against the current time. If option B<-attime> is used to specify
a verification time, the check is not suppressed.
=item B<-x509_strict>
This disables non-compliant workarounds for broken certificates.
Thus errors are thrown on certificates not compliant with RFC 5280.
When this option is set,
among others, the following certificate well-formedness conditions are checked:
=over 4
=item *
The basicConstraints of CA certificates must be marked critical.
=item *
CA certificates must explicitly include the keyUsage extension.
=item *
If a pathlenConstraint is given the key usage keyCertSign must be allowed.
=item *
The pathlenConstraint must not be given for non-CA certificates.
=item *
The issuer name of any certificate must not be empty.
=item *
The subject name of CA certs, certs with keyUsage crlSign, and certs
without subjectAlternativeName must not be empty.
=item *
If a subjectAlternativeName extension is given it must not be empty.
=item *
The signatureAlgorithm field and the cert signature must be consistent.
=item *
Any given authorityKeyIdentifier and any given subjectKeyIdentifier
must not be marked critical.
=item *
The authorityKeyIdentifier must be given for X.509v3 certs unless they
are self-signed.
=item *
The subjectKeyIdentifier must be given for all X.509v3 CA certs.
=back
=item B<-ignore_critical>
Normally if an unhandled critical extension is present that is not
supported by OpenSSL the certificate is rejected (as required by RFC5280).
If this option is set critical extensions are ignored.
=item B<-issuer_checks>
Ignored.
=item B<-crl_check>
Checks end entity certificate validity by attempting to look up a valid CRL.
If a valid CRL cannot be found an error occurs.
=item B<-crl_check_all>
Checks the validity of B<all> certificates in the chain by attempting
to look up valid CRLs.
=item B<-use_deltas>
Enable support for delta CRLs.
=item B<-extended_crl>
Enable extended CRL features such as indirect CRLs and alternate CRL
signing keys.
=item B<-suiteB_128_only>, B<-suiteB_128>, B<-suiteB_192>
Enable the Suite B mode operation at 128 bit Level of Security, 128 bit or
192 bit, or only 192 bit Level of Security respectively.
See RFC6460 for details. In particular the supported signature algorithms are
reduced to support only ECDSA and SHA256 or SHA384 and only the elliptic curves
P-256 and P-384.
=item B<-auth_level> I<level>
Set the certificate chain authentication security level to I<level>.
The authentication security level determines the acceptable signature and
public key strength when verifying certificate chains. For a certificate
chain to validate, the public keys of all the certificates must meet the
specified security I<level>. The signature algorithm security level is
enforced for all the certificates in the chain except for the chain's
I<trust anchor>, which is either directly trusted or validated by means
other than its signature. See L<SSL_CTX_set_security_level(3)> for the
definitions of the available levels. The default security level is -1,
or "not set". At security level 0 or lower all algorithms are acceptable.
Security level 1 requires at least 80-bit-equivalent security and is broadly
interoperable, though it will, for example, reject MD5 signatures or RSA
keys shorter than 1024 bits.
=item B<-partial_chain>
Allow verification to succeed if an incomplete chain can be built.
That is, a chain ending in a certificate that normally would not be trusted
(because it has no matching positive trust attributes and is not self-signed)
but is an element of the trust store.
This certificate may be self-issued or belong to an intermediate CA.
=item B<-check_ss_sig>
Verify the signature of
the last certificate in a chain if the certificate is supposedly self-signed.
This is prohibited and will result in an error if it is a non-conforming CA
certificate with key usage restrictions not including the keyCertSign bit.
This verification is disabled by default because it doesn't add any security.
=item B<-allow_proxy_certs>
Allow the verification of proxy certificates.
=item B<-trusted_first>
As of OpenSSL 1.1.0 this option is on by default and cannot be disabled.
When constructing the certificate chain, the trusted certificates specified
via B<-CAfile>, B<-CApath>, B<-CAstore> or B<-trusted> are always used
before any certificates specified via B<-untrusted>.
=item B<-no_alt_chains>
As of OpenSSL 1.1.0, since B<-trusted_first> always on, this option has no
effect.
=item B<-trusted> I<file>
Parse I<file> as a set of one or more certificates.
Each of them qualifies as trusted if has a suitable positive trust attribute
or it is self-signed or the B<-partial_chain> option is specified.
This option implies the B<-no-CAfile>, B<-no-CApath>, and B<-no-CAstore> options
and it cannot be used with the B<-CAfile>, B<-CApath> or B<-CAstore> options, so
only certificates specified using the B<-trusted> option are trust anchors.
This option may be used multiple times.
=item B<-untrusted> I<file>
Parse I<file> as a set of one or more certificates.
All certificates (typically of intermediate CAs) are considered untrusted
and may be used to
construct a certificate chain from the target certificate to a trust anchor.
This option may be used multiple times.
=item B<-policy> I<arg>
Enable policy processing and add I<arg> to the user-initial-policy-set (see
RFC5280). The policy I<arg> can be an object name or an OID in numeric form.
This argument can appear more than once.
=item B<-explicit_policy>
Set policy variable require-explicit-policy (see RFC5280).
=item B<-policy_check>
Enables certificate policy processing.
=item B<-policy_print>
Print out diagnostics related to policy processing.
=item B<-inhibit_any>
Set policy variable inhibit-any-policy (see RFC5280).
=item B<-inhibit_map>
Set policy variable inhibit-policy-mapping (see RFC5280).
=item B<-purpose> I<purpose>
-The intended use for the certificate.
-Currently defined purposes are C<sslclient>, C<sslserver>, C<nssslserver>,
+A high-level specification of the intended use of the target certificate.
+Currently predefined purposes are C<sslclient>, C<sslserver>, C<nssslserver>,
C<smimesign>, C<smimeencrypt>, C<crlsign>, C<ocsphelper>, C<timestampsign>,
and C<any>.
If peer certificate verification is enabled, by default the TLS implementation
-as well as the commands B<s_client> and B<s_server> check for consistency
-with TLS server or TLS client use, respectively.
+and thus the commands L<openssl-s_client(1)> and L<openssl-s_server(1)>
+check for consistency with
+TLS server (C<sslserver>) or TLS client use (C<sslclient>), respectively.
+By default, CMS signature validation, which can be done via L<openssl-cms(1)>,
+checks for consistency with S/MIME signing use (C<smimesign>).
While IETF RFC 5280 says that B<id-kp-serverAuth> and B<id-kp-clientAuth>
are only for WWW use, in practice they are used for all kinds of TLS clients
and servers, and this is what OpenSSL assumes as well.
=item B<-verify_depth> I<num>
Limit the certificate chain to I<num> intermediate CA certificates.
A maximal depth chain can have up to I<num>+2 certificates, since neither the
end-entity certificate nor the trust-anchor certificate count against the
B<-verify_depth> limit.
=item B<-verify_email> I<email>
Verify if I<email> matches the email address in Subject Alternative Name or
the email in the subject Distinguished Name.
=item B<-verify_hostname> I<hostname>
Verify if I<hostname> matches DNS name in Subject Alternative Name or
Common Name in the subject certificate.
=item B<-verify_ip> I<ip>
Verify if I<ip> matches the IP address in Subject Alternative Name of
the subject certificate.
=item B<-verify_name> I<name>
-Use default verification policies like trust model and required certificate
-policies identified by I<name>.
+Use a set of verification parameters, also known as verification method,
+identified by I<name>. The currently predefined methods are named C<ssl_client>,
+C<ssl_server>, C<smime_sign> with alias C<pkcs7>, and C<default>.
+These mimic the combinations of purpose and trust settings used in SSL/(D)TLS,
+and CMS/PKCS7 (including S/MIME).
+
+The verification parameters include the trust model, various flags that can
+partly be set also via other command-line options, and the verification purpose,
+which in turn implies certificate key usage and extended key usage requirements.
+
The trust model determines which auxiliary trust or reject OIDs are applicable
to verifying the given certificate chain.
They can be given using the B<-addtrust> and B<-addreject> options
for L<openssl-x509(1)>.
-Supported policy names include: B<default>, B<pkcs7>, B<smime_sign>,
-B<ssl_client>, B<ssl_server>.
-These mimics the combinations of purpose and trust settings used in SSL, CMS
-and S/MIME.
-As of OpenSSL 1.1.0, the trust model is inferred from the purpose when not
-specified, so the B<-verify_name> options are functionally equivalent to the
-corresponding B<-purpose> settings.
=back
=head2 Extended Verification Options
Sometimes there may be more than one certificate chain leading to an
end-entity certificate.
This usually happens when a root or intermediate CA signs a certificate
for another a CA in other organization.
Another reason is when a CA might have intermediates that use two different
signature formats, such as a SHA-1 and a SHA-256 digest.
The following options can be used to provide data that will allow the
OpenSSL command to generate an alternative chain.
=over 4
=item B<-xkey> I<infile>, B<-xcert> I<infile>, B<-xchain>
Specify an extra certificate, private key and certificate chain. These behave
in the same manner as the B<-cert>, B<-key> and B<-cert_chain> options. When
specified, the callback returning the first valid chain will be in use by the
client.
=item B<-xchain_build>
Specify whether the application should build the certificate chain to be
provided to the server for the extra certificates via the B<-xkey>,
B<-xcert>, and B<-xchain> options.
=item B<-xcertform> B<DER>|B<PEM>|B<P12>
The input format for the extra certificate.
This option has no effect and is retained for backward compatibility only.
=item B<-xkeyform> B<DER>|B<PEM>|B<P12>
The input format for the extra key.
This option has no effect and is retained for backward compatibility only.
=back
=head2 Certificate Extensions
-Options like B<-purpose> lead to checking the certificate extensions,
-which determine what the target certificate and intermediate CA certificates
-can be used for.
+Options like B<-purpose> and B<-verify_name> trigger the processing of specific
+certificate extensions, which determine what certificates can be used for.
=head3 Basic Constraints
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,
which includes the case that it is an X.509v1 certificate,
then the certificate is considered to be a "possible CA" and
other extensions are checked according to the intended use of the certificate.
The treatment of certificates without basicConstraints as a CA
is presently supported, but this could change in the future.
=head3 Key Usage
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.
=head3 Extended Key Usage
-The extKeyUsage (EKU) 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 check is given below. The comments about
+The extKeyUsage (EKU) extension places additional restrictions on
+certificate use. If this extension is present (whether critical or not)
+in an end-entity certficiate, the key is allowed only for the uses specified,
+while the special EKU B<anyExtendedKeyUsage> allows for all uses.
+
+Note that according to RFC 5280 section 4.2.1.12,
+the Extended Key Usage extension will appear only in end-entity certificates,
+and consequently the standard certification path validation described
+in its section 6 does not include EKU checks for CA certificates.
+The CA/Browser Forum requires for TLS server, S/MIME, and code signing use
+the presence of respective EKUs in subordinate CA certificates (while excluding
+them for root CA certificates), while taking over from RFC 5280
+the certificate validity concept and certificate path validation.
+
+For historic reasons, OpenSSL has its own way of interpreting and checking
+EKU extensions on CA certificates, which may change in the future.
+It does not require the presence of EKU extensions in CA certificates,
+but in case the verification purpose is
+C<sslclient>, C<nssslserver>, C<sslserver>, C<smimesign>, or C<smimeencrypt>,
+it checks that any present EKU extension (that does not contain
+B<anyExtendedKeyUsage>) contains the respective EKU as detailed below.
+Moreover, it does these checks even for trust anchor certificates.
+
+=head3 Checks Implied by Specific Predefined Policies
+
+A specific description of each check is given below. The comments about
basicConstraints and keyUsage and X.509v1 certificates above apply to B<all>
CA certificates.
-
=over 4
-=item B<SSL Client>
+=item B<(D)TLS Client> (C<sslclient>)
-The extended key usage extension must be absent or include the "web client
-authentication" OID. The keyUsage extension must be absent or it must have the
-digitalSignature bit set. The Netscape certificate type must be absent
-or it must have the SSL client bit set.
+Any given extended key usage extension must allow for C<clientAuth>
+("TLS WWW client authentication").
-=item B<SSL Client CA>
+For target certificates,
+the key usage must allow for C<digitalSignature> and/or C<keyAgreement>.
+The Netscape certificate type must be absent or have the SSL client bit set.
-The extended key usage extension must be absent or include the "web client
-authentication" OID.
-The 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.
+For all other certificates the normal CA checks apply. In addition,
+the Netscape certificate type must be absent or have the SSL CA bit set.
+This is used as a workaround if the basicConstraints extension is absent.
-=item B<SSL Server>
+=item B<(D)TLS Server> (C<sslserver>)
-The extended key usage extension must be absent or include the "web server
-authentication" and/or one of the SGC OIDs. The keyUsage extension must be
-absent or it
-must have the digitalSignature, the keyEncipherment set or both bits set.
-The Netscape certificate type must be absent or have the SSL server bit set.
+Any given extended key usage extension must allow for C<serverAuth>
+("TLS WWW server authentication") and/or include one of the SGC OIDs.
-=item B<SSL Server CA>
+For target certificates, the key usage must
+allow for C<digitalSignature>, C<keyEncipherment>, and/or C<keyAgreement>.
+The Netscape certificate type must be absent or have the SSL server bit set.
-The extended key usage extension must be absent or include the "web server
-authentication" and/or one of the SGC OIDs. The 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.
+For all other certificates the normal CA checks apply. In addition,
+the Netscape certificate type must be absent or have the SSL CA bit set.
+This is used as a workaround if the basicConstraints extension is absent.
-=item B<Netscape SSL Server>
+=item B<Netscape SSL Server> (C<nssslserver>)
-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
+In addition to what has been described for B<sslserver>, for a Netscape
+SSL client to connect to an SSL server, its EE certficate must have the
+B<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>
+=item B<Common S/MIME Checks>
-The extended key usage extension must be absent or include the "email
-protection" OID. The Netscape certificate type must be absent or should have the
-S/MIME bit set. If the S/MIME bit is not set in the Netscape certificate type
+Any given extended key usage extension must allow for C<emailProtection>.
+
+For target certificates,
+the Netscape certificate type must be absent or should have the S/MIME bit set.
+If the S/MIME bit is not set in the 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>
+For all other certificates the normal CA checks apply. In addition,
+the Netscape certificate type must be absent or have the S/MIME CA bit set.
+This is used as a workaround if the basicConstraints extension is absent.
+
+=item B<S/MIME Signing> (C<smimesign>)
+
+In addition to the common S/MIME checks, for target certficiates
+the key usage must allow for C<digitalSignature> and/or B<nonRepudiation>.
+
+=item B<S/MIME Encryption> (C<smimeencrypt>)
+
+In addition to the common S/MIME checks, for target certficiates
+the key usage must allow for C<keyEncipherment>.
-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<CRL Signing> (C<crlsign>)
-=item B<S/MIME Encryption>
+For target certificates, the key usage must allow for C<cRLSign>.
-In addition to the common S/MIME tests the keyEncipherment bit must be set
-if the keyUsage extension is present.
+For all other certifcates the normal CA checks apply.
+Except in this case the basicConstraints extension must be present.
-=item B<S/MIME CA>
+=item B<OCSP Helper> (C<ocsphelper>)
-The extended key usage extension must be absent or include the "email
-protection" OID. The 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.
+For target certificates, no checks are performed at this stage,
+but special checks apply; see L<OCSP_basic_verify(3)>.
-=item B<CRL Signing>
+For all other certifcates the normal CA checks apply.
-The keyUsage extension must be absent or it must have the CRL signing bit
-set.
+=item B<Timestamp Signing> (C<timestampsign>)
-=item B<CRL Signing CA>
+For target certificates, if the key usage extension is present, it must include
+C<digitalSignature> and/or C<nonRepudiation> and must not include other bits.
+The EKU extension must be present and contain C<timeStamping> only.
+Moreover, it must be marked as critical.
-The normal CA tests apply. Except in this case the basicConstraints extension
-must be present.
+For all other certifcates the normal CA checks apply.
=back
=head1 BUGS
The issuer checks still suffer from limitations in the underlying X509_LOOKUP
API. One consequence of this is that trusted certificates with matching
subject name must appear in a file (as specified by the B<-CAfile> option),
a directory (as specified by B<-CApath>),
or a store (as specified by B<-CAstore>).
If there are multiple such matches, possibly in multiple locations,
only the first one (in the mentioned order of locations) is recognised.
=head1 SEE ALSO
L<X509_verify_cert(3)>,
+L<OCSP_basic_verify(3)>,
L<openssl-verify(1)>,
L<openssl-ocsp(1)>,
L<openssl-ts(1)>,
L<openssl-s_client(1)>,
L<openssl-s_server(1)>,
L<openssl-smime(1)>,
L<openssl-cmp(1)>,
L<openssl-cms(1)>
=head1 HISTORY
The checks enabled by B<-x509_strict> have been extended in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man1/openssl.pod b/crypto/openssl/doc/man1/openssl.pod
index 201428e87004..4865e5c33e6e 100644
--- a/crypto/openssl/doc/man1/openssl.pod
+++ b/crypto/openssl/doc/man1/openssl.pod
@@ -1,843 +1,754 @@
=pod
=head1 NAME
openssl - OpenSSL command line program
=head1 SYNOPSIS
B<openssl>
I<command>
[ I<options> ... ]
[ I<parameters> ... ]
B<openssl> B<no->I<XXX> [ I<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 program 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 and Message Authentication Codes
o Encryption and Decryption with Ciphers
o SSL/TLS Client and Server Tests
o Handling of S/MIME signed or encrypted mail
o Timestamp requests, generation and verification
=head1 COMMAND SUMMARY
The B<openssl> program provides a rich variety of commands (I<command> in
the L</SYNOPSIS> above).
Each command can have many options and argument parameters, shown above as
I<options> and I<parameters>.
Detailed documentation and use cases for most standard subcommands are available
(e.g., L<openssl-x509(1)>). The subcommand L<openssl-list(1)> may be used to list
subcommands.
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 Configuration Option
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 default name of the file is F<openssl.cnf> in the default certificate
storage area, which can be determined from the L<openssl-version(1)>
command using the B<-d> or B<-a> option.
The environment variable B<OPENSSL_CONF> can be used to specify a different
file location or to disable loading a configuration (using the empty string).
Among others, the configuration file can be used to load modules
and to specify parameters for generating certificates and random numbers.
See L<config(5)> for details.
=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) command.
=item B<crl>
Certificate Revocation List (CRL) Management.
=item B<crl2pkcs7>
CRL to PKCS#7 Conversion.
=item B<dgst>
Message Digest calculation. MAC calculations are superseded by
L<openssl-mac(1)>.
=item B<dhparam>
Generation and Management of Diffie-Hellman Parameters. Superseded by
L<openssl-genpkey(1)> and L<openssl-pkeyparam(1)>.
=item B<dsa>
DSA Data Management.
=item B<dsaparam>
DSA Parameter Generation and Management. Superseded by
L<openssl-genpkey(1)> and L<openssl-pkeyparam(1)>.
=item B<ec>
EC (Elliptic curve) key processing.
=item B<ecparam>
EC parameter manipulation and generation.
=item B<enc>
Encryption, decryption, and encoding.
=item B<engine>
Engine (loadable module) information and manipulation.
=item B<errstr>
Error Number to Error String Conversion.
=item B<fipsinstall>
FIPS configuration installation.
=item B<gendsa>
Generation of DSA Private Key from Parameters. Superseded by
L<openssl-genpkey(1)> and L<openssl-pkey(1)>.
=item B<genpkey>
Generation of Private Key or Parameters.
=item B<genrsa>
Generation of RSA Private Key. Superseded by L<openssl-genpkey(1)>.
=item B<help>
Display information about a command's options.
=item B<info>
Display diverse information built into the OpenSSL libraries.
=item B<kdf>
Key Derivation Functions.
=item B<list>
List algorithms and features.
=item B<mac>
Message Authentication Code Calculation.
=item B<nseq>
Create or examine a Netscape certificate sequence.
=item B<ocsp>
Online Certificate Status Protocol command.
=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 command.
=item B<pkey>
Public and private key management.
=item B<pkeyparam>
Public key algorithm parameter management.
=item B<pkeyutl>
Public key algorithm cryptographic operation command.
=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 command for signing, verification, encryption, and decryption. Superseded
by L<openssl-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 command.
=item B<srp>
Maintain SRP password file. This command is deprecated.
=item B<storeutl>
Command to list and display certificates, keys, CRLs, etc.
=item B<ts>
Time Stamping Authority command.
=item B<verify>
X.509 Certificate Verification.
See also the L<openssl-verification-options(1)> manual page.
=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 Encryption, Decryption, and Encoding 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<openssl-enc(1)> for more information.
=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.
If an option takes an argument, the "type" of argument is also given.
=item B<-->
This terminates the list of options. It is mostly useful if any filename
parameters start with a minus sign:
openssl verify [flags...] -- -cert1.pem...
=back
=head2 Format Options
See L<openssl-format-options(1)> for manual page.
=head2 Pass Phrase Options
See the L<openssl-passphrase-options(1)> manual page.
=head2 Random State Options
Prior to OpenSSL 1.1.1, it was common for applications to store information
about the state of the random-number generator in a file that was loaded
at startup and rewritten upon exit. On modern operating systems, this is
generally no longer necessary as OpenSSL will seed itself from a trusted
entropy source provided by the operating system. These flags are still
supported for special platforms or circumstances that might require them.
It is generally an error to use the same seed file more than once and
every use of B<-rand> should be paired with B<-writerand>.
=over 4
=item B<-rand> I<files>
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 C<;> for MS-Windows, C<,> for OpenVMS, and C<:> for
all others. Another way to specify multiple files is to repeat this flag
with different filenames.
=item B<-writerand> I<file>
Writes the seed data to the specified I<file> upon exit.
This file can be used in a subsequent command invocation.
=back
=head2 Certificate Verification Options
See the L<openssl-verification-options(1)> manual page.
=head2 Name Format Options
See the L<openssl-namedisplay-options(1)> manual page.
=head2 TLS Version Options
Several commands use SSL, TLS, or DTLS. By default, the commands use TLS and
clients will offer the lowest and highest protocol version they support,
and servers will pick the highest version that the client offers that is also
supported by the server.
The options below can be used to limit which protocol versions are used,
and whether TCP (SSL and TLS) or UDP (DTLS) is used.
Note that not all protocols and flags may be available, depending on how
OpenSSL was built.
=over 4
=item B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>, B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
These options require or disable the use of the specified SSL or TLS protocols.
When a specific TLS version is required, only that version will be offered or
accepted.
Only one specific protocol can be given and it cannot be combined with any of
the B<no_> options.
The B<no_*> options do not work with B<s_time> and B<ciphers> commands but work with
B<s_client> and B<s_server> commands.
=item B<-dtls>, B<-dtls1>, B<-dtls1_2>
These options specify to use DTLS instead of TLS.
With B<-dtls>, clients will negotiate any supported DTLS protocol version.
Use the B<-dtls1> or B<-dtls1_2> options to support only DTLS1.0 or DTLS1.2,
respectively.
=back
=head2 Engine Options
=over 4
=item B<-engine> I<id>
Load the engine identified by I<id> and use all the methods it implements
(algorithms, key storage, etc.), unless specified otherwise in the
command-specific documentation or it is configured to do so, as described in
L<config(5)/Engine Configuration>.
The engine will be used for key ids specified with B<-key> and similar
options when an option like B<-keyform engine> is given.
A special case is the C<loader_attic> engine, which
is meant just for internal OpenSSL testing purposes and
supports loading keys, parameters, certificates, and CRLs from files.
When this engine is used, files with such credentials are read via this engine.
Using the C<file:> schema is optional; a plain file (path) name will do.
=back
Options specifying keys, like B<-key> and similar, can use the generic
OpenSSL engine key loading URI scheme C<org.openssl.engine:> to retrieve
private keys and public keys. The URI syntax is as follows, in simplified
form:
org.openssl.engine:{engineid}:{keyid}
Where C<{engineid}> is the identity/name of the engine, and C<{keyid}> is a
key identifier that's acceptable by that engine. For example, when using an
engine that interfaces against a PKCS#11 implementation, the generic key URI
would be something like this (this happens to be an example for the PKCS#11
engine that's part of OpenSC):
-key org.openssl.engine:pkcs11:label_some-private-key
As a third possibility, for engines and providers that have implemented
their own L<OSSL_STORE_LOADER(3)>, C<org.openssl.engine:> should not be
necessary. For a PKCS#11 implementation that has implemented such a loader,
the PKCS#11 URI as defined in RFC 7512 should be possible to use directly:
-key pkcs11:object=some-private-key;pin-value=1234
=head2 Provider Options
=over 4
=item B<-provider> I<name>
Load and initialize the provider identified by I<name>. The I<name>
can be also a path to the provider module. In that case the provider name
will be the specified path and not just the provider module name.
Interpretation of relative paths is platform specific. The configured
"MODULESDIR" path, B<OPENSSL_MODULES> environment variable, or the path
specified by B<-provider-path> is prepended to relative paths.
See L<provider(7)> for a more detailed description.
=item B<-provider-path> I<path>
Specifies the search path that is to be used for looking for providers.
Equivalently, the B<OPENSSL_MODULES> environment variable may be set.
=item B<-propquery> I<propq>
Specifies the I<property query clause> to be used when fetching algorithms
from the loaded providers.
See L<property(7)> for a more detailed description.
=back
=head1 ENVIRONMENT
-The OpenSSL library can be take some configuration parameters from the
-environment. Some of these variables are listed below. For information
-about specific commands, see L<openssl-engine(1)>,
-L<openssl-rehash(1)>, and L<tsget(1)>.
-
-For information about the use of environment variables in configuration,
-see L<config(5)/ENVIRONMENT>.
-
-For information about querying or specifying CPU architecture flags, see
-L<OPENSSL_ia32cap(3)>, and L<OPENSSL_s390xcap(3)>.
+The OpenSSL libraries can take some configuration parameters from the
+environment.
For information about all environment variables used by the OpenSSL libraries,
+such as B<OPENSSL_CONF>, B<OPENSSL_MODULES>, and B<OPENSSL_TRACE>,
see L<openssl-env(7)>.
-=over 4
-
-=item B<OPENSSL_TRACE=>I<name>[,...]
-
-Enable tracing output of OpenSSL library, by name.
-This output will only make sense if you know OpenSSL internals well.
-Also, it might not give you any output at all, depending on how
-OpenSSL was built.
-
-The value is a comma separated list of names, with the following
-available:
-
-=over 4
-
-=item B<TRACE>
-
-Traces the OpenSSL trace API itself.
-
-=item B<INIT>
-
-Traces OpenSSL library initialization and cleanup.
-
-=item B<TLS>
-
-Traces the TLS/SSL protocol.
-
-=item B<TLS_CIPHER>
-
-Traces the ciphers used by the TLS/SSL protocol.
-
-=item B<CONF>
-
-Show details about provider and engine configuration.
-
-=item B<ENGINE_TABLE>
-
-The function that is used by RSA, DSA (etc) code to select registered
-ENGINEs, cache defaults and functional references (etc), will generate
-debugging summaries.
-
-=item B<ENGINE_REF_COUNT>
-
-Reference counts in the ENGINE structure will be monitored with a line
-of generated for each change.
-
-=item B<PKCS5V2>
-
-Traces PKCS#5 v2 key generation.
-
-=item B<PKCS12_KEYGEN>
-
-Traces PKCS#12 key generation.
-
-=item B<PKCS12_DECRYPT>
-
-Traces PKCS#12 decryption.
-
-=item B<X509V3_POLICY>
-
-Generates the complete policy tree at various points during X.509 v3
-policy evaluation.
-
-=item B<BN_CTX>
-
-Traces BIGNUM context operations.
-
-=item B<CMP>
-
-Traces CMP client and server activity.
-
-=item B<STORE>
-
-Traces STORE operations.
-
-=item B<DECODER>
-
-Traces decoder operations.
-
-=item B<ENCODER>
-
-Traces encoder operations.
-
-=item B<REF_COUNT>
-
-Traces decrementing certain ASN.1 structure references.
+For information about the use of environment variables in configuration,
+see L<config(5)/ENVIRONMENT>.
-=back
+For information about specific commands, see L<openssl-engine(1)>,
+L<openssl-rehash(1)>, and L<tsget(1)>.
-=back
+For information about querying or specifying CPU architecture flags, see
+L<OPENSSL_ia32cap(3)>, and L<OPENSSL_s390xcap(3)>.
-=head1 SEE ALSO
L<openssl-asn1parse(1)>,
L<openssl-ca(1)>,
L<openssl-ciphers(1)>,
L<openssl-cms(1)>,
L<openssl-crl(1)>,
L<openssl-crl2pkcs7(1)>,
L<openssl-dgst(1)>,
L<openssl-dhparam(1)>,
L<openssl-dsa(1)>,
L<openssl-dsaparam(1)>,
L<openssl-ec(1)>,
L<openssl-ecparam(1)>,
L<openssl-enc(1)>,
L<openssl-engine(1)>,
L<openssl-errstr(1)>,
L<openssl-gendsa(1)>,
L<openssl-genpkey(1)>,
L<openssl-genrsa(1)>,
L<openssl-kdf(1)>,
L<openssl-list(1)>,
L<openssl-mac(1)>,
L<openssl-nseq(1)>,
L<openssl-ocsp(1)>,
L<openssl-passwd(1)>,
L<openssl-pkcs12(1)>,
L<openssl-pkcs7(1)>,
L<openssl-pkcs8(1)>,
L<openssl-pkey(1)>,
L<openssl-pkeyparam(1)>,
L<openssl-pkeyutl(1)>,
L<openssl-prime(1)>,
L<openssl-rand(1)>,
L<openssl-rehash(1)>,
L<openssl-req(1)>,
L<openssl-rsa(1)>,
L<openssl-rsautl(1)>,
L<openssl-s_client(1)>,
L<openssl-s_server(1)>,
L<openssl-s_time(1)>,
L<openssl-sess_id(1)>,
L<openssl-smime(1)>,
L<openssl-speed(1)>,
L<openssl-spkac(1)>,
L<openssl-srp(1)>,
L<openssl-storeutl(1)>,
L<openssl-ts(1)>,
L<openssl-verify(1)>,
L<openssl-version(1)>,
L<openssl-x509(1)>,
L<config(5)>,
L<crypto(7)>,
L<openssl-env(7)>.
L<ssl(7)>,
L<x509v3_config(5)>
=head1 HISTORY
The B<list> -I<XXX>B<-algorithms> options were added in OpenSSL 1.0.0;
For notes on the availability of other commands, see their individual
manual pages.
The B<-issuer_checks> option is deprecated as of OpenSSL 1.1.0 and
is silently ignored.
The B<-xcertform> and B<-xkeyform> options
are obsolete since OpenSSL 3.0 and have no effect.
The interactive mode, which could be invoked by running C<openssl>
with no further arguments, was removed in OpenSSL 3.0, and running
that program with no arguments is now equivalent to C<openssl help>.
=head1 COPYRIGHT
Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/ASN1_TIME_set.pod b/crypto/openssl/doc/man3/ASN1_TIME_set.pod
index 66d9fefe1af6..bdef3fdbb155 100644
--- a/crypto/openssl/doc/man3/ASN1_TIME_set.pod
+++ b/crypto/openssl/doc/man3/ASN1_TIME_set.pod
@@ -1,282 +1,286 @@
=pod
=head1 NAME
ASN1_TIME_set, ASN1_UTCTIME_set, ASN1_GENERALIZEDTIME_set,
ASN1_TIME_adj, ASN1_UTCTIME_adj, ASN1_GENERALIZEDTIME_adj,
ASN1_TIME_check, ASN1_UTCTIME_check, ASN1_GENERALIZEDTIME_check,
ASN1_TIME_set_string, ASN1_UTCTIME_set_string, ASN1_GENERALIZEDTIME_set_string,
ASN1_TIME_set_string_X509,
ASN1_TIME_normalize,
ASN1_TIME_to_tm,
ASN1_TIME_print, ASN1_TIME_print_ex, ASN1_UTCTIME_print, ASN1_GENERALIZEDTIME_print,
ASN1_TIME_diff,
ASN1_TIME_cmp_time_t, ASN1_UTCTIME_cmp_time_t,
ASN1_TIME_compare,
ASN1_TIME_to_generalizedtime,
ASN1_TIME_dup, ASN1_UTCTIME_dup, ASN1_GENERALIZEDTIME_dup - ASN.1 Time functions
=head1 SYNOPSIS
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
time_t t);
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day,
long offset_sec);
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
int offset_day, long offset_sec);
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
time_t t, int offset_day,
long offset_sec);
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str);
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s,
const char *str);
int ASN1_TIME_normalize(ASN1_TIME *s);
int ASN1_TIME_check(const ASN1_TIME *t);
int ASN1_UTCTIME_check(const ASN1_UTCTIME *t);
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *t);
int ASN1_TIME_print(BIO *b, const ASN1_TIME *s);
int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags);
int ASN1_UTCTIME_print(BIO *b, const ASN1_UTCTIME *s);
int ASN1_GENERALIZEDTIME_print(BIO *b, const ASN1_GENERALIZEDTIME *s);
int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);
int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from,
const ASN1_TIME *to);
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t);
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b);
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out);
ASN1_TIME *ASN1_TIME_dup(const ASN1_TIME *t);
ASN1_UTCTIME *ASN1_UTCTIME_dup(const ASN1_UTCTIME *t);
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_dup(const ASN1_GENERALIZEDTIME *t);
=head1 DESCRIPTION
The ASN1_TIME_set(), ASN1_UTCTIME_set() and ASN1_GENERALIZEDTIME_set()
functions set the structure I<s> to the time represented by the time_t
value I<t>. If I<s> is NULL a new time structure is allocated and returned.
The ASN1_TIME_adj(), ASN1_UTCTIME_adj() and ASN1_GENERALIZEDTIME_adj()
functions set the time structure I<s> to the time represented
by the time I<offset_day> and I<offset_sec> after the time_t value I<t>.
The values of I<offset_day> or I<offset_sec> can be negative to set a
time before I<t>. The I<offset_sec> value can also exceed the number of
seconds in a day. If I<s> is NULL a new structure is allocated
and returned.
The ASN1_TIME_set_string(), ASN1_UTCTIME_set_string() and
ASN1_GENERALIZEDTIME_set_string() functions set the time structure I<s>
to the time represented by string I<str> which must be in appropriate ASN.1
time format (for example YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ). If I<s> is NULL
this function performs a format check on I<str> only. The string I<str>
is copied into I<s>.
ASN1_TIME_set_string_X509() sets B<ASN1_TIME> structure I<s> to the time
represented by string I<str> which must be in appropriate time format
that RFC 5280 requires, which means it only allows YYMMDDHHMMSSZ and
YYYYMMDDHHMMSSZ (leap second is rejected), all other ASN.1 time format
are not allowed. If I<s> is NULL this function performs a format check
on I<str> only.
The ASN1_TIME_normalize() function converts an B<ASN1_GENERALIZEDTIME> or
B<ASN1_UTCTIME> into a time value that can be used in a certificate. It
should be used after the ASN1_TIME_set_string() functions and before
ASN1_TIME_print() functions to get consistent (i.e. GMT) results.
The ASN1_TIME_check(), ASN1_UTCTIME_check() and ASN1_GENERALIZEDTIME_check()
functions check the syntax of the time structure I<s>.
The ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
functions print the time structure I<s> to BIO I<b> in human readable
-format. It will be of the format MMM DD HH:MM:SS YYYY [GMT], for example
-"Feb 3 00:55:52 2015 GMT", which does not include a newline.
+format. It will be of the format MMM DD HH:MM:SS[.s*] YYYY GMT, for example
+"Feb E<32>3 00:55:52 2015 GMT", which does not include a newline.
If the time structure has invalid format it prints out "Bad time value" and
returns an error. The output for generalized time may include a fractional part
following the second.
ASN1_TIME_print_ex() provides I<flags> to specify the output format of the
datetime. This can be either B<ASN1_DTFLGS_RFC822> or B<ASN1_DTFLGS_ISO8601>.
ASN1_TIME_to_tm() converts the time I<s> to the standard I<tm> structure.
If I<s> is NULL, then the current time is converted. The output time is GMT.
The I<tm_sec>, I<tm_min>, I<tm_hour>, I<tm_mday>, I<tm_wday>, I<tm_yday>,
I<tm_mon> and I<tm_year> fields of I<tm> structure are set to proper values,
whereas all other fields are set to 0. If I<tm> is NULL this function performs
a format check on I<s> only. If I<s> is in Generalized format with fractional
seconds, e.g. YYYYMMDDHHMMSS.SSSZ, the fractional seconds will be lost while
converting I<s> to I<tm> structure.
ASN1_TIME_diff() sets I<*pday> and I<*psec> to the time difference between
I<from> and I<to>. If I<to> represents a time later than I<from> then
one or both (depending on the time difference) of I<*pday> and I<*psec>
will be positive. If I<to> represents a time earlier than I<from> then
one or both of I<*pday> and I<*psec> will be negative. If I<to> and I<from>
represent the same time then I<*pday> and I<*psec> will both be zero.
If both I<*pday> and I<*psec> are nonzero they will always have the same
sign. The value of I<*psec> will always be less than the number of seconds
in a day. If I<from> or I<to> is NULL the current time is used.
The ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() functions compare
the two times represented by the time structure I<s> and the time_t I<t>.
The ASN1_TIME_compare() function compares the two times represented by the
time structures I<a> and I<b>.
The ASN1_TIME_to_generalizedtime() function converts an B<ASN1_TIME> to an
B<ASN1_GENERALIZEDTIME>, regardless of year. If either I<out> or
I<*out> are NULL, then a new object is allocated and must be freed after use.
The ASN1_TIME_dup(), ASN1_UTCTIME_dup() and ASN1_GENERALIZEDTIME_dup() functions
duplicate the time structure I<t> and return the duplicated result
correspondingly.
=head1 NOTES
The B<ASN1_TIME> structure corresponds to the ASN.1 structure B<Time>
defined in RFC5280 et al. The time setting functions obey the rules outlined
in RFC5280: if the date can be represented by UTCTime it is used, else
GeneralizedTime is used.
The B<ASN1_TIME>, B<ASN1_UTCTIME> and B<ASN1_GENERALIZEDTIME> structures are
represented as an B<ASN1_STRING> internally and can be freed up using
ASN1_STRING_free().
The B<ASN1_TIME> structure can represent years from 0000 to 9999 but no attempt
is made to correct ancient calendar changes (for example from Julian to
Gregorian calendars).
B<ASN1_UTCTIME> is limited to a year range of 1950 through 2049.
Some applications add offset times directly to a time_t value and pass the
results to ASN1_TIME_set() (or equivalent). This can cause problems as the
time_t value can overflow on some systems resulting in unexpected results.
New applications should use ASN1_TIME_adj() instead and pass the offset value
in the I<offset_sec> and I<offset_day> parameters instead of directly
manipulating a time_t value.
ASN1_TIME_adj() may change the type from B<ASN1_GENERALIZEDTIME> to
B<ASN1_UTCTIME>, or vice versa, based on the resulting year.
ASN1_GENERALIZEDTIME_adj() and ASN1_UTCTIME_adj() will not modify the type
of the return structure.
It is recommended that functions starting with B<ASN1_TIME> be used instead of
those starting with B<ASN1_UTCTIME> or B<ASN1_GENERALIZEDTIME>. The functions
starting with B<ASN1_UTCTIME> and B<ASN1_GENERALIZEDTIME> act only on that
specific time format. The functions starting with B<ASN1_TIME> will operate on
either format.
+Users familiar with RFC822 should note that when specifying the flag
+B<ASN1_DTFLGS_RFC822> the year will be formatted as documented above,
+i.e., using 4 digits, not 2 as specified in RFC822.
+
=head1 BUGS
ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print() do
not print out the timezone: it either prints out "GMT" or nothing. But all
certificates complying with RFC5280 et al use GMT anyway.
ASN1_TIME_print(), ASN1_TIME_print_ex(), ASN1_UTCTIME_print() and
ASN1_GENERALIZEDTIME_print() do not distinguish if they fail because
of an I/O error or invalid time format.
Use the ASN1_TIME_normalize() function to normalize the time value before
printing to get GMT results.
=head1 RETURN VALUES
ASN1_TIME_set(), ASN1_UTCTIME_set(), ASN1_GENERALIZEDTIME_set(),
ASN1_TIME_adj(), ASN1_UTCTIME_adj() and ASN1_GENERALIZEDTIME_set() return
a pointer to a time structure or NULL if an error occurred.
ASN1_TIME_set_string(), ASN1_UTCTIME_set_string(),
ASN1_GENERALIZEDTIME_set_string() and ASN1_TIME_set_string_X509() return
1 if the time value is successfully set and 0 otherwise.
ASN1_TIME_normalize() returns 1 on success, and 0 on error.
ASN1_TIME_check(), ASN1_UTCTIME_check and ASN1_GENERALIZEDTIME_check() return 1
if the structure is syntactically correct and 0 otherwise.
ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
return 1 if the time is successfully printed out and
0 if an I/O error occurred an error occurred (I/O error or invalid time format).
ASN1_TIME_to_tm() returns 1 if the time is successfully parsed and 0 if an
error occurred (invalid time format).
ASN1_TIME_diff() returns 1 for success and 0 for failure. It can fail if the
passed-in time structure has invalid syntax, for example.
ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() return -1 if I<s> is
before I<t>, 0 if I<s> equals I<t>, or 1 if I<s> is after I<t>. -2 is returned
on error.
ASN1_TIME_compare() returns -1 if I<a> is before I<b>, 0 if I<a> equals I<b>,
or 1 if I<a> is after I<b>. -2 is returned on error.
ASN1_TIME_to_generalizedtime() returns a pointer to the appropriate time
structure on success or NULL if an error occurred.
ASN1_TIME_dup(), ASN1_UTCTIME_dup() and ASN1_GENERALIZEDTIME_dup() return a
pointer to a time structure or NULL if an error occurred.
=head1 EXAMPLES
Set a time structure to one hour after the current time and print it out:
#include <time.h>
#include <openssl/asn1.h>
ASN1_TIME *tm;
time_t t;
BIO *b;
t = time(NULL);
tm = ASN1_TIME_adj(NULL, t, 0, 60 * 60);
b = BIO_new_fp(stdout, BIO_NOCLOSE);
ASN1_TIME_print(b, tm);
ASN1_STRING_free(tm);
BIO_free(b);
Determine if one time is later or sooner than the current time:
int day, sec;
if (!ASN1_TIME_diff(&day, &sec, NULL, to))
/* Invalid time format */
if (day > 0 || sec > 0)
printf("Later\n");
else if (day < 0 || sec < 0)
printf("Sooner\n");
else
printf("Same\n");
=head1 HISTORY
The ASN1_TIME_to_tm() function was added in OpenSSL 1.1.1.
The ASN1_TIME_set_string_X509() function was added in OpenSSL 1.1.1.
The ASN1_TIME_normalize() function was added in OpenSSL 1.1.1.
The ASN1_TIME_cmp_time_t() function was added in OpenSSL 1.1.1.
The ASN1_TIME_compare() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/ASN1_aux_cb.pod b/crypto/openssl/doc/man3/ASN1_aux_cb.pod
index f87b51d5efac..9963ea135025 100644
--- a/crypto/openssl/doc/man3/ASN1_aux_cb.pod
+++ b/crypto/openssl/doc/man3/ASN1_aux_cb.pod
@@ -1,284 +1,284 @@
=pod
=head1 NAME
ASN1_AUX, ASN1_PRINT_ARG, ASN1_STREAM_ARG, ASN1_aux_cb, ASN1_aux_const_cb
- ASN.1 auxiliary data
=head1 SYNOPSIS
#include <openssl/asn1t.h>
struct ASN1_AUX_st {
void *app_data;
int flags;
int ref_offset; /* Offset of reference value */
int ref_lock; /* Offset to an CRYPTO_RWLOCK */
ASN1_aux_cb *asn1_cb;
int enc_offset; /* Offset of ASN1_ENCODING structure */
ASN1_aux_const_cb *asn1_const_cb; /* for ASN1_OP_I2D_ and ASN1_OP_PRINT_ */
};
typedef struct ASN1_AUX_st ASN1_AUX;
struct ASN1_PRINT_ARG_st {
BIO *out;
int indent;
const ASN1_PCTX *pctx;
};
typedef struct ASN1_PRINT_ARG_st ASN1_PRINT_ARG;
struct ASN1_STREAM_ARG_st {
BIO *out;
BIO *ndef_bio;
unsigned char **boundary;
};
typedef struct ASN1_STREAM_ARG_st ASN1_STREAM_ARG;
typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
void *exarg);
typedef int ASN1_aux_const_cb(int operation, const ASN1_VALUE **in,
const ASN1_ITEM *it, void *exarg);
=head1 DESCRIPTION
ASN.1 data structures can be associated with an B<ASN1_AUX> object to supply
additional information about the ASN.1 structure. An B<ASN1_AUX> structure is
associated with the structure during the definition of the ASN.1 template. For
example an B<ASN1_AUX> structure will be associated by using one of the various
ASN.1 template definition macros that supply auxiliary information such as
ASN1_SEQUENCE_enc(), ASN1_SEQUENCE_ref(), ASN1_SEQUENCE_cb_const_cb(),
ASN1_SEQUENCE_const_cb(), ASN1_SEQUENCE_cb() or ASN1_NDEF_SEQUENCE_cb().
An B<ASN1_AUX> structure contains the following information.
=over 4
=item I<app_data>
Arbitrary application data
=item I<flags>
Flags which indicate the auxiliarly functionality supported.
The B<ASN1_AFLG_REFCOUNT> flag indicates that objects support reference counting.
The B<ASN1_AFLG_ENCODING> flag indicates that the original encoding of the
object will be saved.
The B<ASN1_AFLG_BROKEN> flag is a work around for broken encoders where the
sequence length value may not be correct. This should generally not be used.
The B<ASN1_AFLG_CONST_CB> flag indicates that the "const" form of the
B<ASN1_AUX> callback should be used in preference to the non-const form.
=item I<ref_offset>
If the B<ASN1_AFLG_REFCOUNT> flag is set then this value is assumed to be an
offset into the B<ASN1_VALUE> structure where a B<CRYPTO_REF_COUNT> may be
found for the purposes of reference counting.
=item I<ref_lock>
If the B<ASN1_AFLG_REFCOUNT> flag is set then this value is assumed to be an
offset into the B<ASN1_VALUE> structure where a B<CRYPTO_RWLOCK> may be
found for the purposes of reference counting.
=item I<asn1_cb>
A callback that will be invoked at various points during the processing of
-the the B<ASN1_VALLUE>. See below for further details.
+the B<ASN1_VALUE>. See below for further details.
=item I<enc_offset>
Offset into the B<ASN1_VALUE> object where the original encoding of the object
will be saved if the B<ASN1_AFLG_ENCODING> flag has been set.
=item I<asn1_const_cb>
A callback that will be invoked at various points during the processing of
-the the B<ASN1_VALLUE>. This is used in preference to the I<asn1_cb> callback if
+the B<ASN1_VALUE>. This is used in preference to the I<asn1_cb> callback if
the B<ASN1_AFLG_CONST_CB> flag is set. See below for further details.
=back
During the processing of an B<ASN1_VALUE> object the callbacks set via
I<asn1_cb> or I<asn1_const_cb> will be invoked as a result of various events
indicated via the I<operation> parameter. The value of I<*in> will be the
B<ASN1_VALUE> object being processed based on the template in I<it>. An
additional operation specific parameter may be passed in I<exarg>. The currently
supported operations are as follows. The callbacks should return a positive
value on success or zero on error, unless otherwise noted below.
=over 4
=item B<ASN1_OP_NEW_PRE>
Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
prior to an B<ASN1_VALUE> object being allocated. The callback may allocate the
B<ASN1_VALUE> itself and store it in I<*pval>. If it does so it should return 2
from the callback. On error it should return 0.
=item B<ASN1_OP_NEW_POST>
Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
after an B<ASN1_VALUE> object has been allocated. The allocated object is in
I<*pval>.
=item B<ASN1_OP_FREE_PRE>
Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
immediately before an B<ASN1_VALUE> is freed. If the callback originally
constructed the B<ASN1_VALUE> via B<ASN1_OP_NEW_PRE> then it should free it at
this point and return 2 from the callback. Otherwise it should return 1 for
success or 0 on error.
=item B<ASN1_OP_FREE_POST>
Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
immediately after B<ASN1_VALUE> sub-structures are freed.
=item B<ASN1_OP_D2I_PRE>
Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
immediately before a "d2i" operation for the B<ASN1_VALUE>.
=item B<ASN1_OP_D2I_POST>
Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
immediately after a "d2i" operation for the B<ASN1_VALUE>.
=item B<ASN1_OP_I2D_PRE>
Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
immediately before a "i2d" operation for the B<ASN1_VALUE>.
=item B<ASN1_OP_I2D_POST>
Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
immediately after a "i2d" operation for the B<ASN1_VALUE>.
=item B<ASN1_OP_PRINT_PRE>
Invoked when processing a B<SEQUENCE> or B<NDEF_SEQUENCE> structure immediately
before printing the B<ASN1_VALUE>. The I<exarg> argument will be a pointer to an
B<ASN1_PRINT_ARG> structure (see below).
=item B<ASN1_OP_PRINT_POST>
Invoked when processing a B<SEQUENCE> or B<NDEF_SEQUENCE> structure immediately
after printing the B<ASN1_VALUE>. The I<exarg> argument will be a pointer to an
B<ASN1_PRINT_ARG> structure (see below).
=item B<ASN1_OP_STREAM_PRE>
Invoked immediately prior to streaming the B<ASN1_VALUE> data using indefinite
length encoding. The I<exarg> argument will be a pointer to a B<ASN1_STREAM_ARG>
structure (see below).
=item B<ASN1_OP_STREAM_POST>
Invoked immediately after streaming the B<ASN1_VALUE> data using indefinite
length encoding. The I<exarg> argument will be a pointer to a B<ASN1_STREAM_ARG>
structure (see below).
=item B<ASN1_OP_DETACHED_PRE>
Invoked immediately prior to processing the B<ASN1_VALUE> data as a "detached"
value (as used in CMS and PKCS7). The I<exarg> argument will be a pointer to a
B<ASN1_STREAM_ARG> structure (see below).
=item B<ASN1_OP_DETACHED_POST>
Invoked immediately after processing the B<ASN1_VALUE> data as a "detached"
value (as used in CMS and PKCS7). The I<exarg> argument will be a pointer to a
B<ASN1_STREAM_ARG> structure (see below).
=item B<ASN1_OP_DUP_PRE>
Invoked immediate prior to an ASN1_VALUE being duplicated via a call to
ASN1_item_dup().
=item B<ASN1_OP_DUP_POST>
Invoked immediate after to an ASN1_VALUE has been duplicated via a call to
ASN1_item_dup().
=item B<ASN1_OP_GET0_LIBCTX>
Invoked in order to obtain the B<OSSL_LIB_CTX> associated with an B<ASN1_VALUE>
if any. A pointer to an B<OSSL_LIB_CTX> should be stored in I<*exarg> if such
a value exists.
=item B<ASN1_OP_GET0_PROPQ>
Invoked in order to obtain the property query string associated with an
B<ASN1_VALUE> if any. A pointer to the property query string should be stored in
I<*exarg> if such a value exists.
=back
An B<ASN1_PRINT_ARG> object is used during processing of B<ASN1_OP_PRINT_PRE>
and B<ASN1_OP_PRINT_POST> callback operations. It contains the following
information.
=over 4
=item I<out>
The B<BIO> being used to print the data out.
=item I<ndef_bio>
The current number of indent spaces that should be used for printing this data.
=item I<pctx>
The context for the B<ASN1_PCTX> operation.
=back
An B<ASN1_STREAM_ARG> object is used during processing of B<ASN1_OP_STREAM_PRE>,
B<ASN1_OP_STREAM_POST>, B<ASN1_OP_DETACHED_PRE> and B<ASN1_OP_DETACHED_POST>
callback operations. It contains the following information.
=over 4
=item I<out>
The B<BIO> to stream through
=item I<ndef_bio>
The B<BIO> with filters appended
=item I<boundary>
The streaming I/O boundary.
=back
=head1 RETURN VALUES
The callbacks return 0 on error and a positive value on success. Some operations
require specific positive success values as noted above.
=head1 SEE ALSO
L<ASN1_item_new_ex(3)>
=head1 HISTORY
The ASN1_aux_const_cb() callback and the B<ASN1_OP_GET0_LIBCTX> and
B<ASN1_OP_GET0_PROPQ> operation types were added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/BIO_s_accept.pod b/crypto/openssl/doc/man3/BIO_s_accept.pod
index 25a752998cae..22b3d35b7374 100644
--- a/crypto/openssl/doc/man3/BIO_s_accept.pod
+++ b/crypto/openssl/doc/man3/BIO_s_accept.pod
@@ -1,242 +1,242 @@
=pod
=head1 NAME
BIO_s_accept, BIO_set_accept_name, BIO_set_accept_port, BIO_get_accept_name,
BIO_get_accept_port, BIO_new_accept, BIO_set_nbio_accept, BIO_set_accept_bios,
BIO_get_peer_name, BIO_get_peer_port,
BIO_get_accept_ip_family, BIO_set_accept_ip_family,
BIO_set_bind_mode, BIO_get_bind_mode, BIO_do_accept - accept BIO
=head1 SYNOPSIS
#include <openssl/bio.h>
const BIO_METHOD *BIO_s_accept(void);
long BIO_set_accept_name(BIO *b, char *name);
char *BIO_get_accept_name(BIO *b);
long BIO_set_accept_port(BIO *b, char *port);
char *BIO_get_accept_port(BIO *b);
BIO *BIO_new_accept(char *host_port);
long BIO_set_nbio_accept(BIO *b, int n);
long BIO_set_accept_bios(BIO *b, char *bio);
char *BIO_get_peer_name(BIO *b);
char *BIO_get_peer_port(BIO *b);
long BIO_get_accept_ip_family(BIO *b);
long BIO_set_accept_ip_family(BIO *b, long family);
long BIO_set_bind_mode(BIO *b, long mode);
long BIO_get_bind_mode(BIO *b);
int BIO_do_accept(BIO *b);
=head1 DESCRIPTION
BIO_s_accept() returns the accept BIO method. This is a wrapper
round the platform's TCP/IP socket accept routines.
Using accept BIOs, TCP/IP connections can be accepted and data
transferred using only BIO routines. In this way any platform
specific operations are hidden by the BIO abstraction.
Read and write operations on an accept BIO will perform I/O
on the underlying connection. If no connection is established
and the port (see below) is set up properly then the BIO
waits for an incoming connection.
Accept BIOs support BIO_puts() but not BIO_gets().
If the close flag is set on an accept BIO then any active
connection on that chain is shutdown and the socket closed when
the BIO is freed.
Calling BIO_reset() on an accept BIO will close any active
connection and reset the BIO into a state where it awaits another
incoming connection.
BIO_get_fd() and BIO_set_fd() can be called to retrieve or set
the accept socket. See L<BIO_s_fd(3)>
BIO_set_accept_name() uses the string B<name> to set the accept
name. The name is represented as a string of the form "host:port",
where "host" is the interface to use and "port" is the port.
The host can be "*" or empty which is interpreted as meaning
any interface. If the host is an IPv6 address, it has to be
enclosed in brackets, for example "[::1]:https". "port" has the
same syntax as the port specified in BIO_set_conn_port() for
connect BIOs, that is it can be a numerical port string or a
string to lookup using getservbyname() and a string table.
BIO_set_accept_port() uses the string B<port> to set the accept
port of BIO I<b>. "port" has the same syntax as the port specified in
BIO_set_conn_port() for connect BIOs, that is it can be a numerical
port string or a string to lookup using getservbyname() and a string
table.
If the given port is C<0> then a random available port is chosen.
It may be queried using BIO_sock_info() and L<BIO_ADDR_service_string(3)>.
BIO_new_accept() combines BIO_new() and BIO_set_accept_name() into
a single call: that is it creates a new accept BIO with port
B<host_port>.
BIO_set_nbio_accept() sets the accept socket to blocking mode
(the default) if B<n> is 0 or non blocking mode if B<n> is 1.
BIO_set_accept_bios() can be used to set a chain of BIOs which
will be duplicated and prepended to the chain when an incoming
connection is received. This is useful if, for example, a
buffering or SSL BIO is required for each connection. The
chain of BIOs must not be freed after this call, they will
be automatically freed when the accept BIO is freed.
BIO_get_accept_ip_family() returns the IP family accepted by the BIO I<b>,
which may be B<BIO_FAMILY_IPV4>, B<BIO_FAMILY_IPV6>, or B<BIO_FAMILY_IPANY>.
BIO_set_accept_ip_family() sets the IP family I<family> accepted by BIO I<b>.
The default is B<BIO_FAMILY_IPANY>.
BIO_set_bind_mode() and BIO_get_bind_mode() set and retrieve
the current bind mode. If B<BIO_BIND_NORMAL> (the default) is set
then another socket cannot be bound to the same port. If
B<BIO_BIND_REUSEADDR> is set then other sockets can bind to the
same port. If B<BIO_BIND_REUSEADDR_IF_UNUSED> is set then and
attempt is first made to use BIO_BIN_NORMAL, if this fails
and the port is not in use then a second attempt is made
using B<BIO_BIND_REUSEADDR>.
BIO_do_accept() serves two functions. When it is first
called, after the accept BIO has been setup, it will attempt
to create the accept socket and bind an address to it. Second
and subsequent calls to BIO_do_accept() will await an incoming
connection, or request a retry in non blocking mode.
=head1 NOTES
When an accept BIO is at the end of a chain it will await an
incoming connection before processing I/O calls. When an accept
BIO is not at then end of a chain it passes I/O calls to the next
BIO in the chain.
When a connection is established a new socket BIO is created for
the connection and appended to the chain. That is the chain is now
accept->socket. This effectively means that attempting I/O on
an initial accept socket will await an incoming connection then
perform I/O on it.
If any additional BIOs have been set using BIO_set_accept_bios()
then they are placed between the socket and the accept BIO,
that is the chain will be accept->otherbios->socket.
If a server wishes to process multiple connections (as is normally
the case) then the accept BIO must be made available for further
incoming connections. This can be done by waiting for a connection and
then calling:
connection = BIO_pop(accept);
After this call B<connection> will contain a BIO for the recently
established connection and B<accept> will now be a single BIO
again which can be used to await further incoming connections.
If no further connections will be accepted the B<accept> can
be freed using BIO_free().
If only a single connection will be processed it is possible to
perform I/O using the accept BIO itself. This is often undesirable
however because the accept BIO will still accept additional incoming
connections. This can be resolved by using BIO_pop() (see above)
and freeing up the accept BIO after the initial connection.
If the underlying accept socket is nonblocking and BIO_do_accept() is
called to await an incoming connection it is possible for
BIO_should_io_special() with the reason BIO_RR_ACCEPT. If this happens
then it is an indication that an accept attempt would block: the application
should take appropriate action to wait until the underlying socket has
accepted a connection and retry the call.
BIO_set_accept_name(), BIO_get_accept_name(), BIO_set_accept_port(),
BIO_get_accept_port(), BIO_set_nbio_accept(), BIO_set_accept_bios(),
BIO_get_peer_name(), BIO_get_peer_port(),
BIO_get_accept_ip_family(), BIO_set_accept_ip_family(),
BIO_set_bind_mode(), BIO_get_bind_mode() and BIO_do_accept() are macros.
=head1 RETURN VALUES
BIO_do_accept(),
BIO_set_accept_name(), BIO_set_accept_port(), BIO_set_nbio_accept(),
BIO_set_accept_bios(), BIO_set_accept_ip_family(), and BIO_set_bind_mode()
-return 1 for success and <=0 for failure.
+return 1 for success and <= 0 for failure.
BIO_get_accept_name() returns the accept name or NULL on error.
BIO_get_peer_name() returns the peer name or NULL on error.
BIO_get_accept_port() returns the accept port as a string or NULL on error.
BIO_get_peer_port() returns the peer port as a string or NULL on error.
-BIO_get_accept_ip_family() returns the IP family or <=0 on error.
+BIO_get_accept_ip_family() returns the IP family or <= 0 on error.
-BIO_get_bind_mode() returns the set of B<BIO_BIND> flags, or <=0 on failure.
+BIO_get_bind_mode() returns the set of B<BIO_BIND> flags, or <= 0 on failure.
BIO_new_accept() returns a BIO or NULL on error.
=head1 EXAMPLES
This example accepts two connections on port 4444, sends messages
down each and finally closes both down.
BIO *abio, *cbio, *cbio2;
/* First call to BIO_do_accept() sets up accept BIO */
abio = BIO_new_accept("4444");
if (BIO_do_accept(abio) <= 0) {
fprintf(stderr, "Error setting up accept\n");
ERR_print_errors_fp(stderr);
exit(1);
}
/* Wait for incoming connection */
if (BIO_do_accept(abio) <= 0) {
fprintf(stderr, "Error accepting connection\n");
ERR_print_errors_fp(stderr);
exit(1);
}
fprintf(stderr, "Connection 1 established\n");
/* Retrieve BIO for connection */
cbio = BIO_pop(abio);
BIO_puts(cbio, "Connection 1: Sending out Data on initial connection\n");
fprintf(stderr, "Sent out data on connection 1\n");
/* Wait for another connection */
if (BIO_do_accept(abio) <= 0) {
fprintf(stderr, "Error accepting connection\n");
ERR_print_errors_fp(stderr);
exit(1);
}
fprintf(stderr, "Connection 2 established\n");
/* Close accept BIO to refuse further connections */
cbio2 = BIO_pop(abio);
BIO_free(abio);
BIO_puts(cbio2, "Connection 2: Sending out Data on second\n");
fprintf(stderr, "Sent out data on connection 2\n");
BIO_puts(cbio, "Connection 1: Second connection established\n");
/* Close the two established connections */
BIO_free(cbio);
BIO_free(cbio2);
=head1 COPYRIGHT
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/BIO_s_connect.pod b/crypto/openssl/doc/man3/BIO_s_connect.pod
index ab813b32d031..a3c9e6428e47 100644
--- a/crypto/openssl/doc/man3/BIO_s_connect.pod
+++ b/crypto/openssl/doc/man3/BIO_s_connect.pod
@@ -1,211 +1,211 @@
=pod
=head1 NAME
BIO_s_connect, BIO_new_connect,
BIO_set_conn_hostname, BIO_set_conn_port,
BIO_set_conn_address, BIO_set_conn_ip_family,
BIO_get_conn_hostname, BIO_get_conn_port,
BIO_get_conn_address, BIO_get_conn_ip_family,
BIO_set_nbio, BIO_do_connect - connect BIO
=head1 SYNOPSIS
#include <openssl/bio.h>
const BIO_METHOD *BIO_s_connect(void);
BIO *BIO_new_connect(const char *name);
long BIO_set_conn_hostname(BIO *b, char *name);
long BIO_set_conn_port(BIO *b, char *port);
long BIO_set_conn_address(BIO *b, BIO_ADDR *addr);
long BIO_set_conn_ip_family(BIO *b, long family);
const char *BIO_get_conn_hostname(BIO *b);
const char *BIO_get_conn_port(BIO *b);
const BIO_ADDR *BIO_get_conn_address(BIO *b);
const long BIO_get_conn_ip_family(BIO *b);
long BIO_set_nbio(BIO *b, long n);
long BIO_do_connect(BIO *b);
=head1 DESCRIPTION
BIO_s_connect() returns the connect BIO method. This is a wrapper
round the platform's TCP/IP socket connection routines.
Using connect BIOs, TCP/IP connections can be made and data
transferred using only BIO routines. In this way any platform
specific operations are hidden by the BIO abstraction.
Read and write operations on a connect BIO will perform I/O
on the underlying connection. If no connection is established
and the port and hostname (see below) is set up properly then
a connection is established first.
Connect BIOs support BIO_puts() but not BIO_gets().
If the close flag is set on a connect BIO then any active
connection is shutdown and the socket closed when the BIO
is freed.
Calling BIO_reset() on a connect BIO will close any active
connection and reset the BIO into a state where it can connect
to the same host again.
BIO_new_connect() combines BIO_new() and BIO_set_conn_hostname() into
a single call: that is it creates a new connect BIO with hostname B<name>.
BIO_set_conn_hostname() uses the string B<name> to set the hostname.
The hostname can be an IP address; if the address is an IPv6 one, it
-must be enclosed with brackets C<[> and C<]>.
+must be enclosed in brackets C<[> and C<]>.
The hostname can also include the port in the form hostname:port;
see L<BIO_parse_hostserv(3)> and BIO_set_conn_port() for details.
BIO_set_conn_port() sets the port to B<port>. B<port> can be the
numerical form or a service string such as "http", which
will be mapped to a port number using the system function getservbyname().
BIO_set_conn_address() sets the address and port information using
a BIO_ADDR(3ssl).
BIO_set_conn_ip_family() sets the IP family.
BIO_get_conn_hostname() returns the hostname of the connect BIO or
NULL if the BIO is initialized but no hostname is set.
This return value is an internal pointer which should not be modified.
BIO_get_conn_port() returns the port as a string.
This return value is an internal pointer which should not be modified.
BIO_get_conn_address() returns the address information as a BIO_ADDR.
This return value is an internal pointer which should not be modified.
BIO_get_conn_ip_family() returns the IP family of the connect BIO.
BIO_set_nbio() sets the non blocking I/O flag to B<n>. If B<n> is
zero then blocking I/O is set. If B<n> is 1 then non blocking I/O
is set. Blocking I/O is the default. The call to BIO_set_nbio()
should be made before the connection is established because
non blocking I/O is set during the connect process.
BIO_do_connect() attempts to connect the supplied BIO.
This performs an SSL/TLS handshake as far as supported by the BIO.
For non-SSL BIOs the connection is done typically at TCP level.
If domain name resolution yields multiple IP addresses all of them are tried
after connect() failures.
The function returns 1 if the connection was established successfully.
A zero or negative value is returned if the connection could not be established.
The call BIO_should_retry() should be used for non blocking connect BIOs
to determine if the call should be retried.
If a connection has already been established this call has no effect.
=head1 NOTES
If blocking I/O is set then a non positive return value from any
I/O call is caused by an error condition, although a zero return
will normally mean that the connection was closed.
If the port name is supplied as part of the hostname then this will
override any value set with BIO_set_conn_port(). This may be undesirable
if the application does not wish to allow connection to arbitrary
ports. This can be avoided by checking for the presence of the ':'
character in the passed hostname and either indicating an error or
truncating the string at that point.
The values returned by BIO_get_conn_hostname(), BIO_get_conn_address(),
and BIO_get_conn_port() are updated when a connection attempt is made.
Before any connection attempt the values returned are those set by the
application itself.
Applications do not have to call BIO_do_connect() but may wish to do
so to separate the connection process from other I/O processing.
If non blocking I/O is set then retries will be requested as appropriate.
It addition to BIO_should_read() and BIO_should_write() it is also
possible for BIO_should_io_special() to be true during the initial
connection process with the reason BIO_RR_CONNECT. If this is returned
then this is an indication that a connection attempt would block,
the application should then take appropriate action to wait until
the underlying socket has connected and retry the call.
BIO_set_conn_hostname(), BIO_set_conn_port(), BIO_get_conn_hostname(),
BIO_set_conn_address(), BIO_get_conn_port(), BIO_get_conn_address(),
BIO_set_conn_ip_family(), BIO_get_conn_ip_family(),
BIO_set_nbio(), and BIO_do_connect() are macros.
=head1 RETURN VALUES
BIO_s_connect() returns the connect BIO method.
BIO_set_conn_address(), BIO_set_conn_port(), and BIO_set_conn_ip_family()
return 1 or <=0 if an error occurs.
BIO_set_conn_hostname() returns 1 on success and <=0 on failure.
BIO_get_conn_address() returns the address information or NULL if none
was set.
BIO_get_conn_hostname() returns the connected hostname or NULL if
none was set.
BIO_get_conn_ip_family() returns the address family or -1 if none was set.
BIO_get_conn_port() returns a string representing the connected
port or NULL if not set.
BIO_set_nbio() returns 1 or <=0 if an error occurs.
BIO_do_connect() returns 1 if the connection was successfully
established and <=0 if the connection failed.
=head1 EXAMPLES
This is example connects to a webserver on the local host and attempts
to retrieve a page and copy the result to standard output.
BIO *cbio, *out;
int len;
char tmpbuf[1024];
cbio = BIO_new_connect("localhost:http");
out = BIO_new_fp(stdout, BIO_NOCLOSE);
if (BIO_do_connect(cbio) <= 0) {
fprintf(stderr, "Error connecting to server\n");
ERR_print_errors_fp(stderr);
exit(1);
}
BIO_puts(cbio, "GET / HTTP/1.0\n\n");
for (;;) {
len = BIO_read(cbio, tmpbuf, 1024);
if (len <= 0)
break;
BIO_write(out, tmpbuf, len);
}
BIO_free(cbio);
BIO_free(out);
=head1 SEE ALSO
L<BIO_ADDR(3)>, L<BIO_parse_hostserv(3)>
=head1 HISTORY
BIO_set_conn_int_port(), BIO_get_conn_int_port(), BIO_set_conn_ip(), and BIO_get_conn_ip()
were removed in OpenSSL 1.1.0.
Use BIO_set_conn_address() and BIO_get_conn_address() instead.
=head1 COPYRIGHT
Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/ECDSA_sign.pod b/crypto/openssl/doc/man3/ECDSA_sign.pod
index 7e5646665335..88e851885a01 100644
--- a/crypto/openssl/doc/man3/ECDSA_sign.pod
+++ b/crypto/openssl/doc/man3/ECDSA_sign.pod
@@ -1,186 +1,186 @@
=pod
=head1 NAME
ECDSA_size, ECDSA_sign, ECDSA_do_sign,
ECDSA_verify, ECDSA_do_verify, ECDSA_sign_setup, ECDSA_sign_ex,
ECDSA_do_sign_ex - deprecated low-level elliptic curve digital signature algorithm
(ECDSA) functions
=head1 SYNOPSIS
#include <openssl/ecdsa.h>
The following functions have been deprecated since OpenSSL 3.0, and can be
hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
see L<openssl_user_macros(7)>:
int ECDSA_size(const EC_KEY *eckey);
int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len,
EC_KEY *eckey);
int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
const unsigned char *sig, int siglen, EC_KEY *eckey);
int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY* eckey);
ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
const BIGNUM *kinv, const BIGNUM *rp,
EC_KEY *eckey);
int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp);
int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen,
const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
=head1 DESCRIPTION
See L<ECDSA_SIG_new(3)> for a description of the B<ECDSA_SIG> object.
See L<i2d_ECDSA_SIG(3)> and L<d2i_ECDSA_SIG(3)> for information about encoding
and decoding ECDSA signatures to/from DER.
All of the functions described below are deprecated. Applications should
use the higher level B<EVP> interface such as L<EVP_DigestSignInit(3)>
or L<EVP_DigestVerifyInit(3)> instead.
ECDSA_size() returns the maximum length of a DER encoded ECDSA signature
created with the private EC key I<eckey>. To obtain the actual signature
size use L<EVP_PKEY_sign(3)> with a NULL I<sig> parameter.
ECDSA_sign() computes a digital signature of the I<dgstlen> bytes hash value
I<dgst> using the private EC key I<eckey>. The DER encoded signatures is
-stored in I<sig> and its length is returned in I<sig_len>. Note: I<sig> must
+stored in I<sig> and its length is returned in I<siglen>. Note: I<sig> must
point to ECDSA_size(eckey) bytes of memory. The parameter I<type> is currently
ignored. ECDSA_sign() is wrapper function for ECDSA_sign_ex() with I<kinv>
and I<rp> set to NULL.
ECDSA_do_sign() is similar to ECDSA_sign() except the signature is returned
as a newly allocated B<ECDSA_SIG> structure (or NULL on error). ECDSA_do_sign()
is a wrapper function for ECDSA_do_sign_ex() with I<kinv> and I<rp> set to
NULL.
ECDSA_verify() verifies that the signature in I<sig> of size I<siglen> is a
valid ECDSA signature of the hash value I<dgst> of size I<dgstlen> using the
public key I<eckey>. The parameter I<type> is ignored.
ECDSA_do_verify() is similar to ECDSA_verify() except the signature is
presented in the form of a pointer to an B<ECDSA_SIG> structure.
The remaining functions utilise the internal I<kinv> and I<r> values used
during signature computation. Most applications will never need to call these
and some external ECDSA ENGINE implementations may not support them at all if
either I<kinv> or I<r> is not NULL.
ECDSA_sign_setup() may be used to precompute parts of the signing operation.
I<eckey> is the private EC key and I<ctx> is a pointer to B<BN_CTX> structure
(or NULL). The precomputed values or returned in I<kinv> and I<rp> and can be
used in a later call to ECDSA_sign_ex() or ECDSA_do_sign_ex().
ECDSA_sign_ex() computes a digital signature of the I<dgstlen> bytes hash value
I<dgst> using the private EC key I<eckey> and the optional pre-computed values
I<kinv> and I<rp>. The DER encoded signature is stored in I<sig> and its
-length is returned in I<sig_len>. Note: I<sig> must point to ECDSA_size(eckey)
+length is returned in I<siglen>. Note: I<sig> must point to ECDSA_size(eckey)
bytes of memory. The parameter I<type> is ignored.
ECDSA_do_sign_ex() is similar to ECDSA_sign_ex() except the signature is
returned as a newly allocated B<ECDSA_SIG> structure (or NULL on error).
=head1 RETURN VALUES
ECDSA_size() returns the maximum length signature or 0 on error.
ECDSA_sign(), ECDSA_sign_ex() and ECDSA_sign_setup() return 1 if successful
or 0 on error.
ECDSA_do_sign() and ECDSA_do_sign_ex() return a pointer to an allocated
B<ECDSA_SIG> structure or NULL on error.
ECDSA_verify() and ECDSA_do_verify() return 1 for a valid
signature, 0 for an invalid signature and -1 on error.
The error codes can be obtained by L<ERR_get_error(3)>.
=head1 EXAMPLES
Creating an ECDSA signature of a given SHA-256 hash value using the
named curve prime256v1 (aka P-256).
This example uses deprecated functionality. See L</DESCRIPTION>.
First step: create an EC_KEY object (note: this part is B<not> ECDSA
specific)
int ret;
ECDSA_SIG *sig;
EC_KEY *eckey;
eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (eckey == NULL)
/* error */
if (EC_KEY_generate_key(eckey) == 0)
/* error */
Second step: compute the ECDSA signature of a SHA-256 hash value
using ECDSA_do_sign():
sig = ECDSA_do_sign(digest, 32, eckey);
if (sig == NULL)
/* error */
or using ECDSA_sign():
unsigned char *buffer, *pp;
int buf_len;
buf_len = ECDSA_size(eckey);
buffer = OPENSSL_malloc(buf_len);
pp = buffer;
if (ECDSA_sign(0, dgst, dgstlen, pp, &buf_len, eckey) == 0)
/* error */
Third step: verify the created ECDSA signature using ECDSA_do_verify():
ret = ECDSA_do_verify(digest, 32, sig, eckey);
or using ECDSA_verify():
ret = ECDSA_verify(0, digest, 32, buffer, buf_len, eckey);
and finally evaluate the return value:
if (ret == 1)
/* signature ok */
else if (ret == 0)
/* incorrect signature */
else
/* error */
=head1 CONFORMING TO
ANSI X9.62, US Federal Information Processing Standard FIPS186-2
(Digital Signature Standard, DSS)
=head1 SEE ALSO
L<EC_KEY_new(3)>,
L<EVP_DigestSignInit(3)>,
L<EVP_DigestVerifyInit(3)>,
L<EVP_PKEY_sign(3)>
L<i2d_ECDSA_SIG(3)>,
L<d2i_ECDSA_SIG(3)>
=head1 HISTORY
All functionality described here was deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/EVP_EncryptInit.pod b/crypto/openssl/doc/man3/EVP_EncryptInit.pod
index f037d135c9da..a4635f994c2f 100644
--- a/crypto/openssl/doc/man3/EVP_EncryptInit.pod
+++ b/crypto/openssl/doc/man3/EVP_EncryptInit.pod
@@ -1,1748 +1,1756 @@
=pod
=head1 NAME
EVP_CIPHER_fetch,
EVP_CIPHER_up_ref,
EVP_CIPHER_free,
EVP_CIPHER_CTX_new,
EVP_CIPHER_CTX_reset,
EVP_CIPHER_CTX_free,
EVP_EncryptInit_ex,
EVP_EncryptInit_ex2,
EVP_EncryptUpdate,
EVP_EncryptFinal_ex,
EVP_DecryptInit_ex,
EVP_DecryptInit_ex2,
EVP_DecryptUpdate,
EVP_DecryptFinal_ex,
EVP_CipherInit_ex,
EVP_CipherInit_ex2,
EVP_CipherUpdate,
EVP_CipherFinal_ex,
EVP_CIPHER_CTX_set_key_length,
EVP_CIPHER_CTX_ctrl,
EVP_EncryptInit,
EVP_EncryptFinal,
EVP_DecryptInit,
EVP_DecryptFinal,
EVP_CipherInit,
EVP_CipherFinal,
EVP_Cipher,
EVP_get_cipherbyname,
EVP_get_cipherbynid,
EVP_get_cipherbyobj,
EVP_CIPHER_is_a,
EVP_CIPHER_get0_name,
EVP_CIPHER_get0_description,
EVP_CIPHER_names_do_all,
EVP_CIPHER_get0_provider,
EVP_CIPHER_get_nid,
EVP_CIPHER_get_params,
EVP_CIPHER_gettable_params,
EVP_CIPHER_get_block_size,
EVP_CIPHER_get_key_length,
EVP_CIPHER_get_iv_length,
EVP_CIPHER_get_flags,
EVP_CIPHER_get_mode,
EVP_CIPHER_get_type,
EVP_CIPHER_CTX_cipher,
EVP_CIPHER_CTX_get0_cipher,
EVP_CIPHER_CTX_get1_cipher,
EVP_CIPHER_CTX_get0_name,
EVP_CIPHER_CTX_get_nid,
EVP_CIPHER_CTX_get_params,
EVP_CIPHER_gettable_ctx_params,
EVP_CIPHER_CTX_gettable_params,
EVP_CIPHER_CTX_set_params,
EVP_CIPHER_settable_ctx_params,
EVP_CIPHER_CTX_settable_params,
EVP_CIPHER_CTX_get_block_size,
EVP_CIPHER_CTX_get_key_length,
EVP_CIPHER_CTX_get_iv_length,
EVP_CIPHER_CTX_get_tag_length,
EVP_CIPHER_CTX_get_app_data,
EVP_CIPHER_CTX_set_app_data,
EVP_CIPHER_CTX_flags,
EVP_CIPHER_CTX_set_flags,
EVP_CIPHER_CTX_clear_flags,
EVP_CIPHER_CTX_test_flags,
EVP_CIPHER_CTX_get_type,
EVP_CIPHER_CTX_get_mode,
EVP_CIPHER_CTX_get_num,
EVP_CIPHER_CTX_set_num,
EVP_CIPHER_CTX_is_encrypting,
EVP_CIPHER_param_to_asn1,
EVP_CIPHER_asn1_to_param,
EVP_CIPHER_CTX_set_padding,
EVP_enc_null,
EVP_CIPHER_do_all_provided,
EVP_CIPHER_nid,
EVP_CIPHER_name,
EVP_CIPHER_block_size,
EVP_CIPHER_key_length,
EVP_CIPHER_iv_length,
EVP_CIPHER_flags,
EVP_CIPHER_mode,
EVP_CIPHER_type,
EVP_CIPHER_CTX_encrypting,
EVP_CIPHER_CTX_nid,
EVP_CIPHER_CTX_block_size,
EVP_CIPHER_CTX_key_length,
EVP_CIPHER_CTX_iv_length,
EVP_CIPHER_CTX_tag_length,
EVP_CIPHER_CTX_num,
EVP_CIPHER_CTX_type,
EVP_CIPHER_CTX_mode
- EVP cipher routines
=head1 SYNOPSIS
=for openssl generic
#include <openssl/evp.h>
EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
const char *properties);
int EVP_CIPHER_up_ref(EVP_CIPHER *cipher);
void EVP_CIPHER_free(EVP_CIPHER *cipher);
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv);
int EVP_EncryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv,
const OSSL_PARAM params[]);
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv);
int EVP_DecryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv,
const OSSL_PARAM params[]);
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv,
int enc, const OSSL_PARAM params[]);
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv);
int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv);
int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv, int enc);
int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl);
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int cmd, int p1, void *p2);
int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags);
void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags);
int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags);
const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
const EVP_CIPHER *EVP_get_cipherbynid(int nid);
const EVP_CIPHER *EVP_get_cipherbyobj(const ASN1_OBJECT *a);
int EVP_CIPHER_get_nid(const EVP_CIPHER *e);
int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name);
int EVP_CIPHER_names_do_all(const EVP_CIPHER *cipher,
void (*fn)(const char *name, void *data),
void *data);
const char *EVP_CIPHER_get0_name(const EVP_CIPHER *cipher);
const char *EVP_CIPHER_get0_description(const EVP_CIPHER *cipher);
const OSSL_PROVIDER *EVP_CIPHER_get0_provider(const EVP_CIPHER *cipher);
int EVP_CIPHER_get_block_size(const EVP_CIPHER *e);
int EVP_CIPHER_get_key_length(const EVP_CIPHER *e);
int EVP_CIPHER_get_iv_length(const EVP_CIPHER *e);
unsigned long EVP_CIPHER_get_flags(const EVP_CIPHER *e);
unsigned long EVP_CIPHER_get_mode(const EVP_CIPHER *e);
int EVP_CIPHER_get_type(const EVP_CIPHER *cipher);
const EVP_CIPHER *EVP_CIPHER_CTX_get0_cipher(const EVP_CIPHER_CTX *ctx);
EVP_CIPHER *EVP_CIPHER_CTX_get1_cipher(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_get_nid(const EVP_CIPHER_CTX *ctx);
const char *EVP_CIPHER_CTX_get0_name(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[]);
int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[]);
int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[]);
const OSSL_PARAM *EVP_CIPHER_gettable_params(const EVP_CIPHER *cipher);
const OSSL_PARAM *EVP_CIPHER_settable_ctx_params(const EVP_CIPHER *cipher);
const OSSL_PARAM *EVP_CIPHER_gettable_ctx_params(const EVP_CIPHER *cipher);
const OSSL_PARAM *EVP_CIPHER_CTX_settable_params(EVP_CIPHER_CTX *ctx);
const OSSL_PARAM *EVP_CIPHER_CTX_gettable_params(EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_get_tag_length(const EVP_CIPHER_CTX *ctx);
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_set_app_data(const EVP_CIPHER_CTX *ctx, void *data);
int EVP_CIPHER_CTX_get_type(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_get_mode(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_get_num(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num);
int EVP_CIPHER_CTX_is_encrypting(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
void (*fn)(EVP_CIPHER *cipher, void *arg),
void *arg);
#define EVP_CIPHER_nid EVP_CIPHER_get_nid
#define EVP_CIPHER_name EVP_CIPHER_get0_name
#define EVP_CIPHER_block_size EVP_CIPHER_get_block_size
#define EVP_CIPHER_key_length EVP_CIPHER_get_key_length
#define EVP_CIPHER_iv_length EVP_CIPHER_get_iv_length
#define EVP_CIPHER_flags EVP_CIPHER_get_flags
#define EVP_CIPHER_mode EVP_CIPHER_get_mode
#define EVP_CIPHER_type EVP_CIPHER_get_type
#define EVP_CIPHER_CTX_encrypting EVP_CIPHER_CTX_is_encrypting
#define EVP_CIPHER_CTX_nid EVP_CIPHER_CTX_get_nid
#define EVP_CIPHER_CTX_block_size EVP_CIPHER_CTX_get_block_size
#define EVP_CIPHER_CTX_key_length EVP_CIPHER_CTX_get_key_length
#define EVP_CIPHER_CTX_iv_length EVP_CIPHER_CTX_get_iv_length
#define EVP_CIPHER_CTX_tag_length EVP_CIPHER_CTX_get_tag_length
#define EVP_CIPHER_CTX_num EVP_CIPHER_CTX_get_num
#define EVP_CIPHER_CTX_type EVP_CIPHER_CTX_get_type
#define EVP_CIPHER_CTX_mode EVP_CIPHER_CTX_get_mode
The following function has been deprecated since OpenSSL 3.0, and can be
hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
see L<openssl_user_macros(7)>:
const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
The following function has been deprecated since OpenSSL 1.1.0, and can be
hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
see L<openssl_user_macros(7)>:
int EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
=head1 DESCRIPTION
The EVP cipher routines are a high-level interface to certain
symmetric ciphers.
The B<EVP_CIPHER> type is a structure for cipher method implementation.
=over 4
=item EVP_CIPHER_fetch()
Fetches the cipher implementation for the given I<algorithm> from any provider
offering it, within the criteria given by the I<properties>.
See L<crypto(7)/ALGORITHM FETCHING> for further information.
The returned value must eventually be freed with EVP_CIPHER_free().
Fetched B<EVP_CIPHER> structures are reference counted.
=item EVP_CIPHER_up_ref()
Increments the reference count for an B<EVP_CIPHER> structure.
=item EVP_CIPHER_free()
Decrements the reference count for the fetched B<EVP_CIPHER> structure.
If the reference count drops to 0 then the structure is freed.
If the argument is NULL, nothing is done.
=item EVP_CIPHER_CTX_new()
Allocates and returns a cipher context.
=item EVP_CIPHER_CTX_free()
Clears all information from a cipher context and frees any allocated memory
associated with it, including I<ctx> itself. This function should be called
after all operations using a cipher are complete so sensitive information does
not remain in memory. If the argument is NULL, nothing is done.
=item EVP_CIPHER_CTX_ctrl()
I<This is a legacy method.> EVP_CIPHER_CTX_set_params() and
EVP_CIPHER_CTX_get_params() is the mechanism that should be used to set and get
parameters that are used by providers.
Performs cipher-specific control actions on context I<ctx>. The control command
is indicated in I<cmd> and any additional arguments in I<p1> and I<p2>.
EVP_CIPHER_CTX_ctrl() must be called after EVP_CipherInit_ex2(). Other restrictions
may apply depending on the control type and cipher implementation.
If this function happens to be used with a fetched B<EVP_CIPHER>, it will
translate the controls that are known to OpenSSL into L<OSSL_PARAM(3)>
parameters with keys defined by OpenSSL and call EVP_CIPHER_CTX_get_params() or
EVP_CIPHER_CTX_set_params() as is appropriate for each control command.
See L</CONTROLS> below for more information, including what translations are
being done.
=item EVP_CIPHER_get_params()
Retrieves the requested list of algorithm I<params> from a CIPHER I<cipher>.
See L</PARAMETERS> below for more information.
=item EVP_CIPHER_CTX_get_params()
Retrieves the requested list of I<params> from CIPHER context I<ctx>.
See L</PARAMETERS> below for more information.
=item EVP_CIPHER_CTX_set_params()
Sets the list of I<params> into a CIPHER context I<ctx>.
See L</PARAMETERS> below for more information.
=item EVP_CIPHER_gettable_params()
Get a constant L<OSSL_PARAM(3)> array that describes the retrievable parameters
that can be used with EVP_CIPHER_get_params().
=item EVP_CIPHER_gettable_ctx_params() and EVP_CIPHER_CTX_gettable_params()
Get a constant L<OSSL_PARAM(3)> array that describes the retrievable parameters
that can be used with EVP_CIPHER_CTX_get_params().
EVP_CIPHER_gettable_ctx_params() returns the parameters that can be retrieved
from the algorithm, whereas EVP_CIPHER_CTX_gettable_params() returns the
parameters that can be retrieved in the context's current state.
=item EVP_CIPHER_settable_ctx_params() and EVP_CIPHER_CTX_settable_params()
Get a constant L<OSSL_PARAM(3)> array that describes the settable parameters
that can be used with EVP_CIPHER_CTX_set_params().
EVP_CIPHER_settable_ctx_params() returns the parameters that can be set from the
algorithm, whereas EVP_CIPHER_CTX_settable_params() returns the parameters that
can be set in the context's current state.
=item EVP_EncryptInit_ex2()
Sets up cipher context I<ctx> for encryption with cipher I<type>. I<type> is
typically supplied by calling EVP_CIPHER_fetch(). I<type> may also be set
using legacy functions such as EVP_aes_256_cbc(), but this is not recommended
for new applications. I<key> is the symmetric key to use and I<iv> is the IV to
use (if necessary), the actual number of bytes used for the key and IV depends
on the cipher. The parameters I<params> will be set on the context after
initialisation. It is possible to set all parameters to NULL except I<type> in
an initial call and supply the remaining parameters in subsequent calls, all of
which have I<type> set to NULL. This is done when the default cipher parameters
are not appropriate.
For B<EVP_CIPH_GCM_MODE> the IV will be generated internally if it is not
specified.
=item EVP_EncryptInit_ex()
This legacy function is similar to EVP_EncryptInit_ex2() when I<impl> is NULL.
The implementation of the I<type> from the I<impl> engine will be used if it
exists.
=item EVP_EncryptUpdate()
Encrypts I<inl> bytes from the buffer I<in> and writes the encrypted version to
I<out>. The pointers I<out> and I<in> may point to the same location, in which
case the encryption will be done in-place. However, in-place encryption is
guaranteed to work only if the encryption context (I<ctx>) has processed data in
multiples of the block size. If the context contains an incomplete data block
from previous operations, in-place encryption will fail.
If I<out> and I<in> point to different locations, the two buffers must be
disjoint, otherwise the operation might fail or the outcome might be undefined.
This function can be called multiple times to encrypt successive blocks
of data. The amount of data written depends on the block alignment of the
encrypted data.
For most ciphers and modes, the amount of data written can be anything
from zero bytes to (inl + cipher_block_size - 1) bytes.
For wrap cipher modes, the amount of data written can be anything
from zero bytes to (inl + cipher_block_size) bytes.
For stream ciphers, the amount of data written can be anything from zero
bytes to inl bytes.
Thus, the buffer pointed to by I<out> must contain sufficient room for the
operation being performed.
The actual number of bytes written is placed in I<outl>.
If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts
the "final" data, that is any data that remains in a partial block.
It uses standard block padding (aka PKCS padding) as described in
the NOTES section, below. The encrypted
final data is written to I<out> which should have sufficient space for
one cipher block. The number of bytes written is placed in I<outl>. After
this function is called the encryption operation is finished and no further
calls to EVP_EncryptUpdate() should be made.
If padding is disabled then EVP_EncryptFinal_ex() will not encrypt any more
data and it will return an error if any data remains in a partial block:
that is if the total data length is not a multiple of the block size.
=item EVP_DecryptInit_ex2(), EVP_DecryptInit_ex(), EVP_DecryptUpdate()
and EVP_DecryptFinal_ex()
These functions are the corresponding decryption operations.
EVP_DecryptFinal() will return an error code if padding is enabled and the
final block is not correctly formatted. The parameters and restrictions are
identical to the encryption operations except that if padding is enabled the
decrypted data buffer I<out> passed to EVP_DecryptUpdate() should have
sufficient room for (I<inl> + cipher_block_size) bytes unless the cipher block
size is 1 in which case I<inl> bytes is sufficient.
=item EVP_CipherInit_ex2(), EVP_CipherInit_ex(), EVP_CipherUpdate() and
EVP_CipherFinal_ex()
These functions can be used for decryption or encryption. The operation
performed depends on the value of the I<enc> parameter. It should be set to 1
for encryption, 0 for decryption and -1 to leave the value unchanged
(the actual value of 'enc' being supplied in a previous call).
=item EVP_CIPHER_CTX_reset()
Clears all information from a cipher context and free up any allocated memory
associated with it, except the I<ctx> itself. This function should be called
anytime I<ctx> is reused by another
EVP_CipherInit() / EVP_CipherUpdate() / EVP_CipherFinal() series of calls.
=item EVP_EncryptInit(), EVP_DecryptInit() and EVP_CipherInit()
Behave in a similar way to EVP_EncryptInit_ex(), EVP_DecryptInit_ex() and
EVP_CipherInit_ex() except if the I<type> is not a fetched cipher they use the
default implementation of the I<type>.
=item EVP_EncryptFinal(), EVP_DecryptFinal() and EVP_CipherFinal()
Identical to EVP_EncryptFinal_ex(), EVP_DecryptFinal_ex() and
EVP_CipherFinal_ex(). In previous releases they also cleaned up
the I<ctx>, but this is no longer done and EVP_CIPHER_CTX_cleanup()
must be called to free any context resources.
=item EVP_Cipher()
Encrypts or decrypts a maximum I<inl> amount of bytes from I<in> and leaves the
result in I<out>.
For legacy ciphers - If the cipher doesn't have the flag
B<EVP_CIPH_FLAG_CUSTOM_CIPHER> set, then I<inl> must be a multiple of
EVP_CIPHER_get_block_size(). If it isn't, the result is undefined. If the cipher
has that flag set, then I<inl> can be any size.
Due to the constraints of the API contract of this function it shouldn't be used
in applications, please consider using EVP_CipherUpdate() and
EVP_CipherFinal_ex() instead.
=item EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj()
Returns an B<EVP_CIPHER> structure when passed a cipher name, a cipher B<NID> or
an B<ASN1_OBJECT> structure respectively.
EVP_get_cipherbyname() will return NULL for algorithms such as "AES-128-SIV",
"AES-128-CBC-CTS" and "CAMELLIA-128-CBC-CTS" which were previously only
accessible via low level interfaces.
The EVP_get_cipherbyname() function is present for backwards compatibility with
OpenSSL prior to version 3 and is different to the EVP_CIPHER_fetch() function
since it does not attempt to "fetch" an implementation of the cipher.
Additionally, it only knows about ciphers that are built-in to OpenSSL and have
an associated NID. Similarly EVP_get_cipherbynid() and EVP_get_cipherbyobj()
also return objects without an associated implementation.
When the cipher objects returned by these functions are used (such as in a call
to EVP_EncryptInit_ex()) an implementation of the cipher will be implicitly
fetched from the loaded providers. This fetch could fail if no suitable
implementation is available. Use EVP_CIPHER_fetch() instead to explicitly fetch
the algorithm and an associated implementation from a provider.
See L<crypto(7)/ALGORITHM FETCHING> for more information about fetching.
The cipher objects returned from these functions do not need to be freed with
EVP_CIPHER_free().
=item EVP_CIPHER_get_nid() and EVP_CIPHER_CTX_get_nid()
Return the NID of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>
structure. The actual NID value is an internal value which may not have a
corresponding OBJECT IDENTIFIER.
=item EVP_CIPHER_CTX_set_flags(), EVP_CIPHER_CTX_clear_flags() and EVP_CIPHER_CTX_test_flags()
Sets, clears and tests I<ctx> flags. See L</FLAGS> below for more information.
For provided ciphers EVP_CIPHER_CTX_set_flags() should be called only after the
fetched cipher has been assigned to the I<ctx>. It is recommended to use
L</PARAMETERS> instead.
=item EVP_CIPHER_CTX_set_padding()
Enables or disables padding. This function should be called after the context
is set up for encryption or decryption with EVP_EncryptInit_ex2(),
EVP_DecryptInit_ex2() or EVP_CipherInit_ex2(). By default encryption operations
are padded using standard block padding and the padding is checked and removed
when decrypting. If the I<pad> parameter is zero then no padding is
performed, the total amount of data encrypted or decrypted must then
be a multiple of the block size or an error will occur.
=item EVP_CIPHER_get_key_length() and EVP_CIPHER_CTX_get_key_length()
Return the key length of a cipher when passed an B<EVP_CIPHER> or
B<EVP_CIPHER_CTX> structure. The constant B<EVP_MAX_KEY_LENGTH> is the maximum
key length for all ciphers. Note: although EVP_CIPHER_get_key_length() is fixed for
a given cipher, the value of EVP_CIPHER_CTX_get_key_length() may be different for
variable key length ciphers.
=item EVP_CIPHER_CTX_set_key_length()
Sets the key length of the cipher context.
If the cipher is a fixed length cipher then attempting to set the key
length to any value other than the fixed value is an error.
=item EVP_CIPHER_get_iv_length() and EVP_CIPHER_CTX_get_iv_length()
Return the IV length of a cipher when passed an B<EVP_CIPHER> or
B<EVP_CIPHER_CTX>. It will return zero if the cipher does not use an IV.
The constant B<EVP_MAX_IV_LENGTH> is the maximum IV length for all ciphers.
=item EVP_CIPHER_CTX_get_tag_length()
Returns the tag length of an AEAD cipher when passed a B<EVP_CIPHER_CTX>. It will
return zero if the cipher does not support a tag. It returns a default value if
the tag length has not been set.
=item EVP_CIPHER_get_block_size() and EVP_CIPHER_CTX_get_block_size()
Return the block size of a cipher when passed an B<EVP_CIPHER> or
B<EVP_CIPHER_CTX> structure. The constant B<EVP_MAX_BLOCK_LENGTH> is also the
maximum block length for all ciphers.
=item EVP_CIPHER_get_type() and EVP_CIPHER_CTX_get_type()
Return the type of the passed cipher or context. This "type" is the actual NID
of the cipher OBJECT IDENTIFIER and as such it ignores the cipher parameters
(40 bit RC2 and 128 bit RC2 have the same NID). If the cipher does not have an
object identifier or does not have ASN1 support this function will return
B<NID_undef>.
=item EVP_CIPHER_is_a()
Returns 1 if I<cipher> is an implementation of an algorithm that's identifiable
with I<name>, otherwise 0. If I<cipher> is a legacy cipher (it's the return
value from the likes of EVP_aes128() rather than the result of an
EVP_CIPHER_fetch()), only cipher names registered with the default library
context (see L<OSSL_LIB_CTX(3)>) will be considered.
=item EVP_CIPHER_get0_name() and EVP_CIPHER_CTX_get0_name()
Return the name of the passed cipher or context. For fetched ciphers with
multiple names, only one of them is returned. See also EVP_CIPHER_names_do_all().
=item EVP_CIPHER_names_do_all()
Traverses all names for the I<cipher>, and calls I<fn> with each name and
I<data>. This is only useful with fetched B<EVP_CIPHER>s.
=item EVP_CIPHER_get0_description()
Returns a description of the cipher, meant for display and human consumption.
The description is at the discretion of the cipher implementation.
=item EVP_CIPHER_get0_provider()
Returns an B<OSSL_PROVIDER> pointer to the provider that implements the given
B<EVP_CIPHER>.
=item EVP_CIPHER_CTX_get0_cipher()
Returns the B<EVP_CIPHER> structure when passed an B<EVP_CIPHER_CTX> structure.
EVP_CIPHER_CTX_get1_cipher() is the same except the ownership is passed to
the caller.
=item EVP_CIPHER_get_mode() and EVP_CIPHER_CTX_get_mode()
Return the block cipher mode:
EVP_CIPH_ECB_MODE, EVP_CIPH_CBC_MODE, EVP_CIPH_CFB_MODE, EVP_CIPH_OFB_MODE,
EVP_CIPH_CTR_MODE, EVP_CIPH_GCM_MODE, EVP_CIPH_CCM_MODE, EVP_CIPH_XTS_MODE,
EVP_CIPH_WRAP_MODE, EVP_CIPH_OCB_MODE or EVP_CIPH_SIV_MODE.
If the cipher is a stream cipher then EVP_CIPH_STREAM_CIPHER is returned.
=item EVP_CIPHER_get_flags()
Returns any flags associated with the cipher. See L</FLAGS>
for a list of currently defined flags.
=item EVP_CIPHER_CTX_get_num() and EVP_CIPHER_CTX_set_num()
Gets or sets the cipher specific "num" parameter for the associated I<ctx>.
Built-in ciphers typically use this to track how much of the current underlying block
has been "used" already.
=item EVP_CIPHER_CTX_is_encrypting()
Reports whether the I<ctx> is being used for encryption or decryption.
=item EVP_CIPHER_CTX_flags()
A deprecated macro calling C<EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))>.
Do not use.
=item EVP_CIPHER_param_to_asn1()
Sets the AlgorithmIdentifier "parameter" based on the passed cipher. This will
typically include any parameters and an IV. The cipher IV (if any) must be set
when this call is made. This call should be made before the cipher is actually
"used" (before any EVP_EncryptUpdate(), EVP_DecryptUpdate() calls for example).
This function may fail if the cipher does not have any ASN1 support.
=item EVP_CIPHER_asn1_to_param()
Sets the cipher parameters based on an ASN1 AlgorithmIdentifier "parameter".
The precise effect depends on the cipher. In the case of B<RC2>, for example,
it will set the IV and effective key length.
This function should be called after the base cipher type is set but before
the key is set. For example EVP_CipherInit() will be called with the IV and
key set to NULL, EVP_CIPHER_asn1_to_param() will be called and finally
EVP_CipherInit() again with all parameters except the key set to NULL. It is
possible for this function to fail if the cipher does not have any ASN1 support
or the parameters cannot be set (for example the RC2 effective key length
is not supported.
=item EVP_CIPHER_CTX_rand_key()
Generates a random key of the appropriate length based on the cipher context.
The B<EVP_CIPHER> can provide its own random key generation routine to support
keys of a specific form. I<key> must point to a buffer at least as big as the
value returned by EVP_CIPHER_CTX_get_key_length().
=item EVP_CIPHER_do_all_provided()
Traverses all ciphers implemented by all activated providers in the given
library context I<libctx>, and for each of the implementations, calls the given
function I<fn> with the implementation method and the given I<arg> as argument.
=back
=head1 PARAMETERS
See L<OSSL_PARAM(3)> for information about passing parameters.
=head2 Gettable EVP_CIPHER parameters
When EVP_CIPHER_fetch() is called it internally calls EVP_CIPHER_get_params()
and caches the results.
EVP_CIPHER_get_params() can be used with the following L<OSSL_PARAM(3)> keys:
=over 4
=item "mode" (B<OSSL_CIPHER_PARAM_MODE>) <unsigned integer>
Gets the mode for the associated cipher algorithm I<cipher>.
See L</EVP_CIPHER_get_mode() and EVP_CIPHER_CTX_get_mode()> for a list of valid modes.
Use EVP_CIPHER_get_mode() to retrieve the cached value.
=item "keylen" (B<OSSL_CIPHER_PARAM_KEYLEN>) <unsigned integer>
Gets the key length for the associated cipher algorithm I<cipher>.
Use EVP_CIPHER_get_key_length() to retrieve the cached value.
=item "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN>) <unsigned integer>
Gets the IV length for the associated cipher algorithm I<cipher>.
Use EVP_CIPHER_get_iv_length() to retrieve the cached value.
=item "blocksize" (B<OSSL_CIPHER_PARAM_BLOCK_SIZE>) <unsigned integer>
Gets the block size for the associated cipher algorithm I<cipher>.
The block size should be 1 for stream ciphers.
Note that the block size for a cipher may be different to the block size for
the underlying encryption/decryption primitive.
For example AES in CTR mode has a block size of 1 (because it operates like a
stream cipher), even though AES has a block size of 16.
Use EVP_CIPHER_get_block_size() to retrieve the cached value.
=item "aead" (B<OSSL_CIPHER_PARAM_AEAD>) <integer>
Gets 1 if this is an AEAD cipher algorithm, otherwise it gets 0.
Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) to retrieve the
cached value.
=item "custom-iv" (B<OSSL_CIPHER_PARAM_CUSTOM_IV>) <integer>
Gets 1 if the cipher algorithm I<cipher> has a custom IV, otherwise it gets 0.
Storing and initializing the IV is left entirely to the implementation, if a
custom IV is used.
Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_CUSTOM_IV) to retrieve the
cached value.
=item "cts" (B<OSSL_CIPHER_PARAM_CTS>) <integer>
Gets 1 if the cipher algorithm I<cipher> uses ciphertext stealing,
otherwise it gets 0.
This is currently used to indicate that the cipher is a one shot that only
allows a single call to EVP_CipherUpdate().
Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_CTS) to retrieve the
cached value.
=item "tls-multi" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK>) <integer>
Gets 1 if the cipher algorithm I<cipher> supports interleaving of crypto blocks,
otherwise it gets 0. The interleaving is an optimization only applicable to certain
TLS ciphers.
Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) to retrieve the
cached value.
=item "has-randkey" (B<OSSL_CIPHER_PARAM_HAS_RANDKEY>) <integer>
Gets 1 if the cipher algorithm I<cipher> supports the gettable EVP_CIPHER_CTX
parameter B<OSSL_CIPHER_PARAM_RANDOM_KEY>. Only DES and 3DES set this to 1,
all other OpenSSL ciphers return 0.
=back
=head2 Gettable and Settable EVP_CIPHER_CTX parameters
The following L<OSSL_PARAM(3)> keys can be used with both EVP_CIPHER_CTX_get_params()
and EVP_CIPHER_CTX_set_params().
=over 4
=item "padding" (B<OSSL_CIPHER_PARAM_PADDING>) <unsigned integer>
Gets or sets the padding mode for the cipher context I<ctx>.
Padding is enabled if the value is 1, and disabled if the value is 0.
See also EVP_CIPHER_CTX_set_padding().
=item "num" (B<OSSL_CIPHER_PARAM_NUM>) <unsigned integer>
Gets or sets the cipher specific "num" parameter for the cipher context I<ctx>.
Built-in ciphers typically use this to track how much of the current underlying
block has been "used" already.
See also EVP_CIPHER_CTX_get_num() and EVP_CIPHER_CTX_set_num().
=item "keylen" (B<OSSL_CIPHER_PARAM_KEYLEN>) <unsigned integer>
Gets or sets the key length for the cipher context I<ctx>.
The length of the "keylen" parameter should not exceed that of a B<size_t>.
See also EVP_CIPHER_CTX_get_key_length() and EVP_CIPHER_CTX_set_key_length().
=item "tag" (B<OSSL_CIPHER_PARAM_AEAD_TAG>) <octet string>
Gets or sets the AEAD tag for the associated cipher context I<ctx>.
See L<EVP_EncryptInit(3)/AEAD Interface>.
=item "keybits" (B<OSSL_CIPHER_PARAM_RC2_KEYBITS>) <unsigned integer>
Gets or sets the effective keybits used for a RC2 cipher.
The length of the "keybits" parameter should not exceed that of a B<size_t>.
=item "rounds" (B<OSSL_CIPHER_PARAM_ROUNDS>) <unsigned integer>
Gets or sets the number of rounds to be used for a cipher.
This is used by the RC5 cipher.
=item "alg_id_param" (B<OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS>) <octet string>
Used to pass the DER encoded AlgorithmIdentifier parameter to or from
the cipher implementation. Functions like L<EVP_CIPHER_param_to_asn1(3)>
and L<EVP_CIPHER_asn1_to_param(3)> use this parameter for any implementation
that has the flag B<EVP_CIPH_FLAG_CUSTOM_ASN1> set.
=item "cts_mode" (B<OSSL_CIPHER_PARAM_CTS_MODE>) <UTF8 string>
Gets or sets the cipher text stealing mode. For all modes the output size is the
same as the input size. The input length must be greater than or equal to the
block size. (The block size for AES and CAMELLIA is 16 bytes).
Valid values for the mode are:
=over 4
=item "CS1"
The NIST variant of cipher text stealing.
For input lengths that are multiples of the block size it is equivalent to
using a "AES-XXX-CBC" or "CAMELLIA-XXX-CBC" cipher otherwise the second last
cipher text block is a partial block.
=item "CS2"
For input lengths that are multiples of the block size it is equivalent to
using a "AES-XXX-CBC" or "CAMELLIA-XXX-CBC" cipher, otherwise it is the same as
"CS3" mode.
=item "CS3"
The Kerberos5 variant of cipher text stealing which always swaps the last
cipher text block with the previous block (which may be a partial or full block
depending on the input length). If the input length is exactly one full block
then this is equivalent to using a "AES-XXX-CBC" or "CAMELLIA-XXX-CBC" cipher.
=back
The default is "CS1".
This is only supported for "AES-128-CBC-CTS", "AES-192-CBC-CTS", "AES-256-CBC-CTS",
"CAMELLIA-128-CBC-CTS", "CAMELLIA-192-CBC-CTS" and "CAMELLIA-256-CBC-CTS".
=item "tls1multi_interleave" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE>) <unsigned integer>
Sets or gets the number of records being sent in one go for a tls1 multiblock
cipher operation (either 4 or 8 records).
=back
=head2 Gettable EVP_CIPHER_CTX parameters
The following L<OSSL_PARAM(3)> keys can be used with EVP_CIPHER_CTX_get_params():
=over 4
=item "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN> and <B<OSSL_CIPHER_PARAM_AEAD_IVLEN>) <unsigned integer>
Gets the IV length for the cipher context I<ctx>.
The length of the "ivlen" parameter should not exceed that of a B<size_t>.
See also EVP_CIPHER_CTX_get_iv_length().
=item "iv" (B<OSSL_CIPHER_PARAM_IV>) <octet string OR octet ptr>
Gets the IV used to initialize the associated cipher context I<ctx>.
See also EVP_CIPHER_CTX_get_original_iv().
=item "updated-iv" (B<OSSL_CIPHER_PARAM_UPDATED_IV>) <octet string OR octet ptr>
Gets the updated pseudo-IV state for the associated cipher context, e.g.,
the previous ciphertext block for CBC mode or the iteratively encrypted IV
value for OFB mode. Note that octet pointer access is deprecated and is
provided only for backwards compatibility with historical libcrypto APIs.
See also EVP_CIPHER_CTX_get_updated_iv().
=item "randkey" (B<OSSL_CIPHER_PARAM_RANDOM_KEY>) <octet string>
Gets an implementation specific randomly generated key for the associated
cipher context I<ctx>. This is currently only supported by DES and 3DES (which set
the key to odd parity).
=item "taglen" (B<OSSL_CIPHER_PARAM_AEAD_TAGLEN>) <unsigned integer>
Gets the tag length to be used for an AEAD cipher for the associated cipher
context I<ctx>. It gets a default value if it has not been set.
The length of the "taglen" parameter should not exceed that of a B<size_t>.
See also EVP_CIPHER_CTX_get_tag_length().
=item "tlsaadpad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD>) <unsigned integer>
Gets the length of the tag that will be added to a TLS record for the AEAD
tag for the associated cipher context I<ctx>.
The length of the "tlsaadpad" parameter should not exceed that of a B<size_t>.
=item "tlsivgen" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN>) <octet string>
Gets the invocation field generated for encryption.
Can only be called after "tlsivfixed" is set.
This is only used for GCM mode.
=item "tls1multi_enclen" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN>) <unsigned integer>
Get the total length of the record returned from the "tls1multi_enc" operation.
=item "tls1multi_maxbufsz" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE>) <unsigned integer>
Gets the maximum record length for a TLS1 multiblock cipher operation.
The length of the "tls1multi_maxbufsz" parameter should not exceed that of a B<size_t>.
=item "tls1multi_aadpacklen" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN>) <unsigned integer>
Gets the result of running the "tls1multi_aad" operation.
=item "tls-mac" (B<OSSL_CIPHER_PARAM_TLS_MAC>) <octet ptr>
Used to pass the TLS MAC data.
=back
=head2 Settable EVP_CIPHER_CTX parameters
The following L<OSSL_PARAM(3)> keys can be used with EVP_CIPHER_CTX_set_params():
=over 4
=item "mackey" (B<OSSL_CIPHER_PARAM_AEAD_MAC_KEY>) <octet string>
Sets the MAC key used by composite AEAD ciphers such as AES-CBC-HMAC-SHA256.
=item "speed" (B<OSSL_CIPHER_PARAM_SPEED>) <unsigned integer>
Sets the speed option for the associated cipher context. This is only supported
by AES SIV ciphers which disallow multiple operations by default.
Setting "speed" to 1 allows another encrypt or decrypt operation to be
performed. This is used for performance testing.
=item "use-bits" (B<OSSL_CIPHER_PARAM_USE_BITS>) <unsigned integer>
Determines if the input length I<inl> passed to EVP_EncryptUpdate(),
EVP_DecryptUpdate() and EVP_CipherUpdate() is the number of bits or number of bytes.
Setting "use-bits" to 1 uses bits. The default is in bytes.
This is only used for B<CFB1> ciphers.
This can be set using EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS).
=item "tls-version" (B<OSSL_CIPHER_PARAM_TLS_VERSION>) <integer>
Sets the TLS version.
=item "tls-mac-size" (B<OSSL_CIPHER_PARAM_TLS_MAC_SIZE>) <unsigned integer>
Set the TLS MAC size.
=item "tlsaad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD>) <octet string>
Sets TLSv1.2 AAD information for the associated cipher context I<ctx>.
TLSv1.2 AAD information is always 13 bytes in length and is as defined for the
"additional_data" field described in section 6.2.3.3 of RFC5246.
=item "tlsivfixed" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED>) <octet string>
Sets the fixed portion of an IV for an AEAD cipher used in a TLS record
encryption/ decryption for the associated cipher context.
TLS record encryption/decryption always occurs "in place" so that the input and
output buffers are always the same memory location.
AEAD IVs in TLSv1.2 consist of an implicit "fixed" part and an explicit part
that varies with every record.
Setting a TLS fixed IV changes a cipher to encrypt/decrypt TLS records.
TLS records are encrypted/decrypted using a single OSSL_FUNC_cipher_cipher call per
record.
For a record decryption the first bytes of the input buffer will be the explicit
part of the IV and the final bytes of the input buffer will be the AEAD tag.
The length of the explicit part of the IV and the tag length will depend on the
cipher in use and will be defined in the RFC for the relevant ciphersuite.
In order to allow for "in place" decryption the plaintext output should be
written to the same location in the output buffer that the ciphertext payload
was read from, i.e. immediately after the explicit IV.
When encrypting a record the first bytes of the input buffer should be empty to
allow space for the explicit IV, as will the final bytes where the tag will
be written.
The length of the input buffer will include the length of the explicit IV, the
payload, and the tag bytes.
The cipher implementation should generate the explicit IV and write it to the
beginning of the output buffer, do "in place" encryption of the payload and
write that to the output buffer, and finally add the tag onto the end of the
output buffer.
Whether encrypting or decrypting the value written to I<*outl> in the
OSSL_FUNC_cipher_cipher call should be the length of the payload excluding the explicit
IV length and the tag length.
=item "tlsivinv" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV>) <octet string>
Sets the invocation field used for decryption.
Can only be called after "tlsivfixed" is set.
This is only used for GCM mode.
=item "tls1multi_enc" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC>) <octet string>
Triggers a multiblock TLS1 encrypt operation for a TLS1 aware cipher that
supports sending 4 or 8 records in one go.
The cipher performs both the MAC and encrypt stages and constructs the record
headers itself.
"tls1multi_enc" supplies the output buffer for the encrypt operation,
"tls1multi_encin" & "tls1multi_interleave" must also be set in order to supply
values to the encrypt operation.
=item "tls1multi_encin" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN>) <octet string>
Supplies the data to encrypt for a TLS1 multiblock cipher operation.
=item "tls1multi_maxsndfrag" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT>) <unsigned integer>
Sets the maximum send fragment size for a TLS1 multiblock cipher operation.
It must be set before using "tls1multi_maxbufsz".
The length of the "tls1multi_maxsndfrag" parameter should not exceed that of a B<size_t>.
=item "tls1multi_aad" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD>) <octet string>
Sets the authenticated additional data used by a TLS1 multiblock cipher operation.
The supplied data consists of 13 bytes of record data containing:
Bytes 0-7: The sequence number of the first record
Byte 8: The record type
Byte 9-10: The protocol version
Byte 11-12: Input length (Always 0)
"tls1multi_interleave" must also be set for this operation.
=back
=head1 CONTROLS
The Mappings from EVP_CIPHER_CTX_ctrl() identifiers to PARAMETERS are listed
in the following section. See the L</PARAMETERS> section for more details.
EVP_CIPHER_CTX_ctrl() can be used to send the following standard controls:
=over 4
=item EVP_CTRL_AEAD_SET_IVLEN and EVP_CTRL_GET_IVLEN
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() and
EVP_CIPHER_CTX_get_params() get called with an L<OSSL_PARAM(3)> item with the
key "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN>).
=item EVP_CTRL_AEAD_SET_IV_FIXED
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with an L<OSSL_PARAM(3)> item with the key "tlsivfixed"
(B<OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED>).
=item EVP_CTRL_AEAD_SET_MAC_KEY
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with an L<OSSL_PARAM(3)> item with the key "mackey"
(B<OSSL_CIPHER_PARAM_AEAD_MAC_KEY>).
=item EVP_CTRL_AEAD_SET_TAG and EVP_CTRL_AEAD_GET_TAG
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() and
EVP_CIPHER_CTX_get_params() get called with an L<OSSL_PARAM(3)> item with the
key "tag" (B<OSSL_CIPHER_PARAM_AEAD_TAG>).
=item EVP_CTRL_CCM_SET_L
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with an L<OSSL_PARAM(3)> item with the key "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN>)
with a value of (15 - L)
=item EVP_CTRL_COPY
There is no OSSL_PARAM mapping for this. Use EVP_CIPHER_CTX_copy() instead.
=item EVP_CTRL_GCM_SET_IV_INV
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with an L<OSSL_PARAM(3)> item with the key "tlsivinv"
(B<OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV>).
=item EVP_CTRL_RAND_KEY
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with an L<OSSL_PARAM(3)> item with the key "randkey"
(B<OSSL_CIPHER_PARAM_RANDOM_KEY>).
=item EVP_CTRL_SET_KEY_LENGTH
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with an L<OSSL_PARAM(3)> item with the key "keylen" (B<OSSL_CIPHER_PARAM_KEYLEN>).
=item EVP_CTRL_SET_RC2_KEY_BITS and EVP_CTRL_GET_RC2_KEY_BITS
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() and
EVP_CIPHER_CTX_get_params() get called with an L<OSSL_PARAM(3)> item with the
key "keybits" (B<OSSL_CIPHER_PARAM_RC2_KEYBITS>).
=item EVP_CTRL_SET_RC5_ROUNDS and EVP_CTRL_GET_RC5_ROUNDS
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() and
EVP_CIPHER_CTX_get_params() get called with an L<OSSL_PARAM(3)> item with the
key "rounds" (B<OSSL_CIPHER_PARAM_ROUNDS>).
=item EVP_CTRL_SET_SPEED
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with an L<OSSL_PARAM(3)> item with the key "speed" (B<OSSL_CIPHER_PARAM_SPEED>).
=item EVP_CTRL_GCM_IV_GEN
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_get_params() gets called
with an L<OSSL_PARAM(3)> item with the key
"tlsivgen" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN>).
=item EVP_CTRL_AEAD_TLS1_AAD
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() get called
with an L<OSSL_PARAM(3)> item with the key
"tlsaad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD>)
followed by EVP_CIPHER_CTX_get_params() with a key of
"tlsaadpad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD>).
=item EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE
When used with a fetched B<EVP_CIPHER>,
EVP_CIPHER_CTX_set_params() gets called with an L<OSSL_PARAM(3)> item with the
key OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT
followed by EVP_CIPHER_CTX_get_params() with a key of
"tls1multi_maxbufsz" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE>).
=item EVP_CTRL_TLS1_1_MULTIBLOCK_AAD
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with L<OSSL_PARAM(3)> items with the keys
"tls1multi_aad" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD>) and
"tls1multi_interleave" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE>)
followed by EVP_CIPHER_CTX_get_params() with keys of
"tls1multi_aadpacklen" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN>) and
"tls1multi_interleave" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE>).
=item EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT
When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
with L<OSSL_PARAM(3)> items with the keys
"tls1multi_enc" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC>),
"tls1multi_encin" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN>) and
"tls1multi_interleave" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE>),
followed by EVP_CIPHER_CTX_get_params() with a key of
"tls1multi_enclen" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN>).
=back
=head1 FLAGS
EVP_CIPHER_CTX_set_flags(), EVP_CIPHER_CTX_clear_flags() and EVP_CIPHER_CTX_test_flags().
can be used to manipulate and test these B<EVP_CIPHER_CTX> flags:
=over 4
=item EVP_CIPH_NO_PADDING
Used by EVP_CIPHER_CTX_set_padding().
See also L</Gettable and Settable EVP_CIPHER_CTX parameters> "padding"
=item EVP_CIPH_FLAG_LENGTH_BITS
See L</Settable EVP_CIPHER_CTX parameters> "use-bits".
=item EVP_CIPHER_CTX_FLAG_WRAP_ALLOW
Used for Legacy purposes only. This flag needed to be set to indicate the
cipher handled wrapping.
=back
EVP_CIPHER_flags() uses the following flags that
have mappings to L</Gettable EVP_CIPHER parameters>:
=over 4
=item EVP_CIPH_FLAG_AEAD_CIPHER
See L</Gettable EVP_CIPHER parameters> "aead".
=item EVP_CIPH_CUSTOM_IV
See L</Gettable EVP_CIPHER parameters> "custom-iv".
=item EVP_CIPH_FLAG_CTS
See L</Gettable EVP_CIPHER parameters> "cts".
=item EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK;
See L</Gettable EVP_CIPHER parameters> "tls-multi".
=item EVP_CIPH_RAND_KEY
See L</Gettable EVP_CIPHER parameters> "has-randkey".
=back
EVP_CIPHER_flags() uses the following flags for legacy purposes only:
=over 4
=item EVP_CIPH_VARIABLE_LENGTH
=item EVP_CIPH_FLAG_CUSTOM_CIPHER
=item EVP_CIPH_ALWAYS_CALL_INIT
=item EVP_CIPH_CTRL_INIT
=item EVP_CIPH_CUSTOM_KEY_LENGTH
=item EVP_CIPH_CUSTOM_COPY
=item EVP_CIPH_FLAG_DEFAULT_ASN1
See L<EVP_CIPHER_meth_set_flags(3)> for further information related to the above
flags.
=back
=head1 RETURN VALUES
EVP_CIPHER_fetch() returns a pointer to a B<EVP_CIPHER> for success
and B<NULL> for failure.
EVP_CIPHER_up_ref() returns 1 for success or 0 otherwise.
EVP_CIPHER_CTX_new() returns a pointer to a newly created
B<EVP_CIPHER_CTX> for success and B<NULL> for failure.
EVP_EncryptInit_ex2(), EVP_EncryptUpdate() and EVP_EncryptFinal_ex()
return 1 for success and 0 for failure.
EVP_DecryptInit_ex2() and EVP_DecryptUpdate() return 1 for success and 0 for failure.
EVP_DecryptFinal_ex() returns 0 if the decrypt failed or 1 for success.
EVP_CipherInit_ex2() and EVP_CipherUpdate() return 1 for success and 0 for failure.
EVP_CipherFinal_ex() returns 0 for a decryption failure or 1 for success.
EVP_Cipher() returns 1 on success or 0 on failure, if the flag
B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is not set for the cipher.
EVP_Cipher() returns the number of bytes written to I<out> for encryption / decryption, or
the number of bytes authenticated in a call specifying AAD for an AEAD cipher, if the flag
B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is set for the cipher.
EVP_CIPHER_CTX_reset() returns 1 for success and 0 for failure.
EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj()
return an B<EVP_CIPHER> structure or NULL on error.
EVP_CIPHER_get_nid() and EVP_CIPHER_CTX_get_nid() return a NID.
EVP_CIPHER_get_block_size() and EVP_CIPHER_CTX_get_block_size() return the
block size.
EVP_CIPHER_get_key_length() and EVP_CIPHER_CTX_get_key_length() return the key
length.
EVP_CIPHER_CTX_set_padding() always returns 1.
EVP_CIPHER_get_iv_length() and EVP_CIPHER_CTX_get_iv_length() return the IV
length or zero if the cipher does not use an IV.
EVP_CIPHER_CTX_get_tag_length() return the tag length or zero if the cipher
does not use a tag.
EVP_CIPHER_get_type() and EVP_CIPHER_CTX_get_type() return the NID of the
cipher's OBJECT IDENTIFIER or NID_undef if it has no defined
OBJECT IDENTIFIER.
EVP_CIPHER_CTX_cipher() returns an B<EVP_CIPHER> structure.
EVP_CIPHER_CTX_get_num() returns a nonnegative num value or
B<EVP_CTRL_RET_UNSUPPORTED> if the implementation does not support the call
or on any other error.
EVP_CIPHER_CTX_set_num() returns 1 on success and 0 if the implementation
does not support the call or on any other error.
EVP_CIPHER_CTX_is_encrypting() returns 1 if the I<ctx> is set up for encryption
0 otherwise.
EVP_CIPHER_param_to_asn1() and EVP_CIPHER_asn1_to_param() return greater
than zero for success and zero or a negative number on failure.
EVP_CIPHER_CTX_rand_key() returns 1 for success and zero or a negative number
for failure.
EVP_CIPHER_names_do_all() returns 1 if the callback was called for all names.
A return value of 0 means that the callback was not called for any names.
=head1 CIPHER LISTING
All algorithms have a fixed key length unless otherwise stated.
Refer to L</SEE ALSO> for the full list of ciphers available through the EVP
interface.
=over 4
=item EVP_enc_null()
Null cipher: does nothing.
=back
=head1 AEAD INTERFACE
The EVP interface for Authenticated Encryption with Associated Data (AEAD)
modes are subtly altered and several additional I<ctrl> operations are supported
depending on the mode specified.
To specify additional authenticated data (AAD), a call to EVP_CipherUpdate(),
EVP_EncryptUpdate() or EVP_DecryptUpdate() should be made with the output
parameter I<out> set to B<NULL>. In this case, on success, the parameter
I<outl> is set to the number of bytes authenticated.
When decrypting, the return value of EVP_DecryptFinal() or EVP_CipherFinal()
indicates whether the operation was successful. If it does not indicate success,
the authentication operation has failed and any output data B<MUST NOT> be used
as it is corrupted.
+Please note that the number of authenticated bytes returned by
+EVP_CipherUpdate() depends on the cipher used. Stream ciphers, such as ChaCha20
+or ciphers in GCM mode, can handle 1 byte at a time, resulting in an effective
+"block" size of 1. Conversely, ciphers in OCB mode must process data one block
+at a time, and the block size is returned.
+
+Regardless of the returned size, it is safe to pass unpadded data to an
+EVP_CipherUpdate() call in a single operation.
+
=head2 GCM and OCB Modes
The following I<ctrl>s are supported in GCM and OCB modes.
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
Sets the IV length. This call can only be made before specifying an IV. If
not called a default IV length is used.
For GCM AES and OCB AES the default is 12 (i.e. 96 bits). For OCB mode the
maximum is 15.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag)
Writes C<taglen> bytes of the tag value to the buffer indicated by C<tag>.
This call can only be made when encrypting data and B<after> all data has been
processed (e.g. after an EVP_EncryptFinal() call).
For OCB, C<taglen> must either be 16 or the value previously set via
B<EVP_CTRL_AEAD_SET_TAG>.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag)
When decrypting, this call sets the expected tag to C<taglen> bytes from C<tag>.
C<taglen> must be between 1 and 16 inclusive.
The tag must be set prior to any call to EVP_DecryptFinal() or
EVP_DecryptFinal_ex().
For GCM, this call is only valid when decrypting data.
For OCB, this call is valid when decrypting data to set the expected tag,
and when encrypting to set the desired tag length.
-In OCB mode, calling this when encrypting with C<tag> set to C<NULL> sets the
-tag length. The tag length can only be set before specifying an IV. If this is
-not called prior to setting the IV during encryption, then a default tag length
-is used.
+In OCB mode, calling this with C<tag> set to C<NULL> sets the tag length.
+The tag length can only be set before specifying an IV. If this is not called
+prior to setting the IV, then a default tag length is used.
For OCB AES, the default tag length is 16 (i.e. 128 bits). It is also the
maximum tag length for OCB.
=back
=head2 CCM Mode
The EVP interface for CCM mode is similar to that of the GCM mode but with a
few additional requirements and different I<ctrl> values.
For CCM mode, the total plaintext or ciphertext length B<MUST> be passed to
EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() with the output
and input parameters (I<in> and I<out>) set to B<NULL> and the length passed in
the I<inl> parameter.
The following I<ctrl>s are supported in CCM mode.
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag)
This call is made to set the expected B<CCM> tag value when decrypting or
the length of the tag (with the C<tag> parameter set to NULL) when encrypting.
The tag length is often referred to as B<M>. If not set a default value is
used (12 for AES). When decrypting, the tag needs to be set before passing
in data to be decrypted, but as in GCM and OCB mode, it can be set after
passing additional authenticated data (see L</AEAD INTERFACE>).
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, ivlen, NULL)
Sets the CCM B<L> value. If not set a default is used (8 for AES).
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
Sets the CCM nonce (IV) length. This call can only be made before specifying a
nonce value. The nonce length is given by B<15 - L> so it is 7 by default for
AES.
=back
=head2 SIV Mode
For SIV mode ciphers the behaviour of the EVP interface is subtly
altered and several additional ctrl operations are supported.
To specify any additional authenticated data (AAD) and/or a Nonce, a call to
EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() should be made
with the output parameter I<out> set to B<NULL>.
RFC5297 states that the Nonce is the last piece of AAD before the actual
encrypt/decrypt takes place. The API does not differentiate the Nonce from
other AAD.
When decrypting the return value of EVP_DecryptFinal() or EVP_CipherFinal()
indicates if the operation was successful. If it does not indicate success
the authentication operation has failed and any output data B<MUST NOT>
be used as it is corrupted.
The API does not store the the SIV (Synthetic Initialization Vector) in
the cipher text. Instead, it is stored as the tag within the EVP_CIPHER_CTX.
The SIV must be retrieved from the context after encryption, and set into
the context before decryption.
This differs from RFC5297 in that the cipher output from encryption, and
the cipher input to decryption, does not contain the SIV. This also means
that the plain text and cipher text lengths are identical.
The following ctrls are supported in SIV mode, and are used to get and set
the Synthetic Initialization Vector:
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag);
Writes I<taglen> bytes of the tag value (the Synthetic Initialization Vector)
to the buffer indicated by I<tag>. This call can only be made when encrypting
data and B<after> all data has been processed (e.g. after an EVP_EncryptFinal()
call). For SIV mode the taglen must be 16.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag);
Sets the expected tag (the Synthetic Initialization Vector) to I<taglen>
bytes from I<tag>. This call is only legal when decrypting data and must be
made B<before> any data is processed (e.g. before any EVP_DecryptUpdate()
calls). For SIV mode the taglen must be 16.
=back
SIV mode makes two passes over the input data, thus, only one call to
EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() should be made
with I<out> set to a non-B<NULL> value. A call to EVP_DecryptFinal() or
EVP_CipherFinal() is not required, but will indicate if the update
operation succeeded.
=head2 ChaCha20-Poly1305
The following I<ctrl>s are supported for the ChaCha20-Poly1305 AEAD algorithm.
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
Sets the nonce length. This call is now redundant since the only valid value
is the default length of 12 (i.e. 96 bits).
Prior to OpenSSL 3.0 a nonce of less than 12 bytes could be used to automatically
pad the iv with leading 0 bytes to make it 12 bytes in length.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag)
Writes C<taglen> bytes of the tag value to the buffer indicated by C<tag>.
This call can only be made when encrypting data and B<after> all data has been
processed (e.g. after an EVP_EncryptFinal() call).
C<taglen> specified here must be 16 (B<POLY1305_BLOCK_SIZE>, i.e. 128-bits) or
less.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag)
Sets the expected tag to C<taglen> bytes from C<tag>.
The tag length can only be set before specifying an IV.
C<taglen> must be between 1 and 16 (B<POLY1305_BLOCK_SIZE>) inclusive.
This call is only valid when decrypting data.
=back
=head1 NOTES
Where possible the B<EVP> interface to symmetric ciphers should be used in
preference to the low-level interfaces. This is because the code then becomes
transparent to the cipher used and much more flexible. Additionally, the
B<EVP> interface will ensure the use of platform specific cryptographic
acceleration such as AES-NI (the low-level interfaces do not provide the
guarantee).
PKCS padding works by adding B<n> padding bytes of value B<n> to make the total
length of the encrypted data a multiple of the block size. Padding is always
added so if the data is already a multiple of the block size B<n> will equal
the block size. For example if the block size is 8 and 11 bytes are to be
encrypted then 5 padding bytes of value 5 will be added.
When decrypting the final block is checked to see if it has the correct form.
Although the decryption operation can produce an error if padding is enabled,
it is not a strong test that the input data or key is correct. A random block
has better than 1 in 256 chance of being of the correct format and problems with
the input data earlier on will not produce a final decrypt error.
If padding is disabled then the decryption operation will always succeed if
the total amount of data decrypted is a multiple of the block size.
The functions EVP_EncryptInit(), EVP_EncryptInit_ex(),
EVP_EncryptFinal(), EVP_DecryptInit(), EVP_DecryptInit_ex(),
EVP_CipherInit(), EVP_CipherInit_ex() and EVP_CipherFinal() are obsolete
but are retained for compatibility with existing code. New code should
use EVP_EncryptInit_ex2(), EVP_EncryptFinal_ex(), EVP_DecryptInit_ex2(),
EVP_DecryptFinal_ex(), EVP_CipherInit_ex2() and EVP_CipherFinal_ex()
because they can reuse an existing context without allocating and freeing
it up on each call.
There are some differences between functions EVP_CipherInit() and
EVP_CipherInit_ex(), significant in some circumstances. EVP_CipherInit() fills
the passed context object with zeros. As a consequence, EVP_CipherInit() does
not allow step-by-step initialization of the ctx when the I<key> and I<iv> are
passed in separate calls. It also means that the flags set for the CTX are
removed, and it is especially important for the
B<EVP_CIPHER_CTX_FLAG_WRAP_ALLOW> flag treated specially in
EVP_CipherInit_ex().
Ignoring failure returns of the B<EVP_CIPHER_CTX> initialization functions can
lead to subsequent undefined behavior when calling the functions that update or
finalize the context. The only valid calls on the B<EVP_CIPHER_CTX> when
initialization fails are calls that attempt another initialization of the
context or release the context.
EVP_get_cipherbynid(), and EVP_get_cipherbyobj() are implemented as macros.
=head1 BUGS
B<EVP_MAX_KEY_LENGTH> and B<EVP_MAX_IV_LENGTH> only refer to the internal
ciphers with default key lengths. If custom ciphers exceed these values the
results are unpredictable. This is because it has become standard practice to
define a generic key as a fixed unsigned char array containing
B<EVP_MAX_KEY_LENGTH> bytes.
The ASN1 code is incomplete (and sometimes inaccurate) it has only been tested
for certain common S/MIME ciphers (RC2, DES, triple DES) in CBC mode.
=head1 EXAMPLES
Encrypt a string using IDEA:
int do_crypt(char *outfile)
{
unsigned char outbuf[1024];
int outlen, tmplen;
/*
* Bogus key and IV: we'd normally set these from
* another source.
*/
unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
unsigned char iv[] = {1,2,3,4,5,6,7,8};
char intext[] = "Some Crypto Text";
EVP_CIPHER_CTX *ctx;
FILE *out;
ctx = EVP_CIPHER_CTX_new();
if (!EVP_EncryptInit_ex2(ctx, EVP_idea_cbc(), key, iv, NULL)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, intext, strlen(intext))) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
/*
* Buffer passed to EVP_EncryptFinal() must be after data just
* encrypted to avoid overwriting it.
*/
if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
outlen += tmplen;
EVP_CIPHER_CTX_free(ctx);
/*
* Need binary mode for fopen because encrypted data is
* binary data. Also cannot use strlen() on it because
* it won't be NUL terminated and may contain embedded
* NULs.
*/
out = fopen(outfile, "wb");
if (out == NULL) {
/* Error */
return 0;
}
fwrite(outbuf, 1, outlen, out);
fclose(out);
return 1;
}
The ciphertext from the above example can be decrypted using the B<openssl>
utility with the command line (shown on two lines for clarity):
openssl idea -d \
-K 000102030405060708090A0B0C0D0E0F -iv 0102030405060708 <filename
General encryption and decryption function example using FILE I/O and AES128
with a 128-bit key:
int do_crypt(FILE *in, FILE *out, int do_encrypt)
{
/* Allow enough space in output buffer for additional block */
unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
int inlen, outlen;
EVP_CIPHER_CTX *ctx;
/*
* Bogus key and IV: we'd normally set these from
* another source.
*/
unsigned char key[] = "0123456789abcdeF";
unsigned char iv[] = "1234567887654321";
/* Don't set key or IV right away; we want to check lengths */
ctx = EVP_CIPHER_CTX_new();
if (!EVP_CipherInit_ex2(ctx, EVP_aes_128_cbc(), NULL, NULL,
do_encrypt, NULL)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
OPENSSL_assert(EVP_CIPHER_CTX_get_key_length(ctx) == 16);
OPENSSL_assert(EVP_CIPHER_CTX_get_iv_length(ctx) == 16);
/* Now we can set key and IV */
if (!EVP_CipherInit_ex2(ctx, NULL, key, iv, do_encrypt, NULL)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
for (;;) {
inlen = fread(inbuf, 1, 1024, in);
if (inlen <= 0)
break;
if (!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
}
if (!EVP_CipherFinal_ex(ctx, outbuf, &outlen)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
EVP_CIPHER_CTX_free(ctx);
return 1;
}
Encryption using AES-CBC with a 256-bit key with "CS1" ciphertext stealing.
int encrypt(const unsigned char *key, const unsigned char *iv,
const unsigned char *msg, size_t msg_len, unsigned char *out)
{
/*
* This assumes that key size is 32 bytes and the iv is 16 bytes.
* For ciphertext stealing mode the length of the ciphertext "out" will be
* the same size as the plaintext size "msg_len".
* The "msg_len" can be any size >= 16.
*/
int ret = 0, encrypt = 1, outlen, len;
EVP_CIPHER_CTX *ctx = NULL;
EVP_CIPHER *cipher = NULL;
OSSL_PARAM params[2];
ctx = EVP_CIPHER_CTX_new();
cipher = EVP_CIPHER_fetch(NULL, "AES-256-CBC-CTS", NULL);
if (ctx == NULL || cipher == NULL)
goto err;
/*
* The default is "CS1" so this is not really needed,
* but would be needed to set either "CS2" or "CS3".
*/
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE,
"CS1", 0);
params[1] = OSSL_PARAM_construct_end();
if (!EVP_CipherInit_ex2(ctx, cipher, key, iv, encrypt, params))
goto err;
/* NOTE: CTS mode does not support multiple calls to EVP_CipherUpdate() */
if (!EVP_CipherUpdate(ctx, out, &outlen, msg, msg_len))
goto err;
if (!EVP_CipherFinal_ex(ctx, out + outlen, &len))
goto err;
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
=head1 SEE ALSO
L<evp(7)>,
L<property(7)>,
L<crypto(7)/ALGORITHM FETCHING>,
L<provider-cipher(7)>,
L<life_cycle-cipher(7)>
Supported ciphers are listed in:
L<EVP_aes_128_gcm(3)>,
L<EVP_aria_128_gcm(3)>,
L<EVP_bf_cbc(3)>,
L<EVP_camellia_128_ecb(3)>,
L<EVP_cast5_cbc(3)>,
L<EVP_chacha20(3)>,
L<EVP_des_cbc(3)>,
L<EVP_desx_cbc(3)>,
L<EVP_idea_cbc(3)>,
L<EVP_rc2_cbc(3)>,
L<EVP_rc4(3)>,
L<EVP_rc5_32_12_16_cbc(3)>,
L<EVP_seed_cbc(3)>,
L<EVP_sm4_cbc(3)>,
=head1 HISTORY
Support for OCB mode was added in OpenSSL 1.1.0.
B<EVP_CIPHER_CTX> was made opaque in OpenSSL 1.1.0. As a result,
EVP_CIPHER_CTX_reset() appeared and EVP_CIPHER_CTX_cleanup()
disappeared. EVP_CIPHER_CTX_init() remains as an alias for
EVP_CIPHER_CTX_reset().
The EVP_CIPHER_CTX_cipher() function was deprecated in OpenSSL 3.0; use
EVP_CIPHER_CTX_get0_cipher() instead.
The EVP_EncryptInit_ex2(), EVP_DecryptInit_ex2(), EVP_CipherInit_ex2(),
EVP_CIPHER_fetch(), EVP_CIPHER_free(), EVP_CIPHER_up_ref(),
EVP_CIPHER_CTX_get0_cipher(), EVP_CIPHER_CTX_get1_cipher(),
EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
EVP_CIPHER_CTX_get_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_settable_ctx_params(), EVP_CIPHER_gettable_ctx_params(),
EVP_CIPHER_CTX_settable_params() and EVP_CIPHER_CTX_gettable_params()
functions were added in 3.0.
The EVP_CIPHER_nid(), EVP_CIPHER_name(), EVP_CIPHER_block_size(),
EVP_CIPHER_key_length(), EVP_CIPHER_iv_length(), EVP_CIPHER_flags(),
EVP_CIPHER_mode(), EVP_CIPHER_type(), EVP_CIPHER_CTX_nid(),
EVP_CIPHER_CTX_block_size(), EVP_CIPHER_CTX_key_length(),
EVP_CIPHER_CTX_iv_length(), EVP_CIPHER_CTX_tag_length(),
EVP_CIPHER_CTX_num(), EVP_CIPHER_CTX_type(), and EVP_CIPHER_CTX_mode()
functions were renamed to include C<get> or C<get0> in their names in
OpenSSL 3.0, respectively. The old names are kept as non-deprecated
alias macros.
The EVP_CIPHER_CTX_encrypting() function was renamed to
EVP_CIPHER_CTX_is_encrypting() in OpenSSL 3.0. The old name is kept as
non-deprecated alias macro.
The EVP_CIPHER_CTX_flags() macro was deprecated in OpenSSL 1.1.0.
=head1 COPYRIGHT
Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/EVP_PKEY_decapsulate.pod b/crypto/openssl/doc/man3/EVP_PKEY_decapsulate.pod
index 819291627bb8..cd6f5f0221a2 100644
--- a/crypto/openssl/doc/man3/EVP_PKEY_decapsulate.pod
+++ b/crypto/openssl/doc/man3/EVP_PKEY_decapsulate.pod
@@ -1,101 +1,104 @@
=pod
=head1 NAME
EVP_PKEY_decapsulate_init, EVP_PKEY_decapsulate
- Key decapsulation using a KEM algorithm with a private key
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
unsigned char *unwrapped, size_t *unwrappedlen,
const unsigned char *wrapped, size_t wrappedlen);
=head1 DESCRIPTION
The EVP_PKEY_decapsulate_init() function initializes a private key algorithm
context I<ctx> for a decapsulation operation and then sets the I<params>
on the context in the same way as calling L<EVP_PKEY_CTX_set_params(3)>.
Note that I<ctx> usually is produced using L<EVP_PKEY_CTX_new_from_pkey(3)>,
specifying the private key to use.
The EVP_PKEY_decapsulate() function performs a private key decapsulation
operation using I<ctx>. The data to be decapsulated is specified using the
I<wrapped> and I<wrappedlen> parameters.
-If I<unwrapped> is NULL then the maximum size of the output secret buffer
+If I<unwrapped> is NULL then the size of the output secret buffer
is written to I<*unwrappedlen>. If I<unwrapped> is not NULL and the
call is successful then the decapsulated secret data is written to I<unwrapped>
-and the amount of data written to I<*unwrappedlen>.
+and the amount of data written to I<*unwrappedlen>. Note that, if I<unwrappedlen>
+is not NULL in this call, the value it points to must be initialised to the length of
+I<unwrapped>, so that the call can validate it is of sufficient size to hold the
+result of the operation.
=head1 NOTES
After the call to EVP_PKEY_decapsulate_init() algorithm-specific parameters
for the operation may be set or modified using L<EVP_PKEY_CTX_set_params(3)>.
=head1 RETURN VALUES
EVP_PKEY_decapsulate_init() and EVP_PKEY_decapsulate() 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 private key algorithm.
=head1 EXAMPLES
Decapsulate data using RSA:
#include <openssl/evp.h>
/*
* NB: assumes rsa_priv_key is an RSA private key,
* and that in, inlen are already set up to contain encapsulated data.
*/
EVP_PKEY_CTX *ctx = NULL;
size_t secretlen = 0;
unsigned char *secret = NULL;;
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, rsa_priv_key, NULL);
- if (ctx = NULL)
+ if (ctx == NULL)
/* Error */
if (EVP_PKEY_decapsulate_init(ctx, NULL) <= 0)
/* Error */
/* Set the mode - only 'RSASVE' is currently supported */
if (EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE") <= 0)
/* Error */
/* Determine buffer length */
if (EVP_PKEY_decapsulate(ctx, NULL, &secretlen, in, inlen) <= 0)
/* Error */
secret = OPENSSL_malloc(secretlen);
if (secret == NULL)
/* malloc failure */
/* Decapsulated secret data is secretlen bytes long */
if (EVP_PKEY_decapsulaterctx, secret, &secretlen, in, inlen) <= 0)
/* Error */
=head1 SEE ALSO
L<EVP_PKEY_CTX_new_from_pkey(3)>,
L<EVP_PKEY_encapsulate(3)>,
L<EVP_KEM-RSA(7)>,
=head1 HISTORY
These functions were added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/EVP_PKEY_encapsulate.pod b/crypto/openssl/doc/man3/EVP_PKEY_encapsulate.pod
index 0ee7d627904d..eb51836d7951 100644
--- a/crypto/openssl/doc/man3/EVP_PKEY_encapsulate.pod
+++ b/crypto/openssl/doc/man3/EVP_PKEY_encapsulate.pod
@@ -1,110 +1,113 @@
=pod
=head1 NAME
EVP_PKEY_encapsulate_init, EVP_PKEY_encapsulate
- Key encapsulation using a KEM algorithm with a public key
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
unsigned char *wrappedkey, size_t *wrappedkeylen,
unsigned char *genkey, size_t *genkeylen);
=head1 DESCRIPTION
The EVP_PKEY_encapsulate_init() function initializes a public key algorithm
context I<ctx> for an encapsulation operation and then sets the I<params>
on the context in the same way as calling L<EVP_PKEY_CTX_set_params(3)>.
Note that I<ctx> is usually is produced using L<EVP_PKEY_CTX_new_from_pkey(3)>,
specifying the public key to use.
The EVP_PKEY_encapsulate() function performs a public key encapsulation
operation using I<ctx>.
The symmetric secret generated in I<genkey> can be used as key material.
The ciphertext in I<wrappedkey> is its encapsulated form, which can be sent
to another party, who can use L<EVP_PKEY_decapsulate(3)> to retrieve it
using their private key.
If I<wrappedkey> is NULL then the maximum size of the output buffer
is written to the I<*wrappedkeylen> parameter unless I<wrappedkeylen> is NULL
and the maximum size of the generated key buffer is written to I<*genkeylen>
unless I<genkeylen> is NULL.
If I<wrappedkey> is not NULL and the call is successful then the
internally generated key is written to I<genkey> and its size is written to
I<*genkeylen>. The encapsulated version of the generated key is written to
-I<wrappedkey> and its size is written to I<*wrappedkeylen>.
+I<wrappedkey> and its size is written to I<*wrappedkeylen>. Note that if
+I<wrappedlen> is not NULL, then the value it points to must initially hold the size of
+the I<unwrapped> buffer so that its size can be validated by the call, ensuring
+it is large enough to hold the result written to I<wrapped>.
=head1 NOTES
After the call to EVP_PKEY_encapsulate_init() algorithm-specific parameters
for the operation may be set or modified using L<EVP_PKEY_CTX_set_params(3)>.
=head1 RETURN VALUES
EVP_PKEY_encapsulate_init() and EVP_PKEY_encapsulate() 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 EXAMPLES
Encapsulate an RSASVE key (for RSA keys).
#include <openssl/evp.h>
/*
* NB: assumes rsa_pub_key is an public key of another party.
*/
EVP_PKEY_CTX *ctx = NULL;
size_t secretlen = 0, outlen = 0;
unsigned char *out = NULL, *secret = NULL;
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, rsa_pub_key, NULL);
- if (ctx = NULL)
+ if (ctx == NULL)
/* Error */
if (EVP_PKEY_encapsulate_init(ctx, NULL) <= 0)
/* Error */
/* Set the mode - only 'RSASVE' is currently supported */
if (EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE") <= 0)
/* Error */
/* Determine buffer length */
if (EVP_PKEY_encapsulate(ctx, NULL, &outlen, NULL, &secretlen) <= 0)
/* Error */
out = OPENSSL_malloc(outlen);
secret = OPENSSL_malloc(secretlen);
if (out == NULL || secret == NULL)
/* malloc failure */
/*
* The generated 'secret' can be used as key material.
* The encapsulated 'out' can be sent to another party who can
* decapsulate it using their private key to retrieve the 'secret'.
*/
if (EVP_PKEY_encapsulate(ctx, out, &outlen, secret, &secretlen) <= 0)
/* Error */
=head1 SEE ALSO
L<EVP_PKEY_CTX_new_from_pkey(3)>,
L<EVP_PKEY_decapsulate(3)>,
L<EVP_KEM-RSA(7)>,
=head1 HISTORY
These functions were added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/OSSL_CMP_CTX_new.pod b/crypto/openssl/doc/man3/OSSL_CMP_CTX_new.pod
index cab88ae88c91..f2a38b0adef4 100644
--- a/crypto/openssl/doc/man3/OSSL_CMP_CTX_new.pod
+++ b/crypto/openssl/doc/man3/OSSL_CMP_CTX_new.pod
@@ -1,812 +1,814 @@
=pod
=head1 NAME
OSSL_CMP_CTX_new,
OSSL_CMP_CTX_free,
OSSL_CMP_CTX_reinit,
OSSL_CMP_CTX_set_option,
OSSL_CMP_CTX_get_option,
OSSL_CMP_CTX_set_log_cb,
OSSL_CMP_CTX_set_log_verbosity,
OSSL_CMP_CTX_print_errors,
OSSL_CMP_CTX_set1_serverPath,
OSSL_CMP_CTX_set1_server,
OSSL_CMP_CTX_set_serverPort,
OSSL_CMP_CTX_set1_proxy,
OSSL_CMP_CTX_set1_no_proxy,
OSSL_CMP_CTX_set_http_cb,
OSSL_CMP_CTX_set_http_cb_arg,
OSSL_CMP_CTX_get_http_cb_arg,
OSSL_CMP_transfer_cb_t,
OSSL_CMP_CTX_set_transfer_cb,
OSSL_CMP_CTX_set_transfer_cb_arg,
OSSL_CMP_CTX_get_transfer_cb_arg,
OSSL_CMP_CTX_set1_srvCert,
OSSL_CMP_CTX_set1_expected_sender,
OSSL_CMP_CTX_set0_trustedStore,
OSSL_CMP_CTX_get0_trustedStore,
OSSL_CMP_CTX_set1_untrusted,
OSSL_CMP_CTX_get0_untrusted,
OSSL_CMP_CTX_set1_cert,
OSSL_CMP_CTX_build_cert_chain,
OSSL_CMP_CTX_set1_pkey,
OSSL_CMP_CTX_set1_referenceValue,
OSSL_CMP_CTX_set1_secretValue,
OSSL_CMP_CTX_set1_recipient,
OSSL_CMP_CTX_push0_geninfo_ITAV,
OSSL_CMP_CTX_reset_geninfo_ITAVs,
OSSL_CMP_CTX_set1_extraCertsOut,
OSSL_CMP_CTX_set0_newPkey,
OSSL_CMP_CTX_get0_newPkey,
OSSL_CMP_CTX_set1_issuer,
OSSL_CMP_CTX_set1_subjectName,
OSSL_CMP_CTX_push1_subjectAltName,
OSSL_CMP_CTX_set0_reqExtensions,
OSSL_CMP_CTX_reqExtensions_have_SAN,
OSSL_CMP_CTX_push0_policy,
OSSL_CMP_CTX_set1_oldCert,
OSSL_CMP_CTX_set1_p10CSR,
OSSL_CMP_CTX_push0_genm_ITAV,
OSSL_CMP_certConf_cb_t,
OSSL_CMP_certConf_cb,
OSSL_CMP_CTX_set_certConf_cb,
OSSL_CMP_CTX_set_certConf_cb_arg,
OSSL_CMP_CTX_get_certConf_cb_arg,
OSSL_CMP_CTX_get_status,
OSSL_CMP_CTX_get0_statusString,
OSSL_CMP_CTX_get_failInfoCode,
OSSL_CMP_CTX_get0_newCert,
OSSL_CMP_CTX_get1_newChain,
OSSL_CMP_CTX_get1_caPubs,
OSSL_CMP_CTX_get1_extraCertsIn,
OSSL_CMP_CTX_set1_transactionID,
OSSL_CMP_CTX_set1_senderNonce
- functions for managing the CMP client context data structure
=head1 SYNOPSIS
#include <openssl/cmp.h>
OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq);
void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val);
int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt);
/* logging and error reporting: */
int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb);
#define OSSL_CMP_CTX_set_log_verbosity(ctx, level)
void OSSL_CMP_CTX_print_errors(const OSSL_CMP_CTX *ctx);
/* message transfer: */
int OSSL_CMP_CTX_set1_serverPath(OSSL_CMP_CTX *ctx, const char *path);
int OSSL_CMP_CTX_set1_server(OSSL_CMP_CTX *ctx, const char *address);
int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port);
int OSSL_CMP_CTX_set1_proxy(OSSL_CMP_CTX *ctx, const char *name);
int OSSL_CMP_CTX_set1_no_proxy(OSSL_CMP_CTX *ctx, const char *names);
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, HTTP_bio_cb_t cb);
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx);
typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t)(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req);
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx,
OSSL_CMP_transfer_cb_t cb);
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx);
/* server authentication: */
int OSSL_CMP_CTX_set1_srvCert(OSSL_CMP_CTX *ctx, X509 *cert);
int OSSL_CMP_CTX_set1_expected_sender(OSSL_CMP_CTX *ctx,
const X509_NAME *name);
int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store);
X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs);
STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx);
/* client authentication: */
int OSSL_CMP_CTX_set1_cert(OSSL_CMP_CTX *ctx, X509 *cert);
int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted,
STACK_OF(X509) *candidates);
int OSSL_CMP_CTX_set1_pkey(OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
const unsigned char *ref, int len);
int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx,
const unsigned char *sec, int len);
/* CMP message header and extra certificates: */
int OSSL_CMP_CTX_set1_recipient(OSSL_CMP_CTX *ctx, const X509_NAME *name);
int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *extraCertsOut);
/* certificate template: */
int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey);
EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv);
int OSSL_CMP_CTX_set1_issuer(OSSL_CMP_CTX *ctx, const X509_NAME *name);
int OSSL_CMP_CTX_set1_subjectName(OSSL_CMP_CTX *ctx, const X509_NAME *name);
int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
const GENERAL_NAME *name);
int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts);
int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo);
int OSSL_CMP_CTX_set1_oldCert(OSSL_CMP_CTX *ctx, X509 *cert);
int OSSL_CMP_CTX_set1_p10CSR(OSSL_CMP_CTX *ctx, const X509_REQ *csr);
/* misc body contents: */
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
/* certificate confirmation: */
typedef int (*OSSL_CMP_certConf_cb_t)(OSSL_CMP_CTX *ctx, X509 *cert,
int fail_info, const char **txt);
int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
const char **text);
int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb);
int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx);
/* result fetching: */
int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx);
OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx);
X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx);
STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx);
STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx);
STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx);
/* for testing and debugging purposes: */
int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *id);
int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce);
=head1 DESCRIPTION
This is the context API for using CMP (Certificate Management Protocol) with
OpenSSL.
OSSL_CMP_CTX_new() allocates an B<OSSL_CMP_CTX> structure associated with
the library context I<libctx> and property query string I<propq>,
both of which may be NULL to select the defaults.
It initializes the remaining fields to their default values - for instance,
the logging verbosity is set to OSSL_CMP_LOG_INFO,
the message timeout is set to 120 seconds,
and the proof-of-possession method is set to OSSL_CRMF_POPO_SIGNATURE.
OSSL_CMP_CTX_free() deallocates an OSSL_CMP_CTX structure.
If the argument is NULL, nothing is done.
OSSL_CMP_CTX_reinit() prepares the given I<ctx> for a further transaction by
clearing the internal CMP transaction (aka session) status, PKIStatusInfo,
and any previous results (newCert, newChain, caPubs, and extraCertsIn)
from the last executed transaction.
It also clears any ITAVs that were added by OSSL_CMP_CTX_push0_genm_ITAV().
All other field values (i.e., CMP options) are retained for potential reuse.
OSSL_CMP_CTX_set_option() sets the given value for the given option
(e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) in the given OSSL_CMP_CTX structure.
The following options can be set:
=over 4
=item B<OSSL_CMP_OPT_LOG_VERBOSITY>
The level of severity needed for actually outputting log messages
due to errors, warnings, general info, debugging, etc.
Default is OSSL_CMP_LOG_INFO. See also L<OSSL_CMP_log_open(3)>.
=item B<OSSL_CMP_OPT_KEEP_ALIVE>
If the given value is 0 then HTTP connections are not kept open
after receiving a response, which is the default behavior for HTTP 1.0.
If the value is 1 or 2 then persistent connections are requested.
If the value is 2 then persistent connections are required,
i.e., in case the server does not grant them an error occurs.
The default value is 1: prefer to keep the connection open.
=item B<OSSL_CMP_OPT_MSG_TIMEOUT>
Number of seconds a CMP request-response message round trip
is allowed to take before a timeout error is returned.
A value <= 0 means no limitation (waiting indefinitely).
Default is to use the B<OSSL_CMP_OPT_TOTAL_TIMEOUT> setting.
=item B<OSSL_CMP_OPT_TOTAL_TIMEOUT>
Maximum total number of seconds a transaction may take,
including polling etc.
A value <= 0 means no limitation (waiting indefinitely).
Default is 0.
=item B<OSSL_CMP_OPT_VALIDITY_DAYS>
Number of days new certificates are asked to be valid for.
=item B<OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT>
Do not take default Subject Alternative Names
from the reference certificate.
=item B<OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL>
Demand that the given Subject Alternative Names are flagged as critical.
=item B<OSSL_CMP_OPT_POLICIES_CRITICAL>
Demand that the given policies are flagged as critical.
=item B<OSSL_CMP_OPT_POPO_METHOD>
Select the proof of possession method to use. Possible values are:
OSSL_CRMF_POPO_NONE - ProofOfPossession field omitted
OSSL_CRMF_POPO_RAVERIFIED - assert that the RA has already
verified the PoPo
OSSL_CRMF_POPO_SIGNATURE - sign a value with private key,
which is the default.
OSSL_CRMF_POPO_KEYENC - decrypt the encrypted certificate
("indirect method")
Note that a signature-based POPO can only be produced if a private key
is provided as the newPkey or client's pkey component of the CMP context.
=item B<OSSL_CMP_OPT_DIGEST_ALGNID>
The NID of the digest algorithm to be used in RFC 4210's MSG_SIG_ALG
for signature-based message protection and Proof-of-Possession (POPO).
Default is SHA256.
=item B<OSSL_CMP_OPT_OWF_ALGNID>
The NID of the digest algorithm to be used as one-way function (OWF)
for MAC-based message protection with password-based MAC (PBM).
See RFC 4210 section 5.1.3.1 for details.
Default is SHA256.
=item B<OSSL_CMP_OPT_MAC_ALGNID>
The NID of the MAC algorithm to be used for message protection with PBM.
Default is HMAC-SHA1 as per RFC 4210.
=item B<OSSL_CMP_OPT_REVOCATION_REASON>
The reason code to be included in a Revocation Request (RR);
values: 0..10 (RFC 5210, 5.3.1) or -1 for none, which is the default.
=item B<OSSL_CMP_OPT_IMPLICIT_CONFIRM>
Request server to enable implicit confirm mode, where the client
does not need to send confirmation upon receiving the
certificate. If the server does not enable implicit confirmation
in the return message, then confirmation is sent anyway.
=item B<OSSL_CMP_OPT_DISABLE_CONFIRM>
Do not confirm enrolled certificates, to cope with broken servers
not supporting implicit confirmation correctly.
B<WARNING:> This setting leads to unspecified behavior and it is meant
exclusively to allow interoperability with server implementations violating
RFC 4210.
=item B<OSSL_CMP_OPT_UNPROTECTED_SEND>
Send request or response messages without CMP-level protection.
=item B<OSSL_CMP_OPT_UNPROTECTED_ERRORS>
Accept unprotected error responses which are either explicitly
unprotected or where protection verification failed. Applies to regular
error messages as well as certificate responses (IP/CP/KUP) and
revocation responses (RP) with rejection.
B<WARNING:> This setting leads to unspecified behavior and it is meant
exclusively to allow interoperability with server implementations violating
RFC 4210.
=item B<OSSL_CMP_OPT_IGNORE_KEYUSAGE>
Ignore key usage restrictions in the signer's certificate when
validating signature-based protection in received CMP messages.
Else, 'digitalSignature' must be allowed by CMP signer certificates.
=item B<OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR>
Allow retrieving a trust anchor from extraCerts and using that
to validate the certificate chain of an IP message.
This is a quirk option added to support 3GPP TS 33.310.
Note that using this option is dangerous as the certificate obtained
this way has not been authenticated (at least not at CMP level).
Taking it over as a trust anchor implements trust-on-first-use (TOFU).
=back
OSSL_CMP_CTX_get_option() reads the current value of the given option
(e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) from the given OSSL_CMP_CTX structure.
OSSL_CMP_CTX_set_log_cb() sets in I<ctx> the callback function I<cb>
for handling error queue entries and logging messages.
When I<cb> is NULL errors are printed to STDERR (if available, else ignored)
any log messages are ignored.
Alternatively, L<OSSL_CMP_log_open(3)> may be used to direct logging to STDOUT.
OSSL_CMP_CTX_set_log_verbosity() is a macro setting the
OSSL_CMP_OPT_LOG_VERBOSITY context option to the given level.
OSSL_CMP_CTX_print_errors() outputs any entries in the OpenSSL error queue. It
is similar to L<ERR_print_errors_cb(3)> but uses the CMP log callback function
if set in the I<ctx> for uniformity with CMP logging if given. Otherwise it uses
L<ERR_print_errors(3)> to print to STDERR (unless OPENSSL_NO_STDIO is defined).
OSSL_CMP_CTX_set1_serverPath() sets the HTTP path of the CMP server on the host,
also known as "CMP alias".
The default is C</>.
OSSL_CMP_CTX_set1_server() sets the given server I<address>
(which may be a hostname or IP address or NULL) in the given I<ctx>.
OSSL_CMP_CTX_set_serverPort() sets the port of the CMP server to connect to.
If not used or the I<port> argument is 0
the default port applies, which is 80 for HTTP and 443 for HTTPS.
OSSL_CMP_CTX_set1_proxy() sets the HTTP proxy to be used for connecting to
the given CMP server unless overruled by any "no_proxy" settings (see below).
If TLS is not used this defaults to the value of
the environment variable C<http_proxy> if set, else C<HTTP_PROXY>.
Otherwise defaults to the value of C<https_proxy> if set, else C<HTTPS_PROXY>.
An empty proxy string specifies not to use a proxy.
-Else the format is C<[http[s]://]address[:port][/path]>,
-where any path given is ignored.
+Otherwise the format is
+C<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>,
+where any given userinfo, path, query, and fragment is ignored.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
The default port number is 80, or 443 in case C<https:> is given.
OSSL_CMP_CTX_set1_no_proxy() sets the list of server hostnames not to use
an HTTP proxy for. The names may be separated by commas and/or whitespace.
Defaults to the environment variable C<no_proxy> if set, else C<NO_PROXY>.
OSSL_CMP_CTX_set_http_cb() sets the optional BIO connect/disconnect callback
function, which has the prototype
typedef BIO *(*HTTP_bio_cb_t) (BIO *bio, void *ctx, int connect, int detail);
The callback may modify the I<bio> provided by L<OSSL_CMP_MSG_http_perform(3)>,
whereby it may make use of a custom defined argument I<ctx>
stored in the OSSL_CMP_CTX by means of OSSL_CMP_CTX_set_http_cb_arg().
During connection establishment, just after calling BIO_do_connect_retry(),
the function is invoked with the I<connect> argument being 1 and the I<detail>
argument being 1 if HTTPS is requested, i.e., SSL/TLS should be enabled. On
disconnect I<connect> is 0 and I<detail> is 1 in case no error occurred, else 0.
For instance, on connect the function may prepend a TLS BIO to implement HTTPS;
after disconnect it may do some diagnostic output and/or specific cleanup.
The function should return NULL to indicate failure.
After disconnect the modified BIO will be deallocated using BIO_free_all().
OSSL_CMP_CTX_set_http_cb_arg() sets an argument, respectively a pointer to
a structure containing arguments,
optionally to be used by the http connect/disconnect callback function.
I<arg> is not consumed, and it must therefore explicitly be freed when not
needed any more. I<arg> may be NULL to clear the entry.
OSSL_CMP_CTX_get_http_cb_arg() gets the argument, respectively the pointer to a
structure containing arguments, previously set by
OSSL_CMP_CTX_set_http_cb_arg() or NULL if unset.
OSSL_CMP_CTX_set_transfer_cb() sets the message transfer callback function,
which has the type
typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t) (OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req);
Returns 1 on success, 0 on error.
Default is NULL, which implies the use of L<OSSL_CMP_MSG_http_perform(3)>.
The callback should send the CMP request message it obtains via the I<req>
parameter and on success return the response, else it must return NULL.
The transfer callback may make use of a custom defined argument stored in
the ctx by means of OSSL_CMP_CTX_set_transfer_cb_arg(), which may be retrieved
again through OSSL_CMP_CTX_get_transfer_cb_arg().
OSSL_CMP_CTX_set_transfer_cb_arg() sets an argument, respectively a pointer to a
structure containing arguments, optionally to be used by the transfer callback.
I<arg> is not consumed, and it must therefore explicitly be freed when not
needed any more. I<arg> may be NULL to clear the entry.
OSSL_CMP_CTX_get_transfer_cb_arg() gets the argument, respectively the pointer
to a structure containing arguments, previously set by
OSSL_CMP_CTX_set_transfer_cb_arg() or NULL if unset.
OSSL_CMP_CTX_set1_srvCert() sets the expected server cert in I<ctx> and trusts
it directly (even if it is expired) when verifying signed response messages.
This pins the accepted CMP server and
results in ignoring whatever may be set using OSSL_CMP_CTX_set0_trustedStore().
Any previously set value is freed.
The I<cert> argument may be NULL to clear the entry.
If set, the subject of the certificate is also used
as default value for the recipient of CMP requests
and as default value for the expected sender of CMP responses.
OSSL_CMP_CTX_set1_expected_sender() sets the Distinguished Name (DN)
expected in the sender field of incoming CMP messages.
Defaults to the subject of the pinned server certificate, if any.
This can be used to make sure that only a particular entity is accepted as
CMP message signer, and attackers are not able to use arbitrary certificates
of a trusted PKI hierarchy to fraudulently pose as CMP server.
Note that this gives slightly more freedom than OSSL_CMP_CTX_set1_srvCert(),
which pins the server to the holder of a particular certificate, while the
expected sender name will continue to match after updates of the server cert.
OSSL_CMP_CTX_set0_trustedStore()
sets in the CMP context I<ctx> the certificate store of type X509_STORE
containing trusted certificates, typically of root CAs.
This is ignored when a certificate is pinned using OSSL_CMP_CTX_set1_srvCert().
The store may also hold CRLs and a certificate verification callback function
used for signature-based peer authentication.
Any store entry already set before is freed.
When given a NULL parameter the entry is cleared.
OSSL_CMP_CTX_get0_trustedStore()
extracts from the CMP context I<ctx> the pointer to the currently set
certificate store containing trust anchors etc., or an empty store if unset.
OSSL_CMP_CTX_set1_untrusted() sets up a list of non-trusted certificates
of intermediate CAs that may be useful for path construction for the own CMP
signer certificate, for the own TLS certificate (if any), when verifying peer
CMP protection certificates, and when verifying newly enrolled certificates.
The reference counts of those certificates handled successfully are increased.
OSSL_CMP_CTX_get0_untrusted(OSSL_CMP_CTX *ctx) returns a pointer to the
list of untrusted certs, which may be empty if unset.
OSSL_CMP_CTX_set1_cert() sets the CMP signer certificate, also called protection
certificate, related to the private key for signature-based message protection.
Therefore the public key of this I<cert> must correspond to
the private key set before or thereafter via OSSL_CMP_CTX_set1_pkey().
When using signature-based protection of CMP request messages
this CMP signer certificate will be included first in the extraCerts field.
It serves as fallback reference certificate, see OSSL_CMP_CTX_set1_oldCert().
The subject of this I<cert> will be used as the sender field of outgoing
messages, while the subject of any cert set via OSSL_CMP_CTX_set1_oldCert()
and any value set via OSSL_CMP_CTX_set1_subjectName() are used as fallback.
The I<cert> argument may be NULL to clear the entry.
OSSL_CMP_CTX_build_cert_chain() builds a certificate chain for the CMP signer
certificate previously set in the I<ctx>. It adds the optional I<candidates>,
a list of intermediate CA certs that may already constitute the targeted chain,
to the untrusted certs that may already exist in the I<ctx>.
Then the function uses this augmented set of certs for chain construction.
If I<own_trusted> is NULL it builds the chain as far down as possible and
ignores any verification errors. Else the CMP signer certificate must be
verifiable where the chain reaches a trust anchor contained in I<own_trusted>.
On success the function stores the resulting chain in I<ctx>
for inclusion in the extraCerts field of signature-protected messages.
Calling this function is optional; by default a chain construction
is performed on demand that is equivalent to calling this function
with the I<candidates> and I<own_trusted> arguments being NULL.
OSSL_CMP_CTX_set1_pkey() sets the client's private key corresponding to the
CMP signer certificate set via OSSL_CMP_CTX_set1_cert().
This key is used create signature-based protection (protectionAlg = MSG_SIG_ALG)
of outgoing messages
unless a symmetric secret has been set via OSSL_CMP_CTX_set1_secretValue().
The I<pkey> argument may be NULL to clear the entry.
OSSL_CMP_CTX_set1_secretValue() sets in I<ctx> the byte string I<sec> of length
I<len> to use as pre-shared secret, or clears it if the I<sec> argument is NULL.
If present, this secret is used to create MAC-based authentication and integrity
protection (rather than applying signature-based protection)
of outgoing messages and to verify authenticity and integrity of incoming
messages that have MAC-based protection (protectionAlg = C<MSG_MAC_ALG>).
OSSL_CMP_CTX_set1_referenceValue() sets the given referenceValue I<ref> with
length I<len> in the given I<ctx> or clears it if the I<ref> argument is NULL.
According to RFC 4210 section 5.1.1, if no value for the sender field in
CMP message headers can be determined (i.e., no CMP signer certificate
and no subject DN is set via OSSL_CMP_CTX_set1_subjectName()
then the sender field will contain the NULL-DN
and the senderKID field of the CMP message header must be set.
When signature-based protection is used the senderKID will be set to
the subjectKeyIdentifier of the CMP signer certificate as far as present.
If not present or when MAC-based protection is used
the I<ref> value is taken as the fallback value for the senderKID.
OSSL_CMP_CTX_set1_recipient() sets the recipient name that will be used in the
PKIHeader of CMP request messages, i.e. the X509 name of the (CA) server.
The recipient field in the header of a CMP message is mandatory.
If not given explicitly the recipient is determined in the following order:
the subject of the CMP server certificate set using OSSL_CMP_CTX_set1_srvCert(),
the value set using OSSL_CMP_CTX_set1_issuer(),
the issuer of the certificate set using OSSL_CMP_CTX_set1_oldCert(),
the issuer of the CMP signer certificate,
as far as any of those is present, else the NULL-DN as last resort.
OSSL_CMP_CTX_push0_geninfo_ITAV() adds I<itav> to the stack in the I<ctx> to be
added to the GeneralInfo field of the CMP PKIMessage header of a request
message sent with this context.
OSSL_CMP_CTX_reset_geninfo_ITAVs()
clears any ITAVs that were added by OSSL_CMP_CTX_push0_geninfo_ITAV().
OSSL_CMP_CTX_set1_extraCertsOut() sets the stack of extraCerts that will be
sent to remote.
OSSL_CMP_CTX_set0_newPkey() can be used to explicitly set the given EVP_PKEY
structure as the private or public key to be certified in the CMP context.
The I<priv> parameter must be 0 if and only if the given key is a public key.
OSSL_CMP_CTX_get0_newPkey() gives the key to use for certificate enrollment
dependent on fields of the CMP context structure:
the newPkey (which may be a private or public key) if present,
else the public key in the p10CSR if present, else the client's private key.
If the I<priv> parameter is not 0 and the selected key does not have a
private component then NULL is returned.
OSSL_CMP_CTX_set1_issuer() sets the name of the intended issuer that
will be set in the CertTemplate, i.e., the X509 name of the CA server.
OSSL_CMP_CTX_set1_subjectName() sets the subject DN that will be used in
the CertTemplate structure when requesting a new cert. For Key Update Requests
(KUR), it defaults to the subject DN of the reference certificate,
see OSSL_CMP_CTX_set1_oldCert(). This default is used for Initialization
Requests (IR) and Certification Requests (CR) only if no SANs are set.
The I<subjectName> is also used as fallback for the sender field
of outgoing CMP messages if no reference certificate is available.
OSSL_CMP_CTX_push1_subjectAltName() adds the given X509 name to the list of
alternate names on the certificate template request. This cannot be used if
any Subject Alternative Name extension is set via
OSSL_CMP_CTX_set0_reqExtensions().
By default, unless B<OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT> has been set,
the Subject Alternative Names are copied from the reference certificate,
see OSSL_CMP_CTX_set1_oldCert().
If set and the subject DN is not set with OSSL_CMP_CTX_set1_subjectName() then
the certificate template of an IR and CR will not be filled with the default
subject DN from the reference certificate.
If a subject DN is desired it needs to be set explicitly with
OSSL_CMP_CTX_set1_subjectName().
OSSL_CMP_CTX_set0_reqExtensions() sets the X.509v3 extensions to be used in
IR/CR/KUR.
OSSL_CMP_CTX_reqExtensions_have_SAN() returns 1 if the context contains
a Subject Alternative Name extension, else 0 or -1 on error.
OSSL_CMP_CTX_push0_policy() adds the certificate policy info object
to the X509_EXTENSIONS of the requested certificate template.
OSSL_CMP_CTX_set1_oldCert() sets the old certificate to be updated in
Key Update Requests (KUR) or to be revoked in Revocation Requests (RR).
It must be given for RR, else it defaults to the CMP signer certificate.
The I<reference certificate> determined in this way, if any, is also used for
deriving default subject DN, public key, Subject Alternative Names, and the
default issuer entry in the requested certificate template of IR/CR/KUR.
The subject of the reference certificate is used as the sender field value
in CMP message headers.
Its issuer is used as default recipient in CMP message headers.
OSSL_CMP_CTX_set1_p10CSR() sets the PKCS#10 CSR to use in P10CR messages.
If such a CSR is provided, its subject, public key, and extension fields are
also used as fallback values for the certificate template of IR/CR/KUR messages.
OSSL_CMP_CTX_push0_genm_ITAV() adds I<itav> to the stack in the I<ctx> which
will be the body of a General Message sent with this context.
OSSL_CMP_certConf_cb() is the default certificate confirmation callback function.
If the callback argument is not NULL it must point to a trust store.
In this case the function checks that the newly enrolled certificate can be
verified using this trust store and untrusted certificates from the I<ctx>,
which have been augmented by the list of extraCerts received.
During this verification, any certificate status checking is disabled.
If the callback argument is NULL the function tries building an approximate
chain as far as possible using the same untrusted certificates from the I<ctx>,
and if this fails it takes the received extraCerts as fallback.
The resulting cert chain can be retrieved using OSSL_CMP_CTX_get1_newChain().
OSSL_CMP_CTX_set_certConf_cb() sets the callback used for evaluating the newly
enrolled certificate before the library sends, depending on its result,
a positive or negative certConf message to the server. The callback has type
typedef int (*OSSL_CMP_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert,
int fail_info, const char **txt);
and should inspect the certificate it obtains via the I<cert> parameter and may
overrule the pre-decision given in the I<fail_info> and I<*txt> parameters.
If it accepts the certificate it must return 0, indicating success. Else it must
return a bit field reflecting PKIFailureInfo with at least one failure bit and
may set the I<*txt> output parameter to point to a string constant with more
detail. The transfer callback may make use of a custom defined argument stored
in the I<ctx> by means of OSSL_CMP_CTX_set_certConf_cb_arg(), which may be
retrieved again through OSSL_CMP_CTX_get_certConf_cb_arg().
Typically, the callback will check at least that the certificate can be verified
using a set of trusted certificates.
It also could compare the subject DN and other fields of the newly
enrolled certificate with the certificate template of the request.
OSSL_CMP_CTX_set_certConf_cb_arg() sets an argument, respectively a pointer to a
structure containing arguments, optionally to be used by the certConf callback.
I<arg> is not consumed, and it must therefore explicitly be freed when not
needed any more. I<arg> may be NULL to clear the entry.
OSSL_CMP_CTX_get_certConf_cb_arg() gets the argument, respectively the pointer
to a structure containing arguments, previously set by
OSSL_CMP_CTX_set_certConf_cb_arg(), or NULL if unset.
OSSL_CMP_CTX_get_status() returns for client contexts the PKIstatus from
the last received CertRepMessage or Revocation Response or error message:
=item B<OSSL_CMP_PKISTATUS_accepted> on successful receipt of a GENP message:
=over 4
=item B<OSSL_CMP_PKISTATUS_request>
if an IR/CR/KUR/RR/GENM request message could not be produced,
=item B<OSSL_CMP_PKISTATUS_trans>
on a transmission error or transaction error for this type of request, and
=item B<OSSL_CMP_PKISTATUS_unspecified>
if no such request was attempted or OSSL_CMP_CTX_reinit() has been called.
=back
For server contexts it returns
B<OSSL_CMP_PKISTATUS_trans> if a transaction is open,
otherwise B<OSSL_CMP_PKISTATUS_unspecified>.
OSSL_CMP_CTX_get0_statusString() returns the statusString from the last received
CertRepMessage or Revocation Response or error message, or NULL if unset.
OSSL_CMP_CTX_get_failInfoCode() returns the error code from the failInfo field
of the last received CertRepMessage or Revocation Response or error message,
or -1 if no such response was received or OSSL_CMP_CTX_reinit() has been called.
This is a bit field and the flags for it are specified in the header file
F<< <openssl/cmp.h> >>.
The flags start with OSSL_CMP_CTX_FAILINFO, for example:
OSSL_CMP_CTX_FAILINFO_badAlg. Returns -1 if the failInfoCode field is unset.
OSSL_CMP_CTX_get0_newCert() returns the pointer to the newly obtained
certificate in case it is available, else NULL.
OSSL_CMP_CTX_get1_newChain() returns a pointer to a duplicate of the stack of
X.509 certificates computed by OSSL_CMP_certConf_cb() (if this function has
been called) on the last received certificate response message IP/CP/KUP.
OSSL_CMP_CTX_get1_caPubs() returns a pointer to a duplicate of the list of
X.509 certificates in the caPubs field of the last received certificate
response message (of type IP, CP, or KUP),
or an empty stack if no caPubs have been received in the current transaction.
OSSL_CMP_CTX_get1_extraCertsIn() returns a pointer to a duplicate of the list
of X.509 certificates contained in the extraCerts field of the last received
response message (except for pollRep and PKIConf), or
an empty stack if no extraCerts have been received in the current transaction.
OSSL_CMP_CTX_set1_transactionID() sets the given transaction ID in the given
OSSL_CMP_CTX structure.
OSSL_CMP_CTX_set1_senderNonce() stores the last sent sender I<nonce> in
the I<ctx>. This will be used to validate the recipNonce in incoming messages.
=head1 NOTES
CMP is defined in RFC 4210 (and CRMF in RFC 4211).
=head1 RETURN VALUES
OSSL_CMP_CTX_free() and OSSL_CMP_CTX_print_errors() do not return anything.
OSSL_CMP_CTX_new(),
OSSL_CMP_CTX_get_http_cb_arg(),
OSSL_CMP_CTX_get_transfer_cb_arg(),
OSSL_CMP_CTX_get0_trustedStore(),
OSSL_CMP_CTX_get0_untrusted(),
OSSL_CMP_CTX_get0_newPkey(),
OSSL_CMP_CTX_get_certConf_cb_arg(),
OSSL_CMP_CTX_get0_statusString(),
OSSL_CMP_CTX_get0_newCert(),
OSSL_CMP_CTX_get0_newChain(),
OSSL_CMP_CTX_get1_caPubs(), and
OSSL_CMP_CTX_get1_extraCertsIn()
return the intended pointer value as described above or NULL on error.
OSSL_CMP_CTX_get_option(),
OSSL_CMP_CTX_reqExtensions_have_SAN(),
OSSL_CMP_CTX_get_status(), and
OSSL_CMP_CTX_get_failInfoCode()
return the intended value as described above or -1 on error.
OSSL_CMP_certConf_cb() returns I<fail_info> if it is not equal to 0,
else 0 on successful validation,
or else a bit field with the B<OSSL_CMP_PKIFAILUREINFO_incorrectData> bit set.
All other functions, including OSSL_CMP_CTX_reinit()
and OSSL_CMP_CTX_reset_geninfo_ITAVs(),
return 1 on success, 0 on error.
=head1 EXAMPLES
The following code omits error handling.
Set up a CMP client context for sending requests and verifying responses:
cmp_ctx = OSSL_CMP_CTX_new();
OSSL_CMP_CTX_set1_server(cmp_ctx, name_or_address);
OSSL_CMP_CTX_set1_serverPort(cmp_ctx, port_string);
OSSL_CMP_CTX_set1_serverPath(cmp_ctx, path_or_alias);
OSSL_CMP_CTX_set0_trustedStore(cmp_ctx, ts);
Set up symmetric credentials for MAC-based message protection such as PBM:
OSSL_CMP_CTX_set1_referenceValue(cmp_ctx, ref, ref_len);
OSSL_CMP_CTX_set1_secretValue(cmp_ctx, sec, sec_len);
Set up the details for certificate requests:
OSSL_CMP_CTX_set1_subjectName(cmp_ctx, name);
OSSL_CMP_CTX_set0_newPkey(cmp_ctx, 1, initialKey);
Perform an Initialization Request transaction:
initialCert = OSSL_CMP_exec_IR_ses(cmp_ctx);
Reset the transaction state of the CMP context and the credentials:
OSSL_CMP_CTX_reinit(cmp_ctx);
OSSL_CMP_CTX_set1_referenceValue(cmp_ctx, NULL, 0);
OSSL_CMP_CTX_set1_secretValue(cmp_ctx, NULL, 0);
Perform a Certification Request transaction, making use of the new credentials:
OSSL_CMP_CTX_set1_cert(cmp_ctx, initialCert);
OSSL_CMP_CTX_set1_pkey(cmp_ctx, initialKey);
OSSL_CMP_CTX_set0_newPkey(cmp_ctx, 1, curentKey);
currentCert = OSSL_CMP_exec_CR_ses(cmp_ctx);
Perform a Key Update Request, signed using the cert (and key) to be updated:
OSSL_CMP_CTX_reinit(cmp_ctx);
OSSL_CMP_CTX_set1_cert(cmp_ctx, currentCert);
OSSL_CMP_CTX_set1_pkey(cmp_ctx, currentKey);
OSSL_CMP_CTX_set0_newPkey(cmp_ctx, 1, updatedKey);
currentCert = OSSL_CMP_exec_KUR_ses(cmp_ctx);
currentKey = updatedKey;
Perform a General Message transaction including, as an example,
the id-it-signKeyPairTypes OID and prints info on the General Response contents:
OSSL_CMP_CTX_reinit(cmp_ctx);
ASN1_OBJECT *type = OBJ_txt2obj("1.3.6.1.5.5.7.4.2", 1);
OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_create(type, NULL);
OSSL_CMP_CTX_push0_genm_ITAV(cmp_ctx, itav);
STACK_OF(OSSL_CMP_ITAV) *itavs;
itavs = OSSL_CMP_exec_GENM_ses(cmp_ctx);
print_itavs(itavs);
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
=head1 SEE ALSO
L<OSSL_CMP_exec_IR_ses(3)>, L<OSSL_CMP_exec_CR_ses(3)>,
L<OSSL_CMP_exec_KUR_ses(3)>, L<OSSL_CMP_exec_GENM_ses(3)>,
L<OSSL_CMP_exec_certreq(3)>, L<OSSL_CMP_MSG_http_perform(3)>,
L<ERR_print_errors_cb(3)>
=head1 HISTORY
The OpenSSL CMP support was added in OpenSSL 3.0.
OSSL_CMP_CTX_reset_geninfo_ITAVs() was added in OpenSSL 3.0.8.
=head1 COPYRIGHT
Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/OSSL_CMP_validate_msg.pod b/crypto/openssl/doc/man3/OSSL_CMP_validate_msg.pod
index 555624a40358..c5e68065beff 100644
--- a/crypto/openssl/doc/man3/OSSL_CMP_validate_msg.pod
+++ b/crypto/openssl/doc/man3/OSSL_CMP_validate_msg.pod
@@ -1,87 +1,87 @@
=pod
=head1 NAME
OSSL_CMP_validate_msg,
OSSL_CMP_validate_cert_path
- functions for verifying CMP message protection
=head1 SYNOPSIS
#include <openssl/cmp.h>
int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
X509_STORE *trusted_store, X509 *cert);
=head1 DESCRIPTION
This is the API for validating the protection of CMP messages,
which includes validating CMP message sender certificates and their paths
while optionally checking the revocation status of the certificates(s).
OSSL_CMP_validate_msg() validates the protection of the given I<msg>,
which must be signature-based or using password-based MAC (PBM).
In the former case a suitable trust anchor must be given in the CMP context
I<ctx>, and in the latter case the matching secret must have been set there
using L<OSSL_CMP_CTX_set1_secretValue(3)>.
In case of signature algorithm, the certificate to use for the signature check
is preferably the one provided by a call to L<OSSL_CMP_CTX_set1_srvCert(3)>.
If no such sender cert has been pinned then candidate sender certificates are
taken from the list of certificates received in the I<msg> extraCerts, then any
certificates provided before via L<OSSL_CMP_CTX_set1_untrusted(3)>, and
then all trusted certificates provided via L<OSSL_CMP_CTX_set0_trustedStore(3)>,
where a candidate is acceptable only if has not expired, its subject DN matches
the I<msg> sender DN (as far as present), and its subject key identifier
is present and matches the senderKID (as far as the latter present).
Each acceptable cert is tried in the given order to see if the message
signature check succeeds and the cert and its path can be verified
using any trust store set via L<OSSL_CMP_CTX_set0_trustedStore(3)>.
If the option OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR was set by calling
L<OSSL_CMP_CTX_set_option(3)>, for an Initialization Response (IP) message
any self-issued certificate from the I<msg> extraCerts field may be used
as a trust anchor for the path verification of an 'acceptable' cert if it can be
used also to validate the issued certificate returned in the IP message. This is
according to TS 33.310 [Network Domain Security (NDS); Authentication Framework
-(AF)] document specified by the The 3rd Generation Partnership Project (3GPP).
+(AF)] document specified by The 3rd Generation Partnership Project (3GPP).
Note that using this option is dangerous as the certificate obtained this way
has not been authenticated (at least not at CMP level).
Taking it over as a trust anchor implements trust-on-first-use (TOFU).
Any cert that has been found as described above is cached and tried first when
validating the signatures of subsequent messages in the same transaction.
OSSL_CMP_validate_cert_path() attempts to validate the given certificate and its
path using the given store of trusted certs (possibly including CRLs and a cert
verification callback) and non-trusted intermediate certs from the I<ctx>.
=head1 NOTES
CMP is defined in RFC 4210 (and CRMF in RFC 4211).
=head1 RETURN VALUES
OSSL_CMP_validate_msg() and OSSL_CMP_validate_cert_path()
return 1 on success, 0 on error or validation failed.
=head1 SEE ALSO
L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_exec_certreq(3)>,
L<OSSL_CMP_CTX_set1_secretValue(3)>, L<OSSL_CMP_CTX_set1_srvCert(3)>,
L<OSSL_CMP_CTX_set1_untrusted(3)>, L<OSSL_CMP_CTX_set0_trustedStore(3)>
=head1 HISTORY
The OpenSSL CMP support was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/OSSL_HTTP_parse_url.pod b/crypto/openssl/doc/man3/OSSL_HTTP_parse_url.pod
index 768f0acdb14c..4379c122d66a 100644
--- a/crypto/openssl/doc/man3/OSSL_HTTP_parse_url.pod
+++ b/crypto/openssl/doc/man3/OSSL_HTTP_parse_url.pod
@@ -1,107 +1,112 @@
=pod
=head1 NAME
OSSL_HTTP_adapt_proxy,
OSSL_parse_url,
OSSL_HTTP_parse_url,
OCSP_parse_url
- http utility functions
=head1 SYNOPSIS
#include <openssl/http.h>
const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy,
const char *server, int use_ssl);
int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
char **pport, int *pport_num,
char **ppath, char **pquery, char **pfrag);
int OSSL_HTTP_parse_url(const char *url,
int *pssl, char **puser, char **phost,
char **pport, int *pport_num,
char **ppath, char **pquery, char **pfrag);
The following functions have been deprecated since OpenSSL 3.0, and can be
hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
see L<openssl_user_macros(7)>:
int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
int *pssl);
=head1 DESCRIPTION
OSSL_HTTP_adapt_proxy() takes an optional proxy hostname I<proxy>
and returns it transformed according to the optional I<no_proxy> parameter,
I<server>, I<use_ssl>, and the applicable environment variable, as follows.
If I<proxy> is NULL, take any default value from the C<http_proxy>
environment variable, or from C<https_proxy> if I<use_ssl> is nonzero.
If this still does not yield a proxy hostname,
take any further default value from the C<HTTP_PROXY>
environment variable, or from C<HTTPS_PROXY> if I<use_ssl> is nonzero.
If I<no_proxy> is NULL, take any default exclusion value from the C<no_proxy>
environment variable, or else from C<NO_PROXY>.
-Return the determined proxy hostname unless the exclusion contains I<server>.
+Return the determined proxy host unless the exclusion value,
+which is a list of proxy hosts separated by C<,> and/or whitespace,
+contains I<server>.
Otherwise return NULL.
+When I<server> is a string delimited by C<[> and C<]>, which are used for IPv6
+addresses, the enclosing C<[> and C<]> are stripped prior to comparison.
OSSL_parse_url() parses its input string I<url> as a URL of the form
C<[scheme://][userinfo@]host[:port][/path][?query][#fragment]> and splits it up
into scheme, userinfo, host, port, path, query, and fragment components.
The host (or server) component may be a DNS name or an IP address
-where IPv6 addresses should be enclosed in square brackets C<[> and C<]>.
+where IPv6 addresses must be enclosed in square brackets C<[> and C<]>.
The port component is optional and defaults to C<0>.
If given, it must be in decimal form. If the I<pport_num> argument is not NULL
the integer value of the port number is assigned to I<*pport_num> on success.
The path component is also optional and defaults to C</>.
Each non-NULL result pointer argument I<pscheme>, I<puser>, I<phost>, I<pport>,
I<ppath>, I<pquery>, and I<pfrag>, is assigned the respective url component.
+Any IPv6 address in I<*phost> is enclosed in C<[> and C<]>.
On success, they are guaranteed to contain non-NULL string pointers, else NULL.
It is the responsibility of the caller to free them using L<OPENSSL_free(3)>.
If I<pquery> is NULL, any given query component is handled as part of the path.
A string returned via I<*ppath> is guaranteed to begin with a C</> character.
For absent scheme, userinfo, port, query, and fragment components
an empty string is provided.
OSSL_HTTP_parse_url() is a special form of OSSL_parse_url()
where the scheme, if given, must be C<http> or C<https>.
If I<pssl> is not NULL, I<*pssl> is assigned 1 in case parsing was successful
and the scheme is C<https>, else 0.
The port component is optional and defaults to C<443> if the scheme is C<https>,
else C<80>.
Note that relative paths must be given with a leading C</>,
-otherwise the first path element is interpreted as the hostname.
+otherwise the first path element is interpreted as the host.
Calling the deprecated function OCSP_parse_url(url, host, port, path, ssl)
is equivalent to
OSSL_HTTP_parse_url(url, ssl, NULL, host, port, NULL, path, NULL, NULL).
=head1 RETURN VALUES
OSSL_HTTP_adapt_proxy() returns NULL if no proxy is to be used,
otherwise a constant proxy hostname string,
which is either the proxy name handed in or an environment variable value.
OSSL_parse_url(), OSSL_HTTP_parse_url(), and OCSP_parse_url()
return 1 on success, 0 on error.
=head1 SEE ALSO
L<OSSL_HTTP_transfer(3)>
=head1 HISTORY
OSSL_HTTP_adapt_proxy(),
OSSL_parse_url() and OSSL_HTTP_parse_url() were added in OpenSSL 3.0.
OCSP_parse_url() was deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/OSSL_HTTP_transfer.pod b/crypto/openssl/doc/man3/OSSL_HTTP_transfer.pod
index 716e365ef50d..6da1d91b9f37 100644
--- a/crypto/openssl/doc/man3/OSSL_HTTP_transfer.pod
+++ b/crypto/openssl/doc/man3/OSSL_HTTP_transfer.pod
@@ -1,287 +1,289 @@
=pod
=head1 NAME
OSSL_HTTP_open,
OSSL_HTTP_bio_cb_t,
OSSL_HTTP_proxy_connect,
OSSL_HTTP_set1_request,
OSSL_HTTP_exchange,
OSSL_HTTP_get,
OSSL_HTTP_transfer,
OSSL_HTTP_close
- HTTP client high-level functions
=head1 SYNOPSIS
#include <openssl/http.h>
typedef BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg,
int connect, int detail);
OSSL_HTTP_REQ_CTX *OSSL_HTTP_open(const char *server, const char *port,
const char *proxy, const char *no_proxy,
int use_ssl, BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, int overall_timeout);
int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
const char *proxyuser, const char *proxypass,
int timeout, BIO *bio_err, const char *prog);
int OSSL_HTTP_set1_request(OSSL_HTTP_REQ_CTX *rctx, const char *path,
const STACK_OF(CONF_VALUE) *headers,
const char *content_type, BIO *req,
const char *expected_content_type, int expect_asn1,
size_t max_resp_len, int timeout, int keep_alive);
BIO *OSSL_HTTP_exchange(OSSL_HTTP_REQ_CTX *rctx, char **redirection_url);
BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, const STACK_OF(CONF_VALUE) *headers,
const char *expected_content_type, int expect_asn1,
size_t max_resp_len, int timeout);
BIO *OSSL_HTTP_transfer(OSSL_HTTP_REQ_CTX **prctx,
const char *server, const char *port,
const char *path, int use_ssl,
const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, const STACK_OF(CONF_VALUE) *headers,
const char *content_type, BIO *req,
const char *expected_content_type, int expect_asn1,
size_t max_resp_len, int timeout, int keep_alive);
int OSSL_HTTP_close(OSSL_HTTP_REQ_CTX *rctx, int ok);
=head1 DESCRIPTION
OSSL_HTTP_open() initiates an HTTP session using the I<bio> argument if not
NULL, else by connecting to a given I<server> optionally via a I<proxy>.
Typically the OpenSSL build supports sockets and the I<bio> parameter is NULL.
In this case I<rbio> must be NULL as well and the I<server> must be non-NULL.
The function creates a network BIO internally using L<BIO_new_connect(3)>
for connecting to the given server and the optionally given I<port>,
defaulting to 80 for HTTP or 443 for HTTPS.
Then this internal BIO is used for setting up a connection
and for exchanging one or more request and response.
If I<bio> is given and I<rbio> is NULL then this I<bio> is used instead.
If both I<bio> and I<rbio> are given (which may be memory BIOs for instance)
then no explicit connection is set up, but
I<bio> is used for writing requests and I<rbio> for reading responses.
As soon as the client has flushed I<bio> the server must be ready to provide
a response or indicate a waiting condition via I<rbio>.
If I<bio> is given, it is an error to provide I<proxy> or I<no_proxy> arguments,
while I<server> and I<port> arguments may be given to support diagnostic output.
If I<bio> is NULL the optional I<proxy> parameter can be used to set an
HTTP(S) proxy to use (unless overridden by "no_proxy" settings).
If TLS is not used this defaults to the environment variable C<http_proxy>
if set, else C<HTTP_PROXY>.
If I<use_ssl> != 0 it defaults to C<https_proxy> if set, else C<HTTPS_PROXY>.
An empty proxy string C<""> forbids using a proxy.
-Else the format is
+Otherwise, the format is
C<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>,
where any userinfo, path, query, and fragment given is ignored.
+If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>.
The default proxy port number is 80, or 443 in case "https:" is given.
The HTTP client functions connect via the given proxy unless the I<server>
-is found in the optional list I<no_proxy> of proxy hostnames (if not NULL;
+is found in the optional list I<no_proxy> of proxy hostnames or IP addresses
+separated by C<,> and/or whitespace (if not NULL;
default is the environment variable C<no_proxy> if set, else C<NO_PROXY>).
Proxying plain HTTP is supported directly,
while using a proxy for HTTPS connections requires a suitable callback function
such as OSSL_HTTP_proxy_connect(), described below.
If I<use_ssl> is nonzero a TLS connection is requested
and the I<bio_update_fn> parameter must be provided.
The parameter I<bio_update_fn>, which is optional if I<use_ssl> is 0,
may be used to modify the connection BIO used by the HTTP client,
but cannot be used when both I<bio> and I<rbio> are given.
I<bio_update_fn> is a BIO connect/disconnect callback function with prototype
BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail)
The callback function may modify the BIO provided in the I<bio> argument,
whereby it may make use of a custom defined argument I<arg>,
which may for instance point to an B<SSL_CTX> structure.
During connection establishment, just after calling BIO_do_connect_retry(), the
callback function is invoked with the I<connect> argument being 1 and
I<detail> being 1 if I<use_ssl> is nonzero (i.e., HTTPS is requested), else 0.
On disconnect I<connect> is 0 and I<detail> is 1 if no error occurred, else 0.
For instance, on connect the callback may push an SSL BIO to implement HTTPS;
after disconnect it may do some diagnostic output and pop and free the SSL BIO.
The callback function must return either the potentially modified BIO I<bio>.
or NULL to indicate failure, in which case it should not modify the BIO.
Here is a simple example that supports TLS connections (but not via a proxy):
BIO *http_tls_cb(BIO *bio, void *arg, int connect, int detail)
{
if (connect && detail) { /* connecting with TLS */
SSL_CTX *ctx = (SSL_CTX *)arg;
BIO *sbio = BIO_new_ssl(ctx, 1);
bio = sbio != NULL ? BIO_push(sbio, bio) : NULL;
} else if (!connect) { /* disconnecting */
BIO *hbio;
if (!detail) { /* an error has occurred */
/* optionally add diagnostics here */
}
BIO_ssl_shutdown(bio);
hbio = BIO_pop(bio);
BIO_free(bio); /* SSL BIO */
bio = hbio;
}
return bio;
}
After disconnect the modified BIO will be deallocated using BIO_free_all().
The I<buf_size> parameter specifies the response header maximum line length.
A value <= 0 means that the B<OSSL_HTTP_DEFAULT_MAX_LINE_LEN> (4KiB) is used.
I<buf_size> is also used as the number of content bytes that are read at a time.
If the I<overall_timeout> parameter is > 0 this indicates the maximum number of
seconds the overall HTTP transfer (i.e., connection setup if needed,
sending requests, and receiving responses) is allowed to take until completion.
A value <= 0 enables waiting indefinitely, i.e., no timeout.
OSSL_HTTP_proxy_connect() may be used by an above BIO connect callback function
to set up an SSL/TLS connection via an HTTPS proxy.
It promotes the given BIO I<bio> representing a connection
pre-established with a TLS proxy using the HTTP CONNECT method,
optionally using proxy client credentials I<proxyuser> and I<proxypass>,
to connect with TLS protection ultimately to I<server> and I<port>.
If the I<port> argument is NULL or the empty string it defaults to "443".
If the I<timeout> parameter is > 0 this indicates the maximum number of
seconds the connection setup is allowed to take.
A value <= 0 enables waiting indefinitely, i.e., no timeout.
Since this function is typically called by applications such as
L<openssl-s_client(1)> it uses the I<bio_err> and I<prog> parameters (unless
NULL) to print additional diagnostic information in a user-oriented way.
OSSL_HTTP_set1_request() sets up in I<rctx> the request header and content data
and expectations on the response using the following parameters.
If <rctx> indicates using a proxy for HTTP (but not HTTPS), the server host
(and optionally port) needs to be placed in the header; thus it must be present
in I<rctx>.
For backward compatibility, the server (and optional port) may also be given in
the I<path> argument beginning with C<http://> (thus giving an absoluteURI).
If I<path> is NULL it defaults to "/".
If I<req> is NULL the HTTP GET method will be used to send the request
else HTTP POST with the contents of I<req> and optional I<content_type>, where
the length of the data in I<req> does not need to be determined in advance: the
BIO will be read on-the-fly while sending the request, which supports streaming.
The optional list I<headers> may contain additional custom HTTP header lines.
If the parameter I<expected_content_type>
is not NULL then the client will check that the given content type string
is included in the HTTP header of the response and return an error if not.
If the I<expect_asn1> parameter is nonzero,
a structure in ASN.1 encoding will be expected as response content.
The I<max_resp_len> parameter specifies the maximum allowed
response content length, where the value 0 indicates no limit.
If the I<timeout> parameter is > 0 this indicates the maximum number of seconds
the subsequent HTTP transfer (sending the request and receiving a response)
is allowed to take.
A value of 0 enables waiting indefinitely, i.e., no timeout.
A value < 0 indicates that the I<overall_timeout> parameter value given
when opening the HTTP transfer will be used instead.
If I<keep_alive> is 0 the connection is not kept open
after receiving a response, which is the default behavior for HTTP 1.0.
If the value is 1 or 2 then a persistent connection is requested.
If the value is 2 then a persistent connection is required,
i.e., an error occurs in case the server does not grant it.
OSSL_HTTP_exchange() exchanges any form of HTTP request and response
as specified by I<rctx>, which must include both connection and request data,
typically set up using OSSL_HTTP_open() and OSSL_HTTP_set1_request().
It implements the core of the functions described below.
If the HTTP method is GET and I<redirection_url>
is not NULL the latter pointer is used to provide any new location that
the server may return with HTTP code 301 (MOVED_PERMANENTLY) or 302 (FOUND).
In this case the function returns NULL and the caller is
responsible for deallocating the URL with L<OPENSSL_free(3)>.
If the response header contains one or more "Content-Length" header lines and/or
an ASN.1-encoded response is expected, which should include a total length,
the length indications received are checked for consistency
and for not exceeding any given maximum response length.
If an ASN.1-encoded response is expected, the function returns on success
the contents buffered in a memory BIO, which does not support streaming.
Otherwise it returns directly the read BIO that holds the response contents,
which allows a response of indefinite length and may support streaming.
The caller is responsible for freeing the BIO pointer obtained.
OSSL_HTTP_get() uses HTTP GET to obtain data from I<bio> if non-NULL,
else from the server contained in the I<url>, and returns it as a BIO.
It supports redirection via HTTP status code 301 or 302. It is meant for
transfers with a single round trip, so does not support persistent connections.
If I<bio> is non-NULL, any host and port components in the I<url> are not used
for connecting but the hostname is used, as usual, for the C<Host> header.
Any userinfo and fragment components in the I<url> are ignored.
Any query component is handled as part of the path component.
If the scheme component of the I<url> is C<https> a TLS connection is requested
and the I<bio_update_fn>, as described for OSSL_HTTP_open(), must be provided.
Also the remaining parameters are interpreted as described for OSSL_HTTP_open()
and OSSL_HTTP_set1_request(), respectively.
The caller is responsible for freeing the BIO pointer obtained.
OSSL_HTTP_transfer() exchanges an HTTP request and response
over a connection managed via I<prctx> without supporting redirection.
It combines OSSL_HTTP_open(), OSSL_HTTP_set1_request(), OSSL_HTTP_exchange(),
and OSSL_HTTP_close().
If I<prctx> is not NULL it reuses any open connection represented by a non-NULL
I<*prctx>. It keeps the connection open if a persistent connection is requested
or required and this was granted by the server, else it closes the connection
and assigns NULL to I<*prctx>.
The remaining parameters are interpreted as described for OSSL_HTTP_open()
and OSSL_HTTP_set1_request(), respectively.
The caller is responsible for freeing the BIO pointer obtained.
OSSL_HTTP_close() closes the connection and releases I<rctx>.
The I<ok> parameter is passed to any BIO update function
given during setup as described above for OSSL_HTTP_open().
It must be 1 if no error occurred during the HTTP transfer and 0 otherwise.
=head1 NOTES
The names of the environment variables used by this implementation:
C<http_proxy>, C<HTTP_PROXY>, C<https_proxy>, C<HTTPS_PROXY>, C<no_proxy>, and
C<NO_PROXY>, have been chosen for maximal compatibility with
other HTTP client implementations such as wget, curl, and git.
=head1 RETURN VALUES
OSSL_HTTP_open() returns on success a B<OSSL_HTTP_REQ_CTX>, else NULL.
OSSL_HTTP_proxy_connect() and OSSL_HTTP_set1_request()
return 1 on success, 0 on error.
On success, OSSL_HTTP_exchange(), OSSL_HTTP_get(), and OSSL_HTTP_transfer()
return a memory BIO that buffers all the data received if an ASN.1-encoded
response is expected, otherwise a BIO that may support streaming.
The BIO must be freed by the caller.
On failure, they return NULL.
Failure conditions include connection/transfer timeout, parse errors, etc.
The caller is responsible for freeing the BIO pointer obtained.
OSSL_HTTP_close() returns 0 if anything went wrong while disconnecting, else 1.
=head1 SEE ALSO
L<OSSL_HTTP_parse_url(3)>, L<BIO_new_connect(3)>,
L<ASN1_item_i2d_mem_bio(3)>, L<ASN1_item_d2i_bio(3)>,
L<OSSL_HTTP_is_alive(3)>
=head1 HISTORY
All the functions described here were added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/OSSL_PARAM.pod b/crypto/openssl/doc/man3/OSSL_PARAM.pod
index 1e5bf06cf767..22fd0f0d7dd7 100644
--- a/crypto/openssl/doc/man3/OSSL_PARAM.pod
+++ b/crypto/openssl/doc/man3/OSSL_PARAM.pod
@@ -1,374 +1,374 @@
=pod
=head1 NAME
OSSL_PARAM - a structure to pass or request object parameters
=head1 SYNOPSIS
#include <openssl/core.h>
typedef struct ossl_param_st OSSL_PARAM;
struct ossl_param_st {
const char *key; /* the name of the parameter */
- unsigned char data_type; /* declare what kind of content is in data */
+ unsigned int data_type; /* declare what kind of content is in data */
void *data; /* value being passed in or out */
size_t data_size; /* data size */
size_t return_size; /* returned size */
};
=head1 DESCRIPTION
B<OSSL_PARAM> is a type that allows passing arbitrary data for some
object between two parties that have no or very little shared
knowledge about their respective internal structures for that object.
A typical usage example could be an application that wants to set some
parameters for an object, or wants to find out some parameters of an
object.
Arrays of this type can be used for the following purposes:
=over 4
=item * Setting parameters for some object
The caller sets up the B<OSSL_PARAM> array and calls some function
(the I<setter>) that has intimate knowledge about the object that can
take the data from the B<OSSL_PARAM> array and assign them in a
suitable form for the internal structure of the object.
=item * Request parameters of some object
The caller (the I<requester>) sets up the B<OSSL_PARAM> array and
calls some function (the I<responder>) that has intimate knowledge
about the object, which can take the internal data of the object and
copy (possibly convert) that to the memory prepared by the
I<requester> and pointed at with the B<OSSL_PARAM> I<data>.
=item * Request parameter descriptors
The caller gets an array of constant B<OSSL_PARAM>, which describe
available parameters and some of their properties; name, data type and
expected data size.
For a detailed description of each field for this use, see the field
descriptions below.
The caller may then use the information from this descriptor array to
build up its own B<OSSL_PARAM> array to pass down to a I<setter> or
I<responder>.
=back
Normally, the order of the an B<OSSL_PARAM> array is not relevant.
However, if the I<responder> can handle multiple elements with the
same key, those elements must be handled in the order they are in.
An B<OSSL_PARAM> array must have a terminating element, where I<key>
is NULL. The usual full terminating template is:
{ NULL, 0, NULL, 0, 0 }
This can also be specified using L<OSSL_PARAM_END(3)>.
=head2 Functional support
Libcrypto offers a limited set of helper functions to handle
B<OSSL_PARAM> items and arrays, please see L<OSSL_PARAM_get_int(3)>.
Developers are free to extend or replace those as they see fit.
=head2 B<OSSL_PARAM> fields
=over 4
=item I<key>
The identity of the parameter in the form of a string.
In an B<OSSL_PARAM> array, an item with this field set to NULL is
considered a terminating item.
=item I<data_type>
The I<data_type> is a value that describes the type and organization of
the data.
See L</Supported types> below for a description of the types.
=item I<data>
=item I<data_size>
I<data> is a pointer to the memory where the parameter data is (when
setting parameters) or shall (when requesting parameters) be stored,
and I<data_size> is its size in bytes.
The organization of the data depends on the parameter type and flag.
The I<data_size> needs special attention with the parameter type
B<OSSL_PARAM_UTF8_STRING> in relation to C strings. When setting
parameters, the size should be set to the length of the string, not
counting the terminating NUL byte. When requesting parameters, the
size should be set to the size of the buffer to be populated, which
should accommodate enough space for a terminating NUL byte.
When I<requesting parameters>, it's acceptable for I<data> to be NULL.
This can be used by the I<requester> to figure out dynamically exactly
how much buffer space is needed to store the parameter data.
In this case, I<data_size> is ignored.
When the B<OSSL_PARAM> is used as a parameter descriptor, I<data>
should be ignored.
If I<data_size> is zero, it means that an arbitrary data size is
accepted, otherwise it specifies the maximum size allowed.
=item I<return_size>
When an array of B<OSSL_PARAM> is used to request data, the
I<responder> must set this field to indicate size of the parameter
data, including padding as the case may be.
In case the I<data_size> is an unsuitable size for the data, the
I<responder> must still set this field to indicate the minimum data
size required.
(further notes on this in L</NOTES> below).
When the B<OSSL_PARAM> is used as a parameter descriptor,
I<return_size> should be ignored.
=back
B<NOTE:>
The key names and associated types are defined by the entity that
offers these parameters, i.e. names for parameters provided by the
OpenSSL libraries are defined by the libraries, and names for
parameters provided by providers are defined by those providers,
except for the pointer form of strings (see data type descriptions
below).
Entities that want to set or request parameters need to know what
those keys are and of what type, any functionality between those two
entities should remain oblivious and just pass the B<OSSL_PARAM> array
along.
=head2 Supported types
The I<data_type> field can be one of the following types:
=over 4
=item B<OSSL_PARAM_INTEGER>
=item B<OSSL_PARAM_UNSIGNED_INTEGER>
The parameter data is an integer (signed or unsigned) of arbitrary
length, organized in native form, i.e. most significant byte first on
Big-Endian systems, and least significant byte first on Little-Endian
systems.
=item B<OSSL_PARAM_REAL>
The parameter data is a floating point value in native form.
=item B<OSSL_PARAM_UTF8_STRING>
The parameter data is a printable string.
=item B<OSSL_PARAM_OCTET_STRING>
The parameter data is an arbitrary string of bytes.
=item B<OSSL_PARAM_UTF8_PTR>
The parameter data is a pointer to a printable string.
The difference between this and B<OSSL_PARAM_UTF8_STRING> is that I<data>
doesn't point directly at the data, but to a pointer that points to the data.
If there is any uncertainty about which to use, B<OSSL_PARAM_UTF8_STRING> is
almost certainly the correct choice.
This is used to indicate that constant data is or will be passed,
and there is therefore no need to copy the data that is passed, just
the pointer to it.
I<data_size> must be set to the size of the data, not the size of the
pointer to the data.
If this is used in a parameter request,
I<data_size> is not relevant. However, the I<responder> will set
I<return_size> to the size of the data.
Note that the use of this type is B<fragile> and can only be safely
used for data that remains constant and in a constant location for a
long enough duration (such as the life-time of the entity that
offers these parameters).
=item B<OSSL_PARAM_OCTET_PTR>
The parameter data is a pointer to an arbitrary string of bytes.
The difference between this and B<OSSL_PARAM_OCTET_STRING> is that
I<data> doesn't point directly at the data, but to a pointer that
points to the data.
If there is any uncertainty about which to use, B<OSSL_PARAM_OCTET_STRING> is
almost certainly the correct choice.
This is used to indicate that constant data is or will be passed, and
there is therefore no need to copy the data that is passed, just the
pointer to it.
I<data_size> must be set to the size of the data, not the size of the
pointer to the data.
If this is used in a parameter request,
I<data_size> is not relevant. However, the I<responder> will set
I<return_size> to the size of the data.
Note that the use of this type is B<fragile> and can only be safely
used for data that remains constant and in a constant location for a
long enough duration (such as the life-time of the entity that
offers these parameters).
=back
=head1 NOTES
Both when setting and requesting parameters, the functions that are
called will have to decide what is and what is not an error.
The recommended behaviour is:
=over 4
=item *
Keys that a I<setter> or I<responder> doesn't recognise should simply
be ignored.
That in itself isn't an error.
=item *
If the keys that a called I<setter> recognises form a consistent
enough set of data, that call should succeed.
=item *
Apart from the I<return_size>, a I<responder> must never change the fields
of an B<OSSL_PARAM>.
To return a value, it should change the contents of the memory that
I<data> points at.
=item *
If the data type for a key that it's associated with is incorrect,
the called function may return an error.
The called function may also try to convert the data to a suitable
form (for example, it's plausible to pass a large number as an octet
string, so even though a given key is defined as an
B<OSSL_PARAM_UNSIGNED_INTEGER>, is plausible to pass the value as an
B<OSSL_PARAM_OCTET_STRING>), but this is in no way mandatory.
=item *
If I<data> for a B<OSSL_PARAM_OCTET_STRING> or a
B<OSSL_PARAM_UTF8_STRING> is NULL, the I<responder> should
set I<return_size> to the size of the item to be returned
and return success. Later the responder will be called again
with I<data> pointing at the place for the value to be put.
=item *
If a I<responder> finds that some data sizes are too small for the
requested data, it must set I<return_size> for each such
B<OSSL_PARAM> item to the minimum required size, and eventually return
an error.
=item *
For the integer type parameters (B<OSSL_PARAM_UNSIGNED_INTEGER> and
B<OSSL_PARAM_INTEGER>), a I<responder> may choose to return an error
if the I<data_size> isn't a suitable size (even if I<data_size> is
bigger than needed). If the I<responder> finds the size suitable, it
must fill all I<data_size> bytes and ensure correct padding for the
native endianness, and set I<return_size> to the same value as
I<data_size>.
=back
=begin comment RETURN VALUES doesn't make sense for a manual that only
describes a type, but document checkers still want that section, and
to have more than just the section title.
=head1 RETURN VALUES
txt
=end comment
=head1 EXAMPLES
A couple of examples to just show how B<OSSL_PARAM> arrays could be
set up.
=head3 Example 1
This example is for setting parameters on some object:
#include <openssl/core.h>
const char *foo = "some string";
size_t foo_l = strlen(foo);
const char bar[] = "some other string";
OSSL_PARAM set[] = {
{ "foo", OSSL_PARAM_UTF8_PTR, &foo, foo_l, 0 },
{ "bar", OSSL_PARAM_UTF8_STRING, (void *)&bar, sizeof(bar) - 1, 0 },
{ NULL, 0, NULL, 0, 0 }
};
=head3 Example 2
This example is for requesting parameters on some object:
const char *foo = NULL;
size_t foo_l;
char bar[1024];
size_t bar_l;
OSSL_PARAM request[] = {
{ "foo", OSSL_PARAM_UTF8_PTR, &foo, 0 /*irrelevant*/, 0 },
{ "bar", OSSL_PARAM_UTF8_STRING, &bar, sizeof(bar), 0 },
{ NULL, 0, NULL, 0, 0 }
};
A I<responder> that receives this array (as I<params> in this example)
could fill in the parameters like this:
/* OSSL_PARAM *params */
int i;
for (i = 0; params[i].key != NULL; i++) {
if (strcmp(params[i].key, "foo") == 0) {
*(char **)params[i].data = "foo value";
params[i].return_size = 9; /* length of "foo value" string */
} else if (strcmp(params[i].key, "bar") == 0) {
memcpy(params[i].data, "bar value", 10);
params[i].return_size = 9; /* length of "bar value" string */
}
/* Ignore stuff we don't know */
}
=head1 SEE ALSO
L<openssl-core.h(7)>, L<OSSL_PARAM_get_int(3)>, L<OSSL_PARAM_dup(3)>
=head1 HISTORY
B<OSSL_PARAM> was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/OSSL_trace_enabled.pod b/crypto/openssl/doc/man3/OSSL_trace_enabled.pod
index f9c9dffd8c6a..bad5b1515353 100644
--- a/crypto/openssl/doc/man3/OSSL_trace_enabled.pod
+++ b/crypto/openssl/doc/man3/OSSL_trace_enabled.pod
@@ -1,292 +1,296 @@
=pod
=head1 NAME
OSSL_trace_enabled, OSSL_trace_begin, OSSL_trace_end,
OSSL_TRACE_BEGIN, OSSL_TRACE_END, OSSL_TRACE_CANCEL,
OSSL_TRACE, OSSL_TRACE1, OSSL_TRACE2, OSSL_TRACE3, OSSL_TRACE4,
OSSL_TRACE5, OSSL_TRACE6, OSSL_TRACE7, OSSL_TRACE8, OSSL_TRACE9,
OSSL_TRACEV,
OSSL_TRACE_ENABLED
- OpenSSL Tracing API
=head1 SYNOPSIS
=for openssl generic
#include <openssl/trace.h>
int OSSL_trace_enabled(int category);
BIO *OSSL_trace_begin(int category);
void OSSL_trace_end(int category, BIO *channel);
/* trace group macros */
OSSL_TRACE_BEGIN(category) {
...
if (some_error) {
/* Leave trace group prematurely in case of an error */
OSSL_TRACE_CANCEL(category);
goto err;
}
...
} OSSL_TRACE_END(category);
/* one-shot trace macros */
OSSL_TRACE1(category, format, arg1)
OSSL_TRACE2(category, format, arg1, arg2)
...
OSSL_TRACE9(category, format, arg1, ..., arg9)
/* check whether a trace category is enabled */
if (OSSL_TRACE_ENABLED(category)) {
...
}
=head1 DESCRIPTION
The functions described here are mainly interesting for those who provide
OpenSSL functionality, either in OpenSSL itself or in engine modules
or similar.
If tracing is enabled (see L</NOTES> below), these functions are used to
generate free text tracing output.
The tracing output is divided into types which are enabled
individually by the application.
The tracing types are described in detail in
L<OSSL_trace_set_callback(3)/Trace types>.
The fallback type B<OSSL_TRACE_CATEGORY_ALL> should I<not> be used
with the functions described here.
Tracing for a specific category is enabled if a so called
I<trace channel> is attached to it. A trace channel is simply a
BIO object to which the application can write its trace output.
The application has two different ways of registering a trace channel,
either by directly providing a BIO object using OSSL_trace_set_channel(),
or by providing a callback routine using OSSL_trace_set_callback().
The latter is wrapped internally by a dedicated BIO object, so for the
tracing code both channel types are effectively indistinguishable.
We call them a I<simple trace channel> and a I<callback trace channel>,
respectively.
To produce trace output, it is necessary to obtain a pointer to the
trace channel (i.e., the BIO object) using OSSL_trace_begin(), write
to it using arbitrary BIO output routines, and finally releases the
channel using OSSL_trace_end(). The OSSL_trace_begin()/OSSL_trace_end()
calls surrounding the trace output create a group, which acts as a
critical section (guarded by a mutex) to ensure that the trace output
of different threads does not get mixed up.
The tracing code normally does not call OSSL_trace_{begin,end}() directly,
but rather uses a set of convenience macros, see the L</Macros> section below.
=head2 Functions
OSSL_trace_enabled() can be used to check if tracing for the given
I<category> is enabled.
-OSSL_trace_begin() is used to starts a tracing section, and get the
-channel for the given I<category> in form of a BIO.
+OSSL_trace_begin() is used to start a tracing section,
+and get the channel for the given I<category> in form of a BIO.
This BIO can only be used for output.
+The pointer returned is NULL if the category is invalid or not enabled.
OSSL_trace_end() is used to end a tracing section.
Using OSSL_trace_begin() and OSSL_trace_end() to wrap tracing sections
is I<mandatory>.
The result of trying to produce tracing output outside of such
sections is undefined.
=head2 Macros
There are a number of convenience macros defined, to make tracing
easy and consistent.
OSSL_TRACE_BEGIN() and OSSL_TRACE_END() reserve the B<BIO> C<trc_out> and are
used as follows to wrap a trace section:
OSSL_TRACE_BEGIN(TLS) {
BIO_fprintf(trc_out, ... );
} OSSL_TRACE_END(TLS);
This will normally expand to:
do {
BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS);
if (trc_out != NULL) {
...
BIO_fprintf(trc_out, ...);
}
OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
} while (0);
OSSL_TRACE_CANCEL() must be used before returning from or jumping out of a
trace section:
OSSL_TRACE_BEGIN(TLS) {
if (some_error) {
OSSL_TRACE_CANCEL(TLS);
goto err;
}
BIO_fprintf(trc_out, ... );
} OSSL_TRACE_END(TLS);
This will normally expand to:
do {
BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS);
if (trc_out != NULL) {
if (some_error) {
OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
goto err;
}
BIO_fprintf(trc_out, ... );
}
OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
} while (0);
OSSL_TRACE() and OSSL_TRACE1(), OSSL_TRACE2(), ... OSSL_TRACE9() are
so-called one-shot macros:
The macro call C<OSSL_TRACE(category, text)>, produces literal text trace output.
The macro call C<OSSL_TRACEn(category, format, arg1, ..., argn)> produces
printf-style trace output with n format field arguments (n=1,...,9).
It expands to:
OSSL_TRACE_BEGIN(category) {
BIO_printf(trc_out, format, arg1, ..., argN)
} OSSL_TRACE_END(category)
Internally, all one-shot macros are implemented using a generic OSSL_TRACEV()
macro, since C90 does not support variadic macros. This helper macro has a rather
weird synopsis and should not be used directly.
The OSSL_TRACE_ENABLED() macro can be used to conditionally execute some code
only if a specific trace category is enabled.
In some situations this is simpler than entering a trace section using
OSSL_TRACE_BEGIN() and OSSL_TRACE_END().
For example, the code
if (OSSL_TRACE_ENABLED(TLS)) {
...
}
expands to
if (OSSL_trace_enabled(OSSL_TRACE_CATEGORY_TLS) {
...
}
=head1 NOTES
+It is not needed to guard trace output function calls like
+I<OSSL_TRACE(category, ...)> by I<OSSL_TRACE_ENABLED(category)>.
+
If producing the trace output requires carrying out auxiliary calculations,
this auxiliary code should be placed inside a conditional block which is
executed only if the trace category is enabled.
The most natural way to do this is to place the code inside the trace section
itself because it already introduces such a conditional block.
OSSL_TRACE_BEGIN(TLS) {
int var = do_some_auxiliary_calculation();
BIO_printf(trc_out, "var = %d\n", var);
} OSSL_TRACE_END(TLS);
In some cases it is more advantageous to use a simple conditional group instead
of a trace section. This is the case if calculations and tracing happen in
different locations of the code, or if the calculations are so time consuming
that placing them inside a (critical) trace section would create too much
contention.
if (OSSL_TRACE_ENABLED(TLS)) {
int var = do_some_auxiliary_calculation();
OSSL_TRACE1("var = %d\n", var);
}
Note however that premature optimization of tracing code is in general futile
and it's better to keep the tracing code as simple as possible.
Because most often the limiting factor for the application's speed is the time
it takes to print the trace output, not to calculate it.
=head2 Configure Tracing
By default, the OpenSSL library is built with tracing disabled. To
use the tracing functionality documented here, it is therefore
necessary to configure and build OpenSSL with the 'enable-trace' option.
When the library is built with tracing disabled:
=over 4
=item *
The macro B<OPENSSL_NO_TRACE> is defined in F<< <openssl/opensslconf.h> >>.
=item *
all functions are still present, but OSSL_trace_enabled() will always
report the categories as disabled, and all other functions will do
nothing.
=item *
the convenience macros are defined to produce dead code.
For example, take this example from L</Macros> section above:
OSSL_TRACE_BEGIN(TLS) {
if (condition) {
OSSL_TRACE_CANCEL(TLS);
goto err;
}
BIO_fprintf(trc_out, ... );
} OSSL_TRACE_END(TLS);
When the tracing API isn't operational, that will expand to:
do {
BIO *trc_out = NULL;
if (0) {
if (condition) {
((void)0);
goto err;
}
BIO_fprintf(trc_out, ... );
}
} while (0);
=back
=head1 RETURN VALUES
OSSL_trace_enabled() returns 1 if tracing for the given I<type> is
operational and enabled, otherwise 0.
OSSL_trace_begin() returns a B<BIO> pointer if the given I<type> is enabled,
otherwise NULL.
=head1 HISTORY
The OpenSSL Tracing API was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/SSL_CTX_new.pod b/crypto/openssl/doc/man3/SSL_CTX_new.pod
index f467f93659b5..627d9e7f0dc3 100644
--- a/crypto/openssl/doc/man3/SSL_CTX_new.pod
+++ b/crypto/openssl/doc/man3/SSL_CTX_new.pod
@@ -1,259 +1,261 @@
=pod
=head1 NAME
TLSv1_2_method, TLSv1_2_server_method, TLSv1_2_client_method,
SSL_CTX_new, SSL_CTX_new_ex, SSL_CTX_up_ref, SSLv3_method,
SSLv3_server_method, SSLv3_client_method, TLSv1_method, TLSv1_server_method,
TLSv1_client_method, TLSv1_1_method, TLSv1_1_server_method,
TLSv1_1_client_method, TLS_method, TLS_server_method, TLS_client_method,
SSLv23_method, SSLv23_server_method, SSLv23_client_method, DTLS_method,
DTLS_server_method, DTLS_client_method, DTLSv1_method, DTLSv1_server_method,
DTLSv1_client_method, DTLSv1_2_method, DTLSv1_2_server_method,
DTLSv1_2_client_method
- create a new SSL_CTX object as framework for TLS/SSL or DTLS enabled
functions
=head1 SYNOPSIS
#include <openssl/ssl.h>
SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
const SSL_METHOD *method);
SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
int SSL_CTX_up_ref(SSL_CTX *ctx);
const SSL_METHOD *TLS_method(void);
const SSL_METHOD *TLS_server_method(void);
const SSL_METHOD *TLS_client_method(void);
const SSL_METHOD *SSLv23_method(void);
const SSL_METHOD *SSLv23_server_method(void);
const SSL_METHOD *SSLv23_client_method(void);
#ifndef OPENSSL_NO_SSL3_METHOD
const SSL_METHOD *SSLv3_method(void);
const SSL_METHOD *SSLv3_server_method(void);
const SSL_METHOD *SSLv3_client_method(void);
#endif
#ifndef OPENSSL_NO_TLS1_METHOD
const SSL_METHOD *TLSv1_method(void);
const SSL_METHOD *TLSv1_server_method(void);
const SSL_METHOD *TLSv1_client_method(void);
#endif
#ifndef OPENSSL_NO_TLS1_1_METHOD
const SSL_METHOD *TLSv1_1_method(void);
const SSL_METHOD *TLSv1_1_server_method(void);
const SSL_METHOD *TLSv1_1_client_method(void);
#endif
#ifndef OPENSSL_NO_TLS1_2_METHOD
const SSL_METHOD *TLSv1_2_method(void);
const SSL_METHOD *TLSv1_2_server_method(void);
const SSL_METHOD *TLSv1_2_client_method(void);
#endif
const SSL_METHOD *DTLS_method(void);
const SSL_METHOD *DTLS_server_method(void);
const SSL_METHOD *DTLS_client_method(void);
#ifndef OPENSSL_NO_DTLS1_METHOD
const SSL_METHOD *DTLSv1_method(void);
const SSL_METHOD *DTLSv1_server_method(void);
const SSL_METHOD *DTLSv1_client_method(void);
#endif
#ifndef OPENSSL_NO_DTLS1_2_METHOD
const SSL_METHOD *DTLSv1_2_method(void);
const SSL_METHOD *DTLSv1_2_server_method(void);
const SSL_METHOD *DTLSv1_2_client_method(void);
#endif
=head1 DESCRIPTION
SSL_CTX_new_ex() creates a new B<SSL_CTX> object, which holds various
configuration and data relevant to SSL/TLS or DTLS session establishment.
These are later inherited by the B<SSL> object representing an active session.
The I<method> parameter specifies whether the context will be used for the
client or server side or both - for details see the L</NOTES> below.
The library context I<libctx> (see L<OSSL_LIB_CTX(3)>) is used to provide the
cryptographic algorithms needed for the session. Any cryptographic algorithms
that are used by any B<SSL> objects created from this B<SSL_CTX> will be fetched
from the I<libctx> using the property query string I<propq> (see
L<crypto(7)/ALGORITHM FETCHING>. Either or both the I<libctx> or I<propq>
parameters may be NULL.
SSL_CTX_new() does the same as SSL_CTX_new_ex() except that the default
library context is used and no property query string is specified.
An B<SSL_CTX> object is reference counted. Creating an B<SSL_CTX> object for the
first time increments the reference count. Freeing the B<SSL_CTX> (using
SSL_CTX_free) decrements it. When the reference count drops to zero, any memory
or resources allocated to the B<SSL_CTX> object are freed. SSL_CTX_up_ref()
increments the reference count for an existing B<SSL_CTX> structure.
An B<SSL_CTX> object should not be changed after it is used to create any B<SSL>
objects or from multiple threads concurrently, since the implementation does not
provide serialization of access for these cases.
=head1 NOTES
On session establishment, by default, no peer credentials verification is done.
This must be explicitly requested, typically using L<SSL_CTX_set_verify(3)>.
For verifying peer certificates many options can be set using various functions
such as L<SSL_CTX_load_verify_locations(3)> and L<SSL_CTX_set1_param(3)>.
-The L<X509_VERIFY_PARAM_set_purpose(3)> function can be used, also in conjunction
-with L<SSL_CTX_get0_param(3)>, to set the intended purpose of the session.
-The default is B<X509_PURPOSE_SSL_SERVER> on the client side
+
+The SSL/(D)TLS implementation uses the L<X509_STORE_CTX_set_default(3)>
+function to prepare checks for B<X509_PURPOSE_SSL_SERVER> on the client side
and B<X509_PURPOSE_SSL_CLIENT> on the server side.
+The L<X509_VERIFY_PARAM_set_purpose(3)> function can be used, also in conjunction
+with L<SSL_CTX_get0_param(3)>, to override the default purpose of the session.
The SSL_CTX object uses I<method> as the connection method.
Three method variants are available: a generic method (for either client or
server use), a server-only method, and a client-only method.
The I<method> parameter of SSL_CTX_new_ex() and SSL_CTX_new()
can be one of the following:
=over 4
=item TLS_method(), TLS_server_method(), TLS_client_method()
These are the general-purpose I<version-flexible> SSL/TLS methods.
The actual protocol version used will be negotiated to the highest version
mutually supported by the client and the server.
The supported protocols are SSLv3, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3.
Applications should use these methods, and avoid the version-specific
methods described below, which are deprecated.
=item SSLv23_method(), SSLv23_server_method(), SSLv23_client_method()
These functions do not exist anymore, they have been renamed to
TLS_method(), TLS_server_method() and TLS_client_method() respectively.
Currently, the old function calls are renamed to the corresponding new
ones by preprocessor macros, to ensure that existing code which uses the
old function names still compiles. However, using the old function names
is deprecated and new code should call the new functions instead.
=item TLSv1_2_method(), TLSv1_2_server_method(), TLSv1_2_client_method()
A TLS/SSL connection established with these methods will only understand the
TLSv1.2 protocol. These methods are deprecated.
=item TLSv1_1_method(), TLSv1_1_server_method(), TLSv1_1_client_method()
A TLS/SSL connection established with these methods will only understand the
TLSv1.1 protocol. These methods are deprecated.
=item TLSv1_method(), TLSv1_server_method(), TLSv1_client_method()
A TLS/SSL connection established with these methods will only understand the
TLSv1 protocol. These methods are deprecated.
=item SSLv3_method(), SSLv3_server_method(), SSLv3_client_method()
A TLS/SSL connection established with these methods will only understand the
SSLv3 protocol.
The SSLv3 protocol is deprecated and should not be used.
=item DTLS_method(), DTLS_server_method(), DTLS_client_method()
These are the version-flexible DTLS methods.
Currently supported protocols are DTLS 1.0 and DTLS 1.2.
=item DTLSv1_2_method(), DTLSv1_2_server_method(), DTLSv1_2_client_method()
These are the version-specific methods for DTLSv1.2.
These methods are deprecated.
=item DTLSv1_method(), DTLSv1_server_method(), DTLSv1_client_method()
These are the version-specific methods for DTLSv1.
These methods are deprecated.
=back
SSL_CTX_new() initializes the list of ciphers, the session cache setting, the
callbacks, the keys and certificates and the options to their default values.
TLS_method(), TLS_server_method(), TLS_client_method(), DTLS_method(),
DTLS_server_method() and DTLS_client_method() are the I<version-flexible>
methods.
All other methods only support one specific protocol version.
Use the I<version-flexible> methods instead of the version specific methods.
If you want to limit the supported protocols for the version flexible
methods you can use L<SSL_CTX_set_min_proto_version(3)>,
L<SSL_set_min_proto_version(3)>, L<SSL_CTX_set_max_proto_version(3)> and
L<SSL_set_max_proto_version(3)> functions.
Using these functions it is possible to choose e.g. TLS_server_method()
and be able to negotiate with all possible clients, but to only
allow newer protocols like TLS 1.0, TLS 1.1, TLS 1.2 or TLS 1.3.
The list of protocols available can also be limited using the
B<SSL_OP_NO_SSLv3>, B<SSL_OP_NO_TLSv1>, B<SSL_OP_NO_TLSv1_1>,
B<SSL_OP_NO_TLSv1_3>, B<SSL_OP_NO_TLSv1_2> and B<SSL_OP_NO_TLSv1_3>
options of the
L<SSL_CTX_set_options(3)> or L<SSL_set_options(3)> functions, but this approach
is not recommended. Clients should avoid creating "holes" in the set of
protocols they support. When disabling a protocol, make sure that you also
disable either all previous or all subsequent protocol versions.
In clients, when a protocol version is disabled without disabling I<all>
previous protocol versions, the effect is to also disable all subsequent
protocol versions.
The SSLv3 protocol is deprecated and should generally not be used.
Applications should typically use L<SSL_CTX_set_min_proto_version(3)> to set
the minimum protocol to at least B<TLS1_VERSION>.
=head1 RETURN VALUES
The following return values can occur:
=over 4
=item NULL
The creation of a new SSL_CTX object failed. Check the error stack to find out
the reason.
=item Pointer to an SSL_CTX object
The return value points to an allocated SSL_CTX object.
SSL_CTX_up_ref() returns 1 for success and 0 for failure.
=back
=head1 SEE ALSO
-L<SSL_CTX_set_options(3)>, L<SSL_CTX_free(3)>,
+L<SSL_CTX_set_options(3)>, L<SSL_CTX_free(3)>, L<X509_STORE_CTX_set_default(3)>,
SSL_CTX_set_verify(3), L<SSL_CTX_set1_param(3)>, L<SSL_CTX_get0_param(3)>,
L<SSL_connect(3)>, L<SSL_accept(3)>,
L<SSL_CTX_set_min_proto_version(3)>, L<ssl(7)>, L<SSL_set_connect_state(3)>
=head1 HISTORY
Support for SSLv2 and the corresponding SSLv2_method(),
SSLv2_server_method() and SSLv2_client_method() functions where
removed in OpenSSL 1.1.0.
SSLv23_method(), SSLv23_server_method() and SSLv23_client_method()
were deprecated and the preferred TLS_method(), TLS_server_method()
and TLS_client_method() functions were added in OpenSSL 1.1.0.
All version-specific methods were deprecated in OpenSSL 1.1.0.
SSL_CTX_new_ex() was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/SSL_get_shared_sigalgs.pod b/crypto/openssl/doc/man3/SSL_get_shared_sigalgs.pod
index c18114cdf472..cb9ce025002f 100644
--- a/crypto/openssl/doc/man3/SSL_get_shared_sigalgs.pod
+++ b/crypto/openssl/doc/man3/SSL_get_shared_sigalgs.pod
@@ -1,88 +1,88 @@
=pod
=head1 NAME
SSL_get_shared_sigalgs, SSL_get_sigalgs - get supported signature algorithms
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_get_shared_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash);
int SSL_get_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash);
=head1 DESCRIPTION
SSL_get_shared_sigalgs() returns information about the shared signature
algorithms supported by peer B<s>. The parameter B<idx> indicates the index
of the shared signature algorithm to return starting from zero. The signature
algorithm NID is written to B<*psign>, the hash NID to B<*phash> and the
sign and hash NID to B<*psignhash>. The raw signature and hash values
are written to B<*rsig> and B<*rhash>.
SSL_get_sigalgs() is similar to SSL_get_shared_sigalgs() except it returns
information about all signature algorithms supported by B<s> in the order
they were sent by the peer.
=head1 RETURN VALUES
SSL_get_shared_sigalgs() and SSL_get_sigalgs() return the number of
signature algorithms or B<0> if the B<idx> parameter is out of range.
=head1 NOTES
These functions are typically called for debugging purposes (to report
the peer's preferences) or where an application wants finer control over
certificate selection. Most applications will rely on internal handling
and will not need to call them.
If an application is only interested in the highest preference shared
signature algorithm it can just set B<idx> to zero.
Any or all of the parameters B<psign>, B<phash>, B<psignhash>, B<rsig> or
B<rhash> can be set to B<NULL> if the value is not required. By setting
them all to B<NULL> and setting B<idx> to zero the total number of
signature algorithms can be determined: which can be zero.
These functions must be called after the peer has sent a list of supported
signature algorithms: after a client hello (for servers) or a certificate
request (for clients). They can (for example) be called in the certificate
callback.
Only TLS 1.2, TLS 1.3 and DTLS 1.2 currently support signature algorithms.
If these
functions are called on an earlier version of TLS or DTLS zero is returned.
The shared signature algorithms returned by SSL_get_shared_sigalgs() are
ordered according to configuration and peer preferences.
The raw values correspond to the on the wire form as defined by RFC5246 et al.
The NIDs are OpenSSL equivalents. For example if the peer sent sha256(4) and
rsa(1) then B<*rhash> would be 4, B<*rsign> 1, B<*phash> NID_sha256, B<*psig>
-NID_rsaEncryption and B<*psighash> NID_sha256WithRSAEncryption.
+NID_rsaEncryption and B<*psignhash> NID_sha256WithRSAEncryption.
If a signature algorithm is not recognised the corresponding NIDs
will be set to B<NID_undef>. This may be because the value is not supported,
is not an appropriate combination (for example MD5 and DSA) or the
signature algorithm does not use a hash (for example Ed25519).
=head1 SEE ALSO
L<SSL_CTX_set_cert_cb(3)>,
L<ssl(7)>
=head1 COPYRIGHT
Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/SSL_set_bio.pod b/crypto/openssl/doc/man3/SSL_set_bio.pod
index c666dc466ecd..aaffeedf779b 100644
--- a/crypto/openssl/doc/man3/SSL_set_bio.pod
+++ b/crypto/openssl/doc/man3/SSL_set_bio.pod
@@ -1,112 +1,121 @@
=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
nonblocking then the B<ssl> object will also have nonblocking 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).
+If using a custom BIO, B<rbio> must implement either
+L<BIO_meth_set_read_ex(3)> or L<BIO_meth_set_read(3)>.
+
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.
+If using a custom BIO, B<wbio> must implement
+L<BIO_meth_set_write_ex(3)> or L<BIO_meth_set_write(3)>. It additionally must
+implement L<BIO_flush(3)> using B<BIO_CTRL_FLUSH> and L<BIO_meth_set_ctrl(3)>.
+If flushing is unnecessary with B<wbio>, L<BIO_flush(3)> should return one and
+do nothing.
+
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_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-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/X509V3_set_ctx.pod b/crypto/openssl/doc/man3/X509V3_set_ctx.pod
index 8287802e41b2..7819c344f751 100644
--- a/crypto/openssl/doc/man3/X509V3_set_ctx.pod
+++ b/crypto/openssl/doc/man3/X509V3_set_ctx.pod
@@ -1,67 +1,66 @@
=pod
=head1 NAME
X509V3_set_ctx,
X509V3_set_issuer_pkey - X.509 v3 extension generation utilities
=head1 SYNOPSIS
#include <openssl/x509v3.h>
void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
X509_REQ *req, X509_CRL *crl, int flags);
int X509V3_set_issuer_pkey(X509V3_CTX *ctx, EVP_PKEY *pkey);
=head1 DESCRIPTION
X509V3_set_ctx() fills in the basic fields of I<ctx> of type B<X509V3_CTX>,
providing details potentially needed by functions producing X509 v3 extensions,
e.g., to look up values for filling in authority key identifiers.
Any of I<subject>, I<req>, or I<crl> may be provided, pointing to a certificate,
certification request, or certificate revocation list, respectively.
When constructing the subject key identifier of a certificate by computing a
hash value of its public key, the public key is taken from I<subject> or I<req>.
Similarly, when constructing subject alternative names from any email addresses
contained in a subject DN, the subject DN is taken from I<subject> or I<req>.
If I<subject> or I<crl> is provided, I<issuer> should point to its issuer,
for instance to help generating an authority key identifier extension.
Note that if I<subject> is provided, I<issuer> may be the same as I<subject>,
which means that I<subject> is self-issued (or even self-signed).
I<flags> may be 0
or contain B<X509V3_CTX_TEST>, which means that just the syntax of
extension definitions is to be checked without actually producing an extension,
or B<X509V3_CTX_REPLACE>, which means that each X.509v3 extension added as
defined in some configuration section shall replace any already existing
extension with the same OID.
X509V3_set_issuer_pkey() explicitly sets the issuer private key of
the certificate that has been provided in I<ctx>.
This should be done for self-issued certificates (which may be self-signed
or not) to provide fallback data for the authority key identifier extension.
=head1 RETURN VALUES
-X509V3_set_ctx() and X509V3_set_issuer_pkey()
-return 1 on success and 0 on error.
+X509V3_set_issuer_pkey() returns 1 on success and 0 on error.
=head1 SEE ALSO
L<X509_add_ext(3)>
=head1 HISTORY
X509V3_set_issuer_pkey() was added in OpenSSL 3.0.
CTX_TEST was deprecated in OpenSSL 3.0; use X509V3_CTX_TEST instead.
=head1 COPYRIGHT
-Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/X509_STORE_CTX_new.pod b/crypto/openssl/doc/man3/X509_STORE_CTX_new.pod
index c508a1d3fc1b..9929a98e0cf5 100644
--- a/crypto/openssl/doc/man3/X509_STORE_CTX_new.pod
+++ b/crypto/openssl/doc/man3/X509_STORE_CTX_new.pod
@@ -1,283 +1,290 @@
=pod
=head1 NAME
X509_STORE_CTX_new_ex, X509_STORE_CTX_new, X509_STORE_CTX_cleanup,
X509_STORE_CTX_free, X509_STORE_CTX_init, X509_STORE_CTX_set0_trusted_stack,
X509_STORE_CTX_set_cert, X509_STORE_CTX_set0_crls,
X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param,
X509_STORE_CTX_get0_untrusted, X509_STORE_CTX_set0_untrusted,
X509_STORE_CTX_get_num_untrusted,
X509_STORE_CTX_get0_chain, X509_STORE_CTX_set0_verified_chain,
X509_STORE_CTX_set_default,
X509_STORE_CTX_set_verify,
X509_STORE_CTX_verify_fn,
X509_STORE_CTX_set_purpose,
X509_STORE_CTX_set_trust,
X509_STORE_CTX_purpose_inherit
- X509_STORE_CTX initialisation
=head1 SYNOPSIS
#include <openssl/x509_vfy.h>
X509_STORE_CTX *X509_STORE_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
X509_STORE_CTX *X509_STORE_CTX_new(void);
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store,
X509 *target, STACK_OF(X509) *untrusted);
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target);
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx);
STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *chain);
int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *);
void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, X509_STORE_CTX_verify_fn verify);
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
int purpose, int trust);
=head1 DESCRIPTION
These functions initialise an B<X509_STORE_CTX> structure for subsequent use
by L<X509_verify_cert(3)> or L<X509_STORE_CTX_verify(3)>.
X509_STORE_CTX_new_ex() returns a newly initialised B<X509_STORE_CTX>
structure associated with the specified library context I<libctx> and property
query string I<propq>. Any cryptographic algorithms fetched while performing
processing with the X509_STORE_CTX will use that library context and property
query string.
X509_STORE_CTX_new() is the same as X509_STORE_CTX_new_ex() except that
the default library context and a NULL property query string are used.
X509_STORE_CTX_cleanup() internally cleans up an B<X509_STORE_CTX> structure.
It is used by X509_STORE_CTX_init() and X509_STORE_CTX_free().
X509_STORE_CTX_free() completely frees up I<ctx>. After this call I<ctx>
is no longer valid.
If I<ctx> is NULL nothing is done.
+X509_STORE_CTX_init() sets up I<ctx> for a subsequent verification operation.
+
+X509_STORE_CTX_init() initializes the internal state and resources of the
+given I<ctx>. Among others, it sets the verification parameters associcated
+with the method name C<default>, which includes the C<any> purpose,
+and takes over callback function pointers from I<trust_store> (unless NULL).
It must be called before each call to L<X509_verify_cert(3)> or
L<X509_STORE_CTX_verify(3)>, i.e., a context is only good for one verification.
If you want to verify a further certificate or chain with the same I<ctx>
then you must call X509_STORE_CTX_init() again.
The trusted certificate store is set to I<trust_store> of type B<X509_STORE>.
This may be NULL because there are no trusted certificates or because
they are provided simply as a list using X509_STORE_CTX_set0_trusted_stack().
The certificate to be verified is set to I<target>,
and a list of additional certificates may be provided in I<untrusted>,
which will be untrusted but may be used to build the chain.
Each of the I<trust_store>, I<target> and I<untrusted> parameters can be NULL.
Yet note that L<X509_verify_cert(3)> and L<X509_STORE_CTX_verify(3)>
will need a verification target.
This can also be set using X509_STORE_CTX_set_cert().
For L<X509_STORE_CTX_verify(3)>, which takes by default the first element of the
list of untrusted certificates as its verification target,
this can be also set indirectly using X509_STORE_CTX_set0_untrusted().
X509_STORE_CTX_set0_trusted_stack() sets the set of trusted certificates of
I<ctx> to I<sk>. This is an alternative way of specifying trusted certificates
instead of using an B<X509_STORE> where its complexity is not needed
or to make sure that only the given set I<sk> of certificates are trusted.
X509_STORE_CTX_set_cert() sets the target certificate to be verified in I<ctx>
to I<target>.
X509_STORE_CTX_set0_verified_chain() sets the validated chain to I<chain>.
Ownership of the chain is transferred to I<ctx>,
and so it should not be free'd by the caller.
X509_STORE_CTX_get0_chain() returns the internal pointer used by the
I<ctx> that contains the constructed (output) chain.
X509_STORE_CTX_set0_crls() sets a set of CRLs to use to aid certificate
verification to I<sk>. These CRLs will only be used if CRL verification is
enabled in the associated B<X509_VERIFY_PARAM> structure. This might be
used where additional "useful" CRLs are supplied as part of a protocol,
for example in a PKCS#7 structure.
X509_STORE_CTX_get0_param() retrieves an internal pointer
to the verification parameters associated with I<ctx>.
X509_STORE_CTX_set0_param() sets the internal verification parameter pointer
to I<param>. After this call B<param> should not be used.
X509_STORE_CTX_get0_untrusted() retrieves an internal pointer to the
stack of untrusted certificates associated with I<ctx>.
X509_STORE_CTX_set0_untrusted() sets the internal pointer to the stack
of untrusted certificates associated with I<ctx> to I<sk>.
X509_STORE_CTX_verify() will take the first element, if any,
as its default target if the target certificate is not set explicitly.
X509_STORE_CTX_get_num_untrusted() returns the number of untrusted certificates
that were used in building the chain.
This is can be used after calling L<X509_verify_cert(3)> and similar functions.
With L<X509_STORE_CTX_verify(3)>, this does not count the first chain element.
X509_STORE_CTX_get0_chain() returns the internal pointer used by the
I<ctx> that contains the validated chain.
Details of the chain building and checking process are described in
L<openssl-verification-options(1)/Certification Path Building> and
L<openssl-verification-options(1)/Certification Path Validation>.
X509_STORE_CTX_set0_verified_chain() sets the validated chain used
by I<ctx> to be I<chain>.
Ownership of the chain is transferred to I<ctx>,
and so it should not be free'd by the caller.
-X509_STORE_CTX_set_default() looks up and sets the default verification
-method to I<name>. This uses the function X509_VERIFY_PARAM_lookup() to
-find an appropriate set of parameters from the purpose identifier I<name>.
-Currently defined purposes are C<sslclient>, C<sslserver>, C<nssslserver>,
-C<smimesign>, C<smimeencrypt>, C<crlsign>, C<ocsphelper>, C<timestampsign>,
-and C<any>.
+X509_STORE_CTX_set_default() looks up and sets the default verification method.
+This uses the function X509_VERIFY_PARAM_lookup() to find
+the set of parameters associated with the given verification method I<name>.
+Among others, the parameters determine the trust model and verification purpose.
+More detail, including the list of currently predefined methods,
+is described for the B<-verify_name> command-line option
+in L<openssl-verification-options(1)/Verification Options>.
X509_STORE_CTX_set_verify() provides the capability for overriding the default
verify function. This function is responsible for verifying chain signatures and
expiration times.
A verify function is defined as an X509_STORE_CTX_verify type which has the
following signature:
int (*verify)(X509_STORE_CTX *);
This function should receive the current X509_STORE_CTX as a parameter and
return 1 on success or 0 on failure.
X509 certificates may contain information about what purposes keys contained
within them can be used for. For example "TLS WWW Server Authentication" or
"Email Protection". This "key usage" information is held internally to the
certificate itself. In addition the trust store containing trusted certificates
can declare what purposes we trust different certificates for. This "trust"
information is not held within the certificate itself but is "meta" information
held alongside it. This "meta" information is associated with the certificate
after it is issued and could be determined by a system administrator. For
example a certificate might declare that it is suitable for use for both
"TLS WWW Server Authentication" and "TLS Client Authentication", but a system
administrator might only trust it for the former. An X.509 certificate extension
exists that can record extended key usage information to supplement the purpose
information described above. This extended mechanism is arbitrarily extensible
and not well suited for a generic library API; applications that need to
validate extended key usage information in certificates will need to define a
custom "purpose" (see below) or supply a nondefault verification callback
(L<X509_STORE_set_verify_cb_func(3)>).
X509_STORE_CTX_set_purpose() sets the purpose for the target certificate being
verified in the I<ctx>. Built-in available values for the I<purpose> argument
are B<X509_PURPOSE_SSL_CLIENT>, B<X509_PURPOSE_SSL_SERVER>,
B<X509_PURPOSE_NS_SSL_SERVER>, B<X509_PURPOSE_SMIME_SIGN>,
B<X509_PURPOSE_SMIME_ENCRYPT>, B<X509_PURPOSE_CRL_SIGN>, B<X509_PURPOSE_ANY>,
B<X509_PURPOSE_OCSP_HELPER> and B<X509_PURPOSE_TIMESTAMP_SIGN>. It is also
possible to create a custom purpose value. Setting a purpose will ensure that
the key usage declared within certificates in the chain being verified is
consistent with that purpose as well as, potentially, other checks. Every
purpose also has an associated default trust value which will also be set at the
same time. During verification this trust setting will be verified to check it
is consistent with the trust set by the system administrator for certificates in
the chain.
X509_STORE_CTX_set_trust() sets the trust value for the target certificate
being verified in the I<ctx>. Built-in available values for the I<trust>
argument are B<X509_TRUST_COMPAT>, B<X509_TRUST_SSL_CLIENT>,
B<X509_TRUST_SSL_SERVER>, B<X509_TRUST_EMAIL>, B<X509_TRUST_OBJECT_SIGN>,
B<X509_TRUST_OCSP_SIGN>, B<X509_TRUST_OCSP_REQUEST> and B<X509_TRUST_TSA>. It is
also possible to create a custom trust value. Since X509_STORE_CTX_set_purpose()
also sets the trust value it is normally sufficient to only call that function.
If both are called then X509_STORE_CTX_set_trust() should be called after
X509_STORE_CTX_set_purpose() since the trust setting of the last call will be
used.
It should not normally be necessary for end user applications to call
X509_STORE_CTX_purpose_inherit() directly. Typically applications should call
X509_STORE_CTX_set_purpose() or X509_STORE_CTX_set_trust() instead. Using this
function it is possible to set the purpose and trust values for the I<ctx> at
the same time.
Both I<ctx> and its internal verification parameter pointer must not be NULL.
The I<def_purpose> and I<purpose> arguments can have the same
purpose values as described for X509_STORE_CTX_set_purpose() above. The I<trust>
argument can have the same trust values as described in
X509_STORE_CTX_set_trust() above. Any of the I<def_purpose>, I<purpose> or
I<trust> values may also have the value 0 to indicate that the supplied
parameter should be ignored. After calling this function the purpose to be used
for verification is set from the I<purpose> argument unless the purpose was
already set in I<ctx> before, and the trust is set from the I<trust> argument
unless the trust was already set in I<ctx> before.
If I<trust> is 0 then the trust value will be set from
the default trust value for I<purpose>. If the default trust value for the
purpose is I<X509_TRUST_DEFAULT> and I<trust> is 0 then the default trust value
associated with the I<def_purpose> value is used for the trust setting instead.
=head1 NOTES
The certificates and CRLs in a store are used internally and should B<not>
be freed up until after the associated B<X509_STORE_CTX> is freed.
=head1 BUGS
The certificates and CRLs in a context are used internally and should B<not>
be freed up until after the associated B<X509_STORE_CTX> is freed. Copies
should be made or reference counts increased instead.
=head1 RETURN VALUES
X509_STORE_CTX_new() returns a newly allocated context or NULL if an
error occurred.
X509_STORE_CTX_init() returns 1 for success or 0 if an error occurred.
X509_STORE_CTX_get0_param() returns a pointer to an B<X509_VERIFY_PARAM>
structure or NULL if an error occurred.
X509_STORE_CTX_cleanup(), X509_STORE_CTX_free(),
X509_STORE_CTX_set0_trusted_stack(),
X509_STORE_CTX_set_cert(),
X509_STORE_CTX_set0_crls() and X509_STORE_CTX_set0_param() do not return
values.
X509_STORE_CTX_set_default() returns 1 for success or 0 if an error occurred.
X509_STORE_CTX_get_num_untrusted() returns the number of untrusted certificates
used.
=head1 SEE ALSO
L<X509_verify_cert(3)>, L<X509_STORE_CTX_verify(3)>,
L<X509_VERIFY_PARAM_set_flags(3)>
=head1 HISTORY
The X509_STORE_CTX_set0_crls() function was added in OpenSSL 1.0.0.
The X509_STORE_CTX_get_num_untrusted() function was added in OpenSSL 1.1.0.
The X509_STORE_CTX_new_ex() function was added in OpenSSL 3.0.
There is no need to call X509_STORE_CTX_cleanup() explicitly since OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/X509_add_cert.pod b/crypto/openssl/doc/man3/X509_add_cert.pod
index 907164e9710e..f59b93ba54d4 100644
--- a/crypto/openssl/doc/man3/X509_add_cert.pod
+++ b/crypto/openssl/doc/man3/X509_add_cert.pod
@@ -1,76 +1,77 @@
=pod
=head1 NAME
X509_add_cert,
X509_add_certs -
X509 certificate list addition functions
=head1 SYNOPSIS
#include <openssl/x509.h>
int X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags);
int X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags);
=head1 DESCRIPTION
X509_add_cert() adds a certificate I<cert> to the given list I<sk>.
+It is an error for the I<cert> argument to be NULL.
X509_add_certs() adds a list of certificate I<certs> to the given list I<sk>.
The I<certs> argument may be NULL, which implies no effect.
It does not modify the list I<certs> but
in case the B<X509_ADD_FLAG_UP_REF> flag (described below) is set
the reference counters of those of its members added to I<sk> are increased.
Both these functions have a I<flags> parameter,
which is used to control details of the operation.
The value B<X509_ADD_FLAG_DEFAULT>, which equals 0, means no special semantics.
If B<X509_ADD_FLAG_UP_REF> is set then
the reference counts of those certificates added successfully are increased.
If B<X509_ADD_FLAG_PREPEND> is set then the certificates are prepended to I<sk>.
By default they are appended to I<sk>.
In both cases the original order of the added certificates is preserved.
If B<X509_ADD_FLAG_NO_DUP> is set then certificates already contained in I<sk>,
which is determined using L<X509_cmp(3)>, are ignored.
If B<X509_ADD_FLAG_NO_SS> is set then certificates that are marked self-signed,
which is determined using L<X509_self_signed(3)>, are ignored.
=head1 RETURN VALUES
Both functions return 1 for success and 0 for failure.
=head1 NOTES
If X509_add_certs() is used with the flags B<X509_ADD_FLAG_NO_DUP> or
B<X509_ADD_FLAG_NO_SS> it is advisable to use also B<X509_ADD_FLAG_UP_REF>
because otherwise likely not for all members of the I<certs> list
the ownership is transferred to the list of certificates I<sk>.
Care should also be taken in case the I<certs> argument equals I<sk>.
=head1 SEE ALSO
L<X509_cmp(3)>
L<X509_self_signed(3)>
=head1 HISTORY
The functions X509_add_cert() and X509_add_certs()
were added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man3/X509_load_http.pod b/crypto/openssl/doc/man3/X509_load_http.pod
index a147c43caa3f..e17330b05587 100644
--- a/crypto/openssl/doc/man3/X509_load_http.pod
+++ b/crypto/openssl/doc/man3/X509_load_http.pod
@@ -1,68 +1,71 @@
=pod
=head1 NAME
X509_load_http,
X509_http_nbio,
X509_CRL_load_http,
X509_CRL_http_nbio
- certificate and CRL loading functions
=head1 SYNOPSIS
#include <openssl/x509.h>
X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
The following macros have been deprecated since OpenSSL 3.0, and can be
hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
see L<openssl_user_macros(7)>:
#define X509_http_nbio(rctx, pcert)
#define X509_CRL_http_nbio(rctx, pcrl)
=head1 DESCRIPTION
X509_load_http() and X509_CRL_load_http() loads a certificate or a CRL,
respectively, in ASN.1 format using HTTP from the given B<url>.
+Maximum size of the HTTP response is 100 kB for certificates and 32 MB for CRLs
+and hard coded in the functions.
+
If B<bio> is given and B<rbio> is NULL then this BIO is used instead of an
internal one for connecting, writing the request, and reading the response.
If both B<bio> and B<rbio> are given (which may be memory BIOs, for instance)
then no explicit connection is attempted,
B<bio> is used for writing the request, and B<rbio> for reading the response.
If the B<timeout> parameter is > 0 this indicates the maximum number of seconds
to wait until the transfer is complete.
A value of 0 enables waiting indefinitely,
while a value < 0 immediately leads to a timeout condition.
X509_http_nbio() and X509_CRL_http_nbio() are macros for backward compatibility
that have the same effect as the functions above but with infinite timeout
and without the possibility to specify custom BIOs.
=head1 RETURN VALUES
On success the function yield the loaded value, else NULL.
Error conditions include connection/transfer timeout, parse errors, etc.
=head1 SEE ALSO
L<OSSL_HTTP_get(3)>
=head1 HISTORY
X509_load_http() and X509_CRL_load_http() were added in OpenSSL 3.0.
X509_http_nbio() and X509_CRL_http_nbio() were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-HKDF.pod b/crypto/openssl/doc/man7/EVP_KDF-HKDF.pod
index 5fc0a73241cc..b563efa5f5d7 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-HKDF.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-HKDF.pod
@@ -1,156 +1,158 @@
=pod
=head1 NAME
EVP_KDF-HKDF - The HKDF EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the B<HKDF> KDF through the B<EVP_KDF> API.
The EVP_KDF-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).
+The output is considered to be keying material.
+
=head2 Identity
"HKDF" is the name for this implementation; it
can be used with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
=item "info" (B<OSSL_KDF_PARAM_INFO>) <octet string>
This parameter sets the info value.
The length of the context info buffer cannot exceed 1024 bytes;
this should be more than enough for any normal use of HKDF.
=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string> or <integer>
This parameter sets the mode for the HKDF operation.
There are three modes that are currently defined:
=over 4
=item "EXTRACT_AND_EXPAND" or B<EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND>
This is the default mode. Calling L<EVP_KDF_derive(3)> on an EVP_KDF_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 otherwise an error will occur.
=item "EXTRACT_ONLY" or B<EVP_KDF_HKDF_MODE_EXTRACT_ONLY>
In this mode calling L<EVP_KDF_derive(3)> will just perform the extract
operation. The value returned will be the intermediate fixed-length pseudorandom
key K. The I<keylen> parameter must match the size of K, which can be looked
up by calling EVP_KDF_CTX_get_kdf_size() after setting the mode and digest.
The digest, key and salt values must be set before a key is derived otherwise
an error will occur.
=item "EXPAND_ONLY" or B<EVP_KDF_HKDF_MODE_EXPAND_ONLY>
In this mode calling L<EVP_KDF_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 otherwise
an error will occur.
=back
=back
=head1 NOTES
A context for HKDF can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The output length of an HKDF expand operation is specified via the I<keylen>
parameter to the L<EVP_KDF_derive(3)> function. When using
EVP_KDF_HKDF_MODE_EXTRACT_ONLY the I<keylen> parameter must equal the size of
the intermediate fixed-length pseudorandom key otherwise an error will occur.
For that mode, the fixed output size can be looked up by calling EVP_KDF_CTX_get_kdf_size()
after setting the mode and digest on the B<EVP_KDF_CTX>.
=head1 EXAMPLES
This example derives 10 bytes using SHA-256 with the secret key "secret",
salt value "salt" and info value "label":
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
OSSL_PARAM params[5], *p = params;
kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
SN_sha256, strlen(SN_sha256));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
"secret", (size_t)6);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
"label", (size_t)5);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
"salt", (size_t)4);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
RFC 5869
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_get_kdf_size(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>,
L<EVP_KDF-TLS13_KDF(7)>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-KB.pod b/crypto/openssl/doc/man7/EVP_KDF-KB.pod
index 6e25882d674c..78b81673a5bd 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-KB.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-KB.pod
@@ -1,172 +1,174 @@
=pod
=head1 NAME
EVP_KDF-KB - The Key-Based EVP_KDF implementation
=head1 DESCRIPTION
The EVP_KDF-KB algorithm implements the Key-Based key derivation function
(KBKDF). KBKDF derives a key from repeated application of a keyed MAC to an
input secret (and other optional values).
+The output is considered to be keying material.
+
=head2 Identity
"KBKDF" is the name for this implementation; it can be used with the
EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string>
The mode parameter determines which flavor of KBKDF to use - currently the
choices are "counter" and "feedback". "counter" is the default, and will be
used if unspecified.
=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string>
The value is either CMAC or HMAC.
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
=item "cipher" (B<OSSL_KDF_PARAM_CIPHER>) <UTF8 string>
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
=item "info (B<OSSL_KDF_PARAM_INFO>) <octet string>
=item "seed" (B<OSSL_KDF_PARAM_SEED>) <octet string>
The seed parameter is unused in counter mode.
=item "use-l" (B<OSSL_KDF_PARAM_KBKDF_USE_L>) <integer>
Set to B<0> to disable use of the optional Fixed Input data 'L' (see SP800-108).
The default value of B<1> will be used if unspecified.
=item "use-separator" (B<OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR>) <integer>
Set to B<0> to disable use of the optional Fixed Input data 'zero separator'
(see SP800-108) that is placed between the Label and Context.
The default value of B<1> will be used if unspecified.
=back
Depending on whether mac is CMAC or HMAC, either digest or cipher is required
(respectively) and the other is unused.
The parameters key, salt, info, and seed correspond to KI, Label, Context, and
IV (respectively) in SP800-108. As in that document, salt, info, and seed are
optional and may be omitted.
"mac", "digest", cipher" and "properties" are described in
L<EVP_KDF(3)/PARAMETERS>.
=head1 NOTES
A context for KBKDF can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The output length of an KBKDF is specified via the C<keylen>
parameter to the L<EVP_KDF_derive(3)> function.
Note that currently OpenSSL only implements counter and feedback modes. Other
variants may be supported in the future.
=head1 EXAMPLES
This example derives 10 bytes using COUNTER-HMAC-SHA256, with KI "secret",
Label "label", and Context "context".
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
OSSL_PARAM params[6], *p = params;
kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
"SHA2-256", 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
"HMAC", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
"secret", strlen("secret"));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
"label", strlen("label"));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
"context", strlen("context"));
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0)
error("EVP_KDF_derive");
EVP_KDF_CTX_free(kctx);
This example derives 10 bytes using FEEDBACK-CMAC-AES256, with KI "secret",
Label "label", and IV "sixteen bytes iv".
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
OSSL_PARAM params[8], *p = params;
unsigned char *iv = "sixteen bytes iv";
kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER, "AES256", 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC, "CMAC", 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE, "FEEDBACK", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
"secret", strlen("secret"));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
"label", strlen("label"));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
"context", strlen("context"));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
iv, strlen(iv));
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0)
error("EVP_KDF_derive");
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
NIST SP800-108, IETF RFC 6803, IETF RFC 8009.
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_get_kdf_size(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2019 Red Hat, Inc.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-PBKDF2.pod b/crypto/openssl/doc/man7/EVP_KDF-PBKDF2.pod
index e6cadc8b826d..9a90f7583abe 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-PBKDF2.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-PBKDF2.pod
@@ -1,104 +1,106 @@
=pod
=head1 NAME
EVP_KDF-PBKDF2 - The PBKDF2 EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the B<PBKDF2> password-based KDF through the B<EVP_KDF>
API.
The EVP_KDF-PBKDF2 algorithm implements the PBKDF2 password-based key
derivation function, as described in SP800-132; it derives a key from a password
using a salt and iteration count.
+The output is considered to be a cryptographic key.
+
=head2 Identity
"PBKDF2" is the name for this implementation; it
can be used with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "pass" (B<OSSL_KDF_PARAM_PASSWORD>) <octet string>
=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
=item "iter" (B<OSSL_KDF_PARAM_ITER>) <unsigned integer>
This parameter has a default value of 2048.
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
=item "pkcs5" (B<OSSL_KDF_PARAM_PKCS5>) <integer>
This parameter can be used to enable or disable SP800-132 compliance checks.
Setting the mode to 0 enables the compliance checks.
The checks performed are:
=over 4
=item - the iteration count is at least 1000.
=item - the salt length is at least 128 bits.
=item - the derived key length is at least 112 bits.
=back
The default provider uses a default mode of 1 for backwards compatibility,
and the FIPS provider uses a default mode of 0.
The value string is expected to be a decimal number 0 or 1.
=back
=head1 NOTES
A typical application of this algorithm is to derive keying material for an
encryption algorithm from a password in the "pass", a salt in "salt",
and an iteration count.
Increasing the "iter" parameter slows down the algorithm which makes it
harder for an attacker to perform a brute force attack using a large number
of candidate passwords.
No assumption is made regarding the given password; it is simply treated as a
byte sequence.
=head1 CONFORMING TO
SP800-132
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-SS.pod b/crypto/openssl/doc/man7/EVP_KDF-SS.pod
index c8d19691a797..6640703eef1c 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-SS.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-SS.pod
@@ -1,188 +1,190 @@
=pod
=head1 NAME
EVP_KDF-SS - The Single Step / One Step EVP_KDF implementation
=head1 DESCRIPTION
The EVP_KDF-SS algorithm implements the Single Step key derivation function (SSKDF).
SSKDF derives a key using input such as a shared secret key (that was generated
during the execution of a key establishment scheme) and fixedinfo.
SSKDF is also informally referred to as 'Concat KDF'.
+The output is considered to be keying material.
+
=head2 Auxiliary function
The implementation uses a selectable auxiliary function H, which can be one of:
=over 4
=item B<H(x) = hash(x, digest=md)>
=item B<H(x) = HMAC_hash(x, key=salt, digest=md)>
=item B<H(x) = KMACxxx(x, key=salt, custom="KDF", outlen=mac_size)>
=back
Both the HMAC and KMAC implementations set the key using the 'salt' value.
The hash and HMAC also require the digest to be set.
=head2 Identity
"SSKDF" is the name for this implementation; it
can be used with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
This parameter is ignored for KMAC.
=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string>
=item "maclen" (B<OSSL_KDF_PARAM_MAC_SIZE>) <unsigned integer>
=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
=item "key" (B<OSSL_KDF_PARAM_SECRET>) <octet string>
This parameter set the shared secret that is used for key derivation.
=item "info" (B<OSSL_KDF_PARAM_INFO>) <octet string>
This parameter sets an optional value for fixedinfo, also known as otherinfo.
=back
=head1 NOTES
A context for SSKDF can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The output length of an SSKDF is specified via the I<keylen>
parameter to the L<EVP_KDF_derive(3)> function.
=head1 EXAMPLES
This example derives 10 bytes using H(x) = SHA-256, with the secret key "secret"
and fixedinfo value "label":
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
OSSL_PARAM params[4], *p = params;
kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
SN_sha256, strlen(SN_sha256));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
"secret", (size_t)6);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
"label", (size_t)5);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
This example derives 10 bytes using H(x) = HMAC(SHA-256), with the secret key "secret",
fixedinfo value "label" and salt "salt":
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
OSSL_PARAM params[6], *p = params;
kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
SN_hmac, strlen(SN_hmac));
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
SN_sha256, strlen(SN_sha256));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
"secret", (size_t)6);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
"label", (size_t)5);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
"salt", (size_t)4);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
This example derives 10 bytes using H(x) = KMAC128(x,salt,outlen), with the secret key "secret"
fixedinfo value "label", salt of "salt" and KMAC outlen of 20:
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
OSSL_PARAM params[6], *p = params;
kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
SN_kmac128, strlen(SN_kmac128));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
"secret", (size_t)6);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
"label", (size_t)5);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
"salt", (size_t)4);
*p++ = OSSL_PARAM_construct_size_t(OSSL_KDF_PARAM_MAC_SIZE, (size_t)20);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
NIST SP800-56Cr1.
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_CTX_get_kdf_size(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. Copyright
(c) 2019, Oracle and/or its affiliates. All rights reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-SSHKDF.pod b/crypto/openssl/doc/man7/EVP_KDF-SSHKDF.pod
index c7a3263f455a..a5b153947558 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-SSHKDF.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-SSHKDF.pod
@@ -1,161 +1,163 @@
=pod
=head1 NAME
EVP_KDF-SSHKDF - The SSHKDF EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the B<SSHKDF> KDF through the B<EVP_KDF> API.
The EVP_KDF-SSHKDF algorithm implements the SSHKDF key derivation function.
It is defined in RFC 4253, section 7.2 and is used by SSH to derive IVs,
encryption keys and integrity keys.
Five inputs are required to perform key derivation: The hashing function
(for example SHA256), the Initial Key, the Exchange Hash, the Session ID,
and the derivation key type.
+The output is considered to be keying material.
+
=head2 Identity
"SSHKDF" is the name for this implementation; it
can be used with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
=item "xcghash" (B<OSSL_KDF_PARAM_SSHKDF_XCGHASH>) <octet string>
=item "session_id" (B<OSSL_KDF_PARAM_SSHKDF_SESSION_ID>) <octet string>
These parameters set the respective values for the KDF.
If a value is already set, the contents are replaced.
=item "type" (B<OSSL_KDF_PARAM_SSHKDF_TYPE>) <UTF8 string>
This parameter sets the type for the SSHKDF operation.
There are six supported types:
=over 4
=item EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV
The Initial IV from client to server.
A single char of value 65 (ASCII char 'A').
=item EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI
The Initial IV from server to client
A single char of value 66 (ASCII char 'B').
=item EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV
The Encryption Key from client to server
A single char of value 67 (ASCII char 'C').
=item EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_SRV_TO_CLI
The Encryption Key from server to client
A single char of value 68 (ASCII char 'D').
=item EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV
The Integrity Key from client to server
A single char of value 69 (ASCII char 'E').
=item EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI
The Integrity Key from client to server
A single char of value 70 (ASCII char 'F').
=back
=back
=head1 NOTES
A context for SSHKDF can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The output length of the SSHKDF derivation is specified via the I<keylen>
parameter to the L<EVP_KDF_derive(3)> function.
Since the SSHKDF output length is variable, calling L<EVP_KDF_CTX_get_kdf_size(3)>
to obtain the requisite length is not meaningful. The caller must
allocate a buffer of the desired length, and pass that buffer to the
L<EVP_KDF_derive(3)> function along with the desired length.
=head1 EXAMPLES
This example derives an 8 byte IV using SHA-256 with a 1K "key" and appropriate
"xcghash" and "session_id" values:
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
char type = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
unsigned char key[1024] = "01234...";
unsigned char xcghash[32] = "012345...";
unsigned char session_id[32] = "012345...";
unsigned char out[8];
size_t outlen = sizeof(out);
OSSL_PARAM params[6], *p = params;
kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
SN_sha256, strlen(SN_sha256));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
key, (size_t)1024);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH,
xcghash, (size_t)32);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID,
session_id, (size_t)32);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE,
&type, sizeof(type));
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, outlen, params) <= 0)
/* Error */
=head1 CONFORMING TO
RFC 4253
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_CTX_get_kdf_size(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-TLS13_KDF.pod b/crypto/openssl/doc/man7/EVP_KDF-TLS13_KDF.pod
index d588b121faf5..7fad55ca61f1 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-TLS13_KDF.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-TLS13_KDF.pod
@@ -1,132 +1,134 @@
=pod
=head1 NAME
EVP_KDF-TLS13_KDF - The TLS 1.3 EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the TLS 1.3 version of the B<HKDF> KDF through
the B<EVP_KDF> API.
The EVP_KDF-TLS13_KDF algorithm implements the HKDF key derivation function
as used by TLS 1.3.
+The output is considered to be keying material.
+
=head2 Identity
"TLS13-KDF" is the name for this implementation; it
can be used with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
=item "prefix" (B<OSSL_KDF_PARAM_PREFIX>) <octet string>
This parameter sets the label prefix on the specified TLS 1.3 KDF context.
For TLS 1.3 this should be set to the ASCII string "tls13 " without a
trailing zero byte. Refer to RFC 8446 section 7.1 "Key Schedule" for details.
=item "label" (B<OSSL_KDF_PARAM_LABEL>) <octet string>
This parameter sets the label on the specified TLS 1.3 KDF context.
Refer to RFC 8446 section 7.1 "Key Schedule" for details.
=item "data" (B<OSSL_KDF_PARAM_DATA>) <octet string>
This parameter sets the context data on the specified TLS 1.3 KDF context.
Refer to RFC 8446 section 7.1 "Key Schedule" for details.
=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string> or <integer>
This parameter sets the mode for the TLS 1.3 KDF operation.
There are two modes that are currently defined:
=over 4
=item "EXTRACT_ONLY" or B<EVP_KDF_HKDF_MODE_EXTRACT_ONLY>
In this mode calling L<EVP_KDF_derive(3)> will just perform the extract
operation. The value returned will be the intermediate fixed-length pseudorandom
key K. The I<keylen> parameter must match the size of K, which can be looked
up by calling EVP_KDF_CTX_get_kdf_size() after setting the mode and digest.
The digest, key and salt values must be set before a key is derived otherwise
an error will occur.
=item "EXPAND_ONLY" or B<EVP_KDF_HKDF_MODE_EXPAND_ONLY>
In this mode calling L<EVP_KDF_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 otherwise
an error will occur.
=back
=back
=head1 NOTES
This KDF is intended for use by the TLS 1.3 implementation in libssl.
It does not support all the options and capabilities that HKDF does.
The I<OSSL_PARAM> array passed to L<EVP_KDF_derive(3)> or
L<EVP_KDF_CTX_set_params(3)> must specify all of the parameters required.
This KDF does not support a piecemeal approach to providing these.
A context for a TLS 1.3 KDF can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "TLS13-KDF", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The output length of a TLS 1.3 KDF expand operation is specified via the
I<keylen> parameter to the L<EVP_KDF_derive(3)> function. When using
EVP_KDF_HKDF_MODE_EXTRACT_ONLY the I<keylen> parameter must equal the size of
the intermediate fixed-length pseudorandom key otherwise an error will occur.
For that mode, the fixed output size can be looked up by calling
EVP_KDF_CTX_get_kdf_size() after setting the mode and digest on the
B<EVP_KDF_CTX>.
=head1 CONFORMING TO
RFC 8446
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_get_kdf_size(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>,
L<EVP_KDF-HKDF(7)>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-TLS1_PRF.pod b/crypto/openssl/doc/man7/EVP_KDF-TLS1_PRF.pod
index 8a60e9731554..90b357e70f0b 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-TLS1_PRF.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-TLS1_PRF.pod
@@ -1,114 +1,116 @@
=pod
=head1 NAME
EVP_KDF-TLS1_PRF - The TLS1 PRF EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the B<TLS1> PRF through the B<EVP_KDF> API.
The EVP_KDF-TLS1_PRF algorithm implements the PRF used by TLS versions up to
and including TLS 1.2.
+The output is considered to be keying material.
+
=head2 Identity
"TLS1-PRF" is the name for this implementation; it
can be used with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
The B<OSSL_KDF_PARAM_DIGEST> parameter is used to set the message digest
associated with the TLS PRF.
EVP_md5_sha1() is treated as a special case which uses the
PRF algorithm using both B<MD5> and B<SHA1> as used in TLS 1.0 and 1.1.
=item "secret" (B<OSSL_KDF_PARAM_SECRET>) <octet string>
This parameter sets the secret value of the TLS PRF.
Any existing secret value is replaced.
=item "seed" (B<OSSL_KDF_PARAM_SEED>) <octet string>
This parameter sets the context seed.
The length of the context seed cannot exceed 1024 bytes;
this should be more than enough for any normal use of the TLS PRF.
=back
=head1 NOTES
A context for the TLS PRF can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "TLS1-PRF", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The digest, secret value and seed must be set before a key is derived otherwise
an error will occur.
The output length of the PRF is specified by the I<keylen> parameter to the
EVP_KDF_derive() function.
=head1 EXAMPLES
This example derives 10 bytes using SHA-256 with the secret key "secret"
and seed value "seed":
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
OSSL_PARAM params[4], *p = params;
kdf = EVP_KDF_fetch(NULL, "TLS1-PRF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
SN_sha256, strlen(SN_sha256));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
"secret", (size_t)6);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
"seed", (size_t)4);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
RFC 2246, RFC 5246 and NIST SP 800-135 r1
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-X942-ASN1.pod b/crypto/openssl/doc/man7/EVP_KDF-X942-ASN1.pod
index a5786ab83faa..17464738b511 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-X942-ASN1.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-X942-ASN1.pod
@@ -1,151 +1,153 @@
=pod
=head1 NAME
EVP_KDF-X942-ASN1 - The X9.42-2003 asn1 EVP_KDF implementation
=head1 DESCRIPTION
The EVP_KDF-X942-ASN1 algorithm implements the key derivation function
X942KDF-ASN1. It is used by DH KeyAgreement, to derive a key using input such as
a shared secret key and other info. The other info is DER encoded data that
contains a 32 bit counter as well as optional fields for "partyu-info",
"partyv-info", "supp-pubinfo" and "supp-privinfo".
This kdf is used by Cryptographic Message Syntax (CMS).
+The output is considered to be keying material.
+
=head2 Identity
"X942KDF-ASN1" or "X942KDF" is the name for this implementation; it
can be used with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
=item "secret" (B<OSSL_KDF_PARAM_SECRET>) <octet string>
The shared secret used for key derivation. This parameter sets the secret.
=item "acvp-info" (B<OSSL_KDF_PARAM_X942_ACVPINFO>) <octet string>
This value should not be used in production and should only be used for ACVP
testing. It is an optional octet string containing a combined DER encoded blob
of any of the optional fields related to "partyu-info", "partyv-info",
"supp-pubinfo" and "supp-privinfo". If it is specified then none of these other
fields should be used.
=item "partyu-info" (B<OSSL_KDF_PARAM_X942_PARTYUINFO>) <octet string>
An optional octet string containing public info contributed by the initiator.
=item "ukm" (B<OSSL_KDF_PARAM_UKM>) <octet string>
An alias for "partyu-info".
In CMS this is the user keying material.
=item "partyv-info" (B<OSSL_KDF_PARAM_X942_PARTYVINFO>) <octet string>
An optional octet string containing public info contributed by the responder.
=item "supp-pubinfo" (B<OSSL_KDF_PARAM_X942_SUPP_PUBINFO>) <octet string>
An optional octet string containing some additional, mutually-known public
information. Setting this value also sets "use-keybits" to 0.
=item "use-keybits" (B<OSSL_KDF_PARAM_X942_USE_KEYBITS>) <integer>
The default value of 1 will use the KEK key length (in bits) as the
"supp-pubinfo". A value of 0 disables setting the "supp-pubinfo".
=item "supp-privinfo" (B<OSSL_KDF_PARAM_X942_SUPP_PRIVINFO>) <octet string>
An optional octet string containing some additional, mutually-known private
information.
=item "cekalg" (B<OSSL_KDF_PARAM_CEK_ALG>) <UTF8 string>
This parameter sets the CEK wrapping algorithm name.
Valid values are "AES-128-WRAP", "AES-192-WRAP", "AES-256-WRAP" and "DES3-WRAP".
=back
=head1 NOTES
A context for X942KDF can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "X942KDF", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The output length of an X942KDF is specified via the I<keylen>
parameter to the L<EVP_KDF_derive(3)> function.
=head1 EXAMPLES
This example derives 24 bytes, with the secret key "secret" and random user
keying material:
EVP_KDF_CTX *kctx;
EVP_KDF_CTX *kctx;
unsigned char out[192/8];
unsignred char ukm[64];
OSSL_PARAM params[5], *p = params;
if (RAND_bytes(ukm, sizeof(ukm)) <= 0)
error("RAND_bytes");
kdf = EVP_KDF_fetch(NULL, "X942KDF", NULL);
if (kctx == NULL)
error("EVP_KDF_fetch");
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
if (kctx == NULL)
error("EVP_KDF_CTX_new");
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, "SHA256", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
"secret", (size_t)6);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_UKM, ukm, sizeof(ukm));
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CEK_ALG, "AES-256-WRAP, 0);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0)
error("EVP_KDF_derive");
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
ANS1 X9.42-2003
RFC 2631
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_CTX_get_kdf_size(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_KDF-X963.pod b/crypto/openssl/doc/man7/EVP_KDF-X963.pod
index 3d6f4372cf31..ca2f7c1df0ef 100644
--- a/crypto/openssl/doc/man7/EVP_KDF-X963.pod
+++ b/crypto/openssl/doc/man7/EVP_KDF-X963.pod
@@ -1,108 +1,110 @@
=pod
=head1 NAME
EVP_KDF-X963 - The X9.63-2001 EVP_KDF implementation
=head1 DESCRIPTION
The EVP_KDF-X963 algorithm implements the key derivation function (X963KDF).
X963KDF is used by Cryptographic Message Syntax (CMS) for EC KeyAgreement, to
derive a key using input such as a shared secret key and shared info.
+The output is considered to be keying material.
+
=head2 Identity
"X963KDF" is the name for this implementation; it
can be used with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
The shared secret used for key derivation.
This parameter sets the secret.
=item "info" (B<OSSL_KDF_PARAM_INFO>) <octet string>
This parameter specifies an optional value for shared info.
=back
=head1 NOTES
X963KDF is very similar to the SSKDF that uses a digest as the auxiliary function,
X963KDF appends the counter to the secret, whereas SSKDF prepends the counter.
A context for X963KDF can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "X963KDF", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The output length of an X963KDF is specified via the I<keylen>
parameter to the L<EVP_KDF_derive(3)> function.
=head1 EXAMPLES
This example derives 10 bytes, with the secret key "secret" and sharedinfo
value "label":
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
OSSL_PARAM params[4], *p = params;
kdf = EVP_KDF_fetch(NULL, "X963KDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
SN_sha256, strlen(SN_sha256));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
"secret", (size_t)6);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
"label", (size_t)5);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
"SEC 1: Elliptic Curve Cryptography"
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_CTX_get_kdf_size(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/EVP_SIGNATURE-DSA.pod b/crypto/openssl/doc/man7/EVP_SIGNATURE-DSA.pod
index 5a42d6b1cd22..326a86ee0b42 100644
--- a/crypto/openssl/doc/man7/EVP_SIGNATURE-DSA.pod
+++ b/crypto/openssl/doc/man7/EVP_SIGNATURE-DSA.pod
@@ -1,58 +1,60 @@
=pod
=head1 NAME
EVP_SIGNATURE-DSA
- The B<EVP_PKEY> DSA signature implementation
=head1 DESCRIPTION
-Support for computing DSA signatures.
+Support for computing DSA signatures. The signature produced with
+L<EVP_PKEY_sign(3)> is DER encoded ASN.1 in the form described in
+RFC 3279, section 2.2.2.
See L<EVP_PKEY-DSA(7)> for information related to DSA keys.
=head2 Signature Parameters
The following signature parameters can be set using EVP_PKEY_CTX_set_params().
This may be called after EVP_PKEY_sign_init() or EVP_PKEY_verify_init(),
and before calling EVP_PKEY_sign() or EVP_PKEY_verify().
=over 4
=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
=item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string>
The settable parameters are described in L<provider-signature(7)>.
=back
The following signature parameters can be retrieved using
EVP_PKEY_CTX_get_params().
=over 4
=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
The gettable parameters are described in L<provider-signature(7)>.
=back
=head1 SEE ALSO
L<EVP_PKEY_CTX_set_params(3)>,
L<EVP_PKEY_sign(3)>,
L<EVP_PKEY_verify(3)>,
L<provider-signature(7)>,
=head1 COPYRIGHT
Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/openssl-env.pod b/crypto/openssl/doc/man7/openssl-env.pod
index a2443d54d822..c7dbd2277dc6 100644
--- a/crypto/openssl/doc/man7/openssl-env.pod
+++ b/crypto/openssl/doc/man7/openssl-env.pod
@@ -1,101 +1,194 @@
=pod
=head1 NAME
openssl-env - OpenSSL environment variables
=head1 DESCRIPTION
The OpenSSL libraries use environment variables to override the
compiled-in default paths for various data.
To avoid security risks, the environment is usually not consulted when
the executable is set-user-ID or set-group-ID.
=over 4
=item B<CTLOG_FILE>
Specifies the path to a certificate transparency log list.
See L<CTLOG_STORE_new(3)>.
=item B<OPENSSL>
Specifies the path to the B<openssl> executable. Used by
the B<rehash> script (see L<openssl-rehash(1)/Script Configuration>)
and by the B<CA.pl> script (see L<CA.pl(1)/NOTES>
=item B<OPENSSL_CONF>, B<OPENSSL_CONF_INCLUDE>
Specifies the path to a configuration file and the directory for
included files.
See L<config(5)>.
=item B<OPENSSL_CONFIG>
Specifies a configuration option and filename for the B<req> and B<ca>
commands invoked by the B<CA.pl> script.
See L<CA.pl(1)>.
=item B<OPENSSL_ENGINES>
Specifies the directory from which dynamic engines are loaded.
See L<openssl-engine(1)>.
=item B<OPENSSL_MALLOC_FD>, B<OPENSSL_MALLOC_FAILURES>
If built with debugging, this allows memory allocation to fail.
See L<OPENSSL_malloc(3)>.
=item B<OPENSSL_MODULES>
Specifies the directory from which cryptographic providers are loaded.
Equivalently, the generic B<-provider-path> command-line option may be used.
+=item B<OPENSSL_TRACE>
+
+By default the OpenSSL trace feature is disabled statically.
+To enable it, OpenSSL must be built with tracing support,
+which may be configured like this: C<./config enable-trace>
+
+Unless OpenSSL tracing support is generally disabled,
+enable trace output of specific parts of OpenSSL libraries, by name.
+This output usually makes sense only if you know OpenSSL internals well.
+
+The value of this environment varialble is a comma-separated list of names,
+with the following available:
+
+=over 4
+
+=item B<TRACE>
+
+Traces the OpenSSL trace API itself.
+
+=item B<INIT>
+
+Traces OpenSSL library initialization and cleanup.
+
+=item B<TLS>
+
+Traces the TLS/SSL protocol.
+
+=item B<TLS_CIPHER>
+
+Traces the ciphers used by the TLS/SSL protocol.
+
+=item B<CONF>
+
+Show details about provider and engine configuration.
+
+=item B<ENGINE_TABLE>
+
+The function that is used by RSA, DSA (etc) code to select registered
+ENGINEs, cache defaults and functional references (etc), will generate
+debugging summaries.
+
+=item B<ENGINE_REF_COUNT>
+
+Reference counts in the ENGINE structure will be monitored with a line
+of generated for each change.
+
+=item B<PKCS5V2>
+
+Traces PKCS#5 v2 key generation.
+
+=item B<PKCS12_KEYGEN>
+
+Traces PKCS#12 key generation.
+
+=item B<PKCS12_DECRYPT>
+
+Traces PKCS#12 decryption.
+
+=item B<X509V3_POLICY>
+
+Generates the complete policy tree at various points during X.509 v3
+policy evaluation.
+
+=item B<BN_CTX>
+
+Traces BIGNUM context operations.
+
+=item B<CMP>
+
+Traces CMP client and server activity.
+
+=item B<STORE>
+
+Traces STORE operations.
+
+=item B<DECODER>
+
+Traces decoder operations.
+
+=item B<ENCODER>
+
+Traces encoder operations.
+
+=item B<REF_COUNT>
+
+Traces decrementing certain ASN.1 structure references.
+
+=item B<HTTP>
+
+Traces the HTTP client and server, such as messages being sent and received.
+
+=back
+
=item B<OPENSSL_WIN32_UTF8>
If set, then L<UI_OpenSSL(3)> returns UTF-8 encoded strings, rather than
ones encoded in the current code page, and
the L<openssl(1)> program also transcodes the command-line parameters
from the current code page to UTF-8.
This environment variable is only checked on Microsoft Windows platforms.
=item B<RANDFILE>
The state file for the random number generator.
This should not be needed in normal use.
See L<RAND_load_file(3)>.
=item B<SSL_CERT_DIR>, B<SSL_CERT_FILE>
Specify the default directory or file containing CA certificates.
See L<SSL_CTX_load_verify_locations(3)>.
=item B<TSGET>
Additional arguments for the L<tsget(1)> command.
=item B<OPENSSL_ia32cap>, B<OPENSSL_sparcv9cap>, B<OPENSSL_ppccap>, B<OPENSSL_armcap>, B<OPENSSL_s390xcap>
OpenSSL supports a number of different algorithm implementations for
various machines and, by default, it determines which to use based on the
processor capabilities and run time feature enquiry. These environment
variables can be used to exert more control over this selection process.
See L<OPENSSL_ia32cap(3)>, L<OPENSSL_s390xcap(3)>.
=item B<NO_PROXY>, B<HTTPS_PROXY>, B<HTTP_PROXY>
Specify a proxy hostname.
See L<OSSL_HTTP_parse_url(3)>.
=back
=head1 COPYRIGHT
Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/doc/man7/provider.pod b/crypto/openssl/doc/man7/provider.pod
index a061fc4709d0..08ac1d02907f 100644
--- a/crypto/openssl/doc/man7/provider.pod
+++ b/crypto/openssl/doc/man7/provider.pod
@@ -1,264 +1,276 @@
=pod
=head1 NAME
provider - OpenSSL operation implementation providers
=head1 SYNOPSIS
=for openssl generic
#include <openssl/provider.h>
=head1 DESCRIPTION
=head2 General
This page contains information useful to provider authors.
A I<provider>, in OpenSSL terms, is a unit of code that provides one
or more implementations for various operations for diverse algorithms
that one might want to perform.
An I<operation> is something one wants to do, such as encryption and
decryption, key derivation, MAC calculation, signing and verification,
etc.
An I<algorithm> is a named method to perform an operation.
Very often, the algorithms revolve around cryptographic operations,
but may also revolve around other types of operation, such as managing
certain types of objects.
See L<crypto(7)> for further details.
=head2 Provider
A I<provider> offers an initialization function, as a set of base
functions in the form of an L<OSSL_DISPATCH(3)> array, and by extension,
a set of L<OSSL_ALGORITHM(3)>s (see L<openssl-core.h(7)>).
It may be a dynamically loadable module, or may be built-in, in
OpenSSL libraries or in the application.
If it's a dynamically loadable module, the initialization function
must be named C<OSSL_provider_init> and must be exported.
If it's built-in, the initialization function may have any name.
The initialization function must have the following signature:
int NAME(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *in, const OSSL_DISPATCH **out,
void **provctx);
I<handle> is the OpenSSL library object for the provider, and works
as a handle for everything the OpenSSL libraries need to know about
the provider.
For the provider itself, it is passed to some of the functions given in the
dispatch array I<in>.
I<in> is a dispatch array of base functions offered by the OpenSSL
libraries, and the available functions are further described in
L<provider-base(7)>.
I<*out> must be assigned a dispatch array of base functions that the
provider offers to the OpenSSL libraries.
The functions that may be offered are further described in
L<provider-base(7)>, and they are the central means of communication
between the OpenSSL libraries and the provider.
I<*provctx> should be assigned a provider specific context to allow
the provider multiple simultaneous uses.
This pointer will be passed to various operation functions offered by
the provider.
Note that the provider will not be made available for applications to use until
the initialization function has completed and returned successfully.
One of the functions the provider offers to the OpenSSL libraries is
the central mechanism for the OpenSSL libraries to get access to
operation implementations for diverse algorithms.
Its referred to with the number B<OSSL_FUNC_PROVIDER_QUERY_OPERATION>
and has the following signature:
const OSSL_ALGORITHM *provider_query_operation(void *provctx,
int operation_id,
const int *no_store);
I<provctx> is the provider specific context that was passed back by
the initialization function.
I<operation_id> is an operation identity (see L</Operations> below).
I<no_store> is a flag back to the OpenSSL libraries which, when
nonzero, signifies that the OpenSSL libraries will not store a
reference to the returned data in their internal store of
implementations.
The returned L<OSSL_ALGORITHM(3)> is the foundation of any OpenSSL
library API that uses providers for their implementation, most
commonly in the I<fetching> type of functions
(see L<crypto(7)/ALGORITHM FETCHING>).
=head2 Operations
Operations are referred to with numbers, via macros with names
starting with C<OSSL_OP_>.
With each operation comes a set of defined function types that a
provider may or may not offer, depending on its needs.
Currently available operations are:
=over 4
=item Digests
In the OpenSSL libraries, the corresponding method object is
B<EVP_MD>.
The number for this operation is B<OSSL_OP_DIGEST>.
The functions the provider can offer are described in
L<provider-digest(7)>.
=item Symmetric ciphers
In the OpenSSL libraries, the corresponding method object is
B<EVP_CIPHER>.
The number for this operation is B<OSSL_OP_CIPHER>.
The functions the provider can offer are described in
L<provider-cipher(7)>.
=item Message Authentication Code (MAC)
In the OpenSSL libraries, the corresponding method object is
B<EVP_MAC>.
The number for this operation is B<OSSL_OP_MAC>.
The functions the provider can offer are described in
L<provider-mac(7)>.
=item Key Derivation Function (KDF)
In the OpenSSL libraries, the corresponding method object is
B<EVP_KDF>.
The number for this operation is B<OSSL_OP_KDF>.
The functions the provider can offer are described in
L<provider-kdf(7)>.
=item Key Exchange
In the OpenSSL libraries, the corresponding method object is
B<EVP_KEYEXCH>.
The number for this operation is B<OSSL_OP_KEYEXCH>.
The functions the provider can offer are described in
L<provider-keyexch(7)>.
=item Asymmetric Ciphers
In the OpenSSL libraries, the corresponding method object is
B<EVP_ASYM_CIPHER>.
The number for this operation is B<OSSL_OP_ASYM_CIPHER>.
The functions the provider can offer are described in
L<provider-asym_cipher(7)>.
=item Asymmetric Key Encapsulation
In the OpenSSL libraries, the corresponding method object is B<EVP_KEM>.
The number for this operation is B<OSSL_OP_KEM>.
The functions the provider can offer are described in L<provider-kem(7)>.
=item Encoding
In the OpenSSL libraries, the corresponding method object is
B<OSSL_ENCODER>.
The number for this operation is B<OSSL_OP_ENCODER>.
The functions the provider can offer are described in
L<provider-encoder(7)>.
=item Decoding
In the OpenSSL libraries, the corresponding method object is
B<OSSL_DECODER>.
The number for this operation is B<OSSL_OP_DECODER>.
The functions the provider can offer are described in
L<provider-decoder(7)>.
=item Random Number Generation
The number for this operation is B<OSSL_OP_RAND>.
The functions the provider can offer for random number generation are described
in L<provider-rand(7)>.
=item Key Management
The number for this operation is B<OSSL_OP_KEYMGMT>.
The functions the provider can offer for key management are described in
L<provider-keymgmt(7)>.
=item Signing and Signature Verification
The number for this operation is B<OSSL_OP_SIGNATURE>.
The functions the provider can offer for digital signatures are described in
L<provider-signature(7)>.
=item Store Management
The number for this operation is B<OSSL_OP_STORE>.
The functions the provider can offer for store management are described in
L<provider-storemgmt(7)>.
=back
=head3 Algorithm naming
Algorithm names are case insensitive. Any particular algorithm can have multiple
aliases associated with it. The canonical OpenSSL naming scheme follows this
format:
ALGNAME[VERSION?][-SUBNAME[VERSION?]?][-SIZE?][-MODE?]
VERSION is only present if there are multiple versions of an algorithm (e.g.
MD2, MD4, MD5). It may be omitted if there is only one version.
SUBNAME may be present where multiple algorithms are combined together,
e.g. MD5-SHA1.
SIZE is only present if multiple versions of an algorithm exist with different
sizes (e.g. AES-128-CBC, AES-256-CBC)
MODE is only present where applicable.
Other aliases may exist for example where standards bodies or common practice
use alternative names or names that OpenSSL has used historically.
+=head3 Provider dependencies
+
+Providers may depend for their proper operation on the availability of
+(functionality implemented in) other providers. As there is no mechanism to
+express such dependencies towards the OpenSSL core, provider authors must
+take care that such dependencies are either completely avoided or made visible
+to users, e.g., by documentation and/or defensive programming, e.g.,
+outputting error messages if required external dependencies are not available,
+e.g., when no provider implementing the required functionality has been
+activated. In particular, provider initialization should not depend on other
+providers already having been initialized.
+
=head1 OPENSSL PROVIDERS
OpenSSL provides a number of its own providers. These are the default, base,
fips, legacy and null providers. See L<crypto(7)> for an overview of these
providers.
=head1 SEE ALSO
L<EVP_DigestInit_ex(3)>, L<EVP_EncryptInit_ex(3)>,
L<OSSL_LIB_CTX(3)>,
L<EVP_set_default_properties(3)>,
L<EVP_MD_fetch(3)>,
L<EVP_CIPHER_fetch(3)>,
L<EVP_KEYMGMT_fetch(3)>,
L<openssl-core.h(7)>,
L<provider-base(7)>,
L<provider-digest(7)>,
L<provider-cipher(7)>,
L<provider-keyexch(7)>
=head1 HISTORY
The concept of providers and everything surrounding them was
introduced in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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/crypto/openssl/engines/e_afalg.c b/crypto/openssl/engines/e_afalg.c
index ec4e21c582c8..58d58ef24ec4 100644
--- a/crypto/openssl/engines/e_afalg.c
+++ b/crypto/openssl/engines/e_afalg.c
@@ -1,935 +1,935 @@
/*
- * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* We need to use some deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
/* Required for vmsplice */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <openssl/engine.h>
#include <openssl/async.h>
#include <openssl/err.h>
#include "internal/nelem.h"
#include <sys/socket.h>
#include <linux/version.h>
#define K_MAJ 4
#define K_MIN1 1
#define K_MIN2 0
#if LINUX_VERSION_CODE < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2) || \
!defined(AF_ALG)
# ifndef PEDANTIC
# warning "AFALG ENGINE requires Kernel Headers >= 4.1.0"
# warning "Skipping Compilation of AFALG engine"
# endif
void engine_load_afalg_int(void);
void engine_load_afalg_int(void)
{
}
#else
# include <linux/if_alg.h>
# include <fcntl.h>
# include <sys/utsname.h>
# include <linux/aio_abi.h>
# include <sys/syscall.h>
# include <errno.h>
# include "e_afalg.h"
# include "e_afalg_err.c"
# ifndef SOL_ALG
# define SOL_ALG 279
# endif
# ifdef ALG_ZERO_COPY
# ifndef SPLICE_F_GIFT
# define SPLICE_F_GIFT (0x08)
# endif
# endif
# define ALG_AES_IV_LEN 16
# define ALG_IV_LEN(len) (sizeof(struct af_alg_iv) + (len))
# define ALG_OP_TYPE unsigned int
# define ALG_OP_LEN (sizeof(ALG_OP_TYPE))
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
void engine_load_afalg_int(void);
# endif
/* Local Linkage Functions */
static int afalg_init_aio(afalg_aio *aio);
static int afalg_fin_cipher_aio(afalg_aio *ptr, int sfd,
unsigned char *buf, size_t len);
static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype,
const char *ciphername);
static int afalg_destroy(ENGINE *e);
static int afalg_init(ENGINE *e);
static int afalg_finish(ENGINE *e);
static const EVP_CIPHER *afalg_aes_cbc(int nid);
static cbc_handles *get_cipher_handle(int nid);
static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl);
static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx);
static int afalg_chk_platform(void);
/* Engine Id and Name */
static const char *engine_afalg_id = "afalg";
static const char *engine_afalg_name = "AFALG engine support";
static int afalg_cipher_nids[] = {
NID_aes_128_cbc,
NID_aes_192_cbc,
NID_aes_256_cbc,
};
static cbc_handles cbc_handle[] = {{AES_KEY_SIZE_128, NULL},
{AES_KEY_SIZE_192, NULL},
{AES_KEY_SIZE_256, NULL}};
static ossl_inline int io_setup(unsigned n, aio_context_t *ctx)
{
return syscall(__NR_io_setup, n, ctx);
}
static ossl_inline int eventfd(int n)
{
return syscall(__NR_eventfd2, n, 0);
}
static ossl_inline int io_destroy(aio_context_t ctx)
{
return syscall(__NR_io_destroy, ctx);
}
static ossl_inline int io_read(aio_context_t ctx, long n, struct iocb **iocb)
{
return syscall(__NR_io_submit, ctx, n, iocb);
}
/* A version of 'struct timespec' with 32-bit time_t and nanoseconds. */
struct __timespec32
{
__kernel_long_t tv_sec;
__kernel_long_t tv_nsec;
};
static ossl_inline int io_getevents(aio_context_t ctx, long min, long max,
struct io_event *events,
struct timespec *timeout)
{
#if defined(__NR_io_pgetevents_time64)
/* Check if we are a 32-bit architecture with a 64-bit time_t */
if (sizeof(*timeout) != sizeof(struct __timespec32)) {
int ret = syscall(__NR_io_pgetevents_time64, ctx, min, max, events,
timeout, NULL);
if (ret == 0 || errno != ENOSYS)
return ret;
}
#endif
#if defined(__NR_io_getevents)
if (sizeof(*timeout) == sizeof(struct __timespec32))
/*
* time_t matches our architecture length, we can just use
* __NR_io_getevents
*/
return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
else {
/*
* We don't have __NR_io_pgetevents_time64, but we are using a
* 64-bit time_t on a 32-bit architecture. If we can fit the
* timeout value in a 32-bit time_t, then let's do that
* and then use the __NR_io_getevents syscall.
*/
if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
struct __timespec32 ts32;
ts32.tv_sec = (__kernel_long_t) timeout->tv_sec;
ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
- return syscall(__NR_io_getevents, ctx, min, max, events, ts32);
+ return syscall(__NR_io_getevents, ctx, min, max, events, &ts32);
} else {
return syscall(__NR_io_getevents, ctx, min, max, events, NULL);
}
}
#endif
errno = ENOSYS;
return -1;
}
static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
OSSL_ASYNC_FD waitfd, void *custom)
{
close(waitfd);
}
static int afalg_setup_async_event_notification(afalg_aio *aio)
{
ASYNC_JOB *job;
ASYNC_WAIT_CTX *waitctx;
void *custom = NULL;
int ret;
if ((job = ASYNC_get_current_job()) != NULL) {
/* Async mode */
waitctx = ASYNC_get_wait_ctx(job);
if (waitctx == NULL) {
ALG_WARN("%s(%d): ASYNC_get_wait_ctx error", __FILE__, __LINE__);
return 0;
}
/* Get waitfd from ASYNC_WAIT_CTX if it is already set */
ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_afalg_id,
&aio->efd, &custom);
if (ret == 0) {
/*
* waitfd is not set in ASYNC_WAIT_CTX, create a new one
* and set it. efd will be signaled when AIO operation completes
*/
aio->efd = eventfd(0);
if (aio->efd == -1) {
ALG_PERR("%s(%d): Failed to get eventfd : ", __FILE__,
__LINE__);
AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION,
AFALG_R_EVENTFD_FAILED);
return 0;
}
ret = ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_afalg_id,
aio->efd, custom,
afalg_waitfd_cleanup);
if (ret == 0) {
ALG_WARN("%s(%d): Failed to set wait fd", __FILE__, __LINE__);
close(aio->efd);
return 0;
}
/* make fd non-blocking in async mode */
if (fcntl(aio->efd, F_SETFL, O_NONBLOCK) != 0) {
ALG_WARN("%s(%d): Failed to set event fd as NONBLOCKING",
__FILE__, __LINE__);
}
}
aio->mode = MODE_ASYNC;
} else {
/* Sync mode */
aio->efd = eventfd(0);
if (aio->efd == -1) {
ALG_PERR("%s(%d): Failed to get eventfd : ", __FILE__, __LINE__);
AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION,
AFALG_R_EVENTFD_FAILED);
return 0;
}
aio->mode = MODE_SYNC;
}
return 1;
}
static int afalg_init_aio(afalg_aio *aio)
{
int r = -1;
/* Initialise for AIO */
aio->aio_ctx = 0;
r = io_setup(MAX_INFLIGHTS, &aio->aio_ctx);
if (r < 0) {
ALG_PERR("%s(%d): io_setup error : ", __FILE__, __LINE__);
AFALGerr(AFALG_F_AFALG_INIT_AIO, AFALG_R_IO_SETUP_FAILED);
return 0;
}
memset(aio->cbt, 0, sizeof(aio->cbt));
aio->efd = -1;
aio->mode = MODE_UNINIT;
return 1;
}
static int afalg_fin_cipher_aio(afalg_aio *aio, int sfd, unsigned char *buf,
size_t len)
{
int r;
int retry = 0;
unsigned int done = 0;
struct iocb *cb;
struct timespec timeout;
struct io_event events[MAX_INFLIGHTS];
u_int64_t eval = 0;
timeout.tv_sec = 0;
timeout.tv_nsec = 0;
/* if efd has not been initialised yet do it here */
if (aio->mode == MODE_UNINIT) {
r = afalg_setup_async_event_notification(aio);
if (r == 0)
return 0;
}
cb = &(aio->cbt[0 % MAX_INFLIGHTS]);
memset(cb, '\0', sizeof(*cb));
cb->aio_fildes = sfd;
cb->aio_lio_opcode = IOCB_CMD_PREAD;
/*
* The pointer has to be converted to unsigned value first to avoid
* sign extension on cast to 64 bit value in 32-bit builds
*/
cb->aio_buf = (size_t)buf;
cb->aio_offset = 0;
cb->aio_data = 0;
cb->aio_nbytes = len;
cb->aio_flags = IOCB_FLAG_RESFD;
cb->aio_resfd = aio->efd;
/*
* Perform AIO read on AFALG socket, this in turn performs an async
* crypto operation in kernel space
*/
r = io_read(aio->aio_ctx, 1, &cb);
if (r < 0) {
ALG_PWARN("%s(%d): io_read failed : ", __FILE__, __LINE__);
return 0;
}
do {
/* While AIO read is being performed pause job */
ASYNC_pause_job();
/* Check for completion of AIO read */
r = read(aio->efd, &eval, sizeof(eval));
if (r < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
continue;
ALG_PERR("%s(%d): read failed for event fd : ", __FILE__, __LINE__);
return 0;
} else if (r == 0 || eval <= 0) {
ALG_WARN("%s(%d): eventfd read %d bytes, eval = %lu\n", __FILE__,
__LINE__, r, eval);
}
if (eval > 0) {
#ifdef OSSL_SANITIZE_MEMORY
/*
* In a memory sanitiser build, the changes to memory made by the
* system call aren't reliably detected. By initialising the
* memory here, the sanitiser is told that they are okay.
*/
memset(events, 0, sizeof(events));
#endif
/* Get results of AIO read */
r = io_getevents(aio->aio_ctx, 1, MAX_INFLIGHTS,
events, &timeout);
if (r > 0) {
/*
* events.res indicates the actual status of the operation.
* Handle the error condition first.
*/
if (events[0].res < 0) {
/*
* Underlying operation cannot be completed at the time
* of previous submission. Resubmit for the operation.
*/
if (events[0].res == -EBUSY && retry++ < 3) {
r = io_read(aio->aio_ctx, 1, &cb);
if (r < 0) {
ALG_PERR("%s(%d): retry %d for io_read failed : ",
__FILE__, __LINE__, retry);
return 0;
}
continue;
} else {
/*
* Retries exceed for -EBUSY or unrecoverable error
* condition for this instance of operation.
*/
ALG_WARN
("%s(%d): Crypto Operation failed with code %lld\n",
__FILE__, __LINE__, events[0].res);
return 0;
}
}
/* Operation successful. */
done = 1;
} else if (r < 0) {
ALG_PERR("%s(%d): io_getevents failed : ", __FILE__, __LINE__);
return 0;
} else {
ALG_WARN("%s(%d): io_geteventd read 0 bytes\n", __FILE__,
__LINE__);
}
}
} while (!done);
return 1;
}
static ossl_inline void afalg_set_op_sk(struct cmsghdr *cmsg,
const ALG_OP_TYPE op)
{
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_OP;
cmsg->cmsg_len = CMSG_LEN(ALG_OP_LEN);
memcpy(CMSG_DATA(cmsg), &op, ALG_OP_LEN);
}
static void afalg_set_iv_sk(struct cmsghdr *cmsg, const unsigned char *iv,
const unsigned int len)
{
struct af_alg_iv *aiv;
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_IV;
cmsg->cmsg_len = CMSG_LEN(ALG_IV_LEN(len));
aiv = (struct af_alg_iv *)CMSG_DATA(cmsg);
aiv->ivlen = len;
memcpy(aiv->iv, iv, len);
}
static ossl_inline int afalg_set_key(afalg_ctx *actx, const unsigned char *key,
const int klen)
{
int ret;
ret = setsockopt(actx->bfd, SOL_ALG, ALG_SET_KEY, key, klen);
if (ret < 0) {
ALG_PERR("%s(%d): Failed to set socket option : ", __FILE__, __LINE__);
AFALGerr(AFALG_F_AFALG_SET_KEY, AFALG_R_SOCKET_SET_KEY_FAILED);
return 0;
}
return 1;
}
static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype,
const char *ciphername)
{
struct sockaddr_alg sa;
int r = -1;
actx->bfd = actx->sfd = -1;
memset(&sa, 0, sizeof(sa));
sa.salg_family = AF_ALG;
OPENSSL_strlcpy((char *) sa.salg_type, ciphertype, sizeof(sa.salg_type));
OPENSSL_strlcpy((char *) sa.salg_name, ciphername, sizeof(sa.salg_name));
actx->bfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (actx->bfd == -1) {
ALG_PERR("%s(%d): Failed to open socket : ", __FILE__, __LINE__);
AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_CREATE_FAILED);
goto err;
}
r = bind(actx->bfd, (struct sockaddr *)&sa, sizeof(sa));
if (r < 0) {
ALG_PERR("%s(%d): Failed to bind socket : ", __FILE__, __LINE__);
AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_BIND_FAILED);
goto err;
}
actx->sfd = accept(actx->bfd, NULL, 0);
if (actx->sfd < 0) {
ALG_PERR("%s(%d): Socket Accept Failed : ", __FILE__, __LINE__);
AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_ACCEPT_FAILED);
goto err;
}
return 1;
err:
if (actx->bfd >= 0)
close(actx->bfd);
if (actx->sfd >= 0)
close(actx->sfd);
actx->bfd = actx->sfd = -1;
return 0;
}
static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in,
size_t inl, const unsigned char *iv,
unsigned int enc)
{
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
ssize_t sbytes;
# ifdef ALG_ZERO_COPY
int ret;
# endif
char cbuf[CMSG_SPACE(ALG_IV_LEN(ALG_AES_IV_LEN)) + CMSG_SPACE(ALG_OP_LEN)];
memset(&msg, 0, sizeof(msg));
memset(cbuf, 0, sizeof(cbuf));
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
/*
* cipher direction (i.e. encrypt or decrypt) and iv are sent to the
* kernel as part of sendmsg()'s ancillary data
*/
cmsg = CMSG_FIRSTHDR(&msg);
afalg_set_op_sk(cmsg, enc);
cmsg = CMSG_NXTHDR(&msg, cmsg);
afalg_set_iv_sk(cmsg, iv, ALG_AES_IV_LEN);
/* iov that describes input data */
iov.iov_base = (unsigned char *)in;
iov.iov_len = inl;
msg.msg_flags = MSG_MORE;
# ifdef ALG_ZERO_COPY
/*
* ZERO_COPY mode
* Works best when buffer is 4k aligned
* OPENS: out of place processing (i.e. out != in)
*/
/* Input data is not sent as part of call to sendmsg() */
msg.msg_iovlen = 0;
msg.msg_iov = NULL;
/* Sendmsg() sends iv and cipher direction to the kernel */
sbytes = sendmsg(actx->sfd, &msg, 0);
if (sbytes < 0) {
ALG_PERR("%s(%d): sendmsg failed for zero copy cipher operation : ",
__FILE__, __LINE__);
return 0;
}
/*
* vmsplice and splice are used to pin the user space input buffer for
* kernel space processing avoiding copies from user to kernel space
*/
ret = vmsplice(actx->zc_pipe[1], &iov, 1, SPLICE_F_GIFT);
if (ret < 0) {
ALG_PERR("%s(%d): vmsplice failed : ", __FILE__, __LINE__);
return 0;
}
ret = splice(actx->zc_pipe[0], NULL, actx->sfd, NULL, inl, 0);
if (ret < 0) {
ALG_PERR("%s(%d): splice failed : ", __FILE__, __LINE__);
return 0;
}
# else
msg.msg_iovlen = 1;
msg.msg_iov = &iov;
/* Sendmsg() sends iv, cipher direction and input data to the kernel */
sbytes = sendmsg(actx->sfd, &msg, 0);
if (sbytes < 0) {
ALG_PERR("%s(%d): sendmsg failed for cipher operation : ", __FILE__,
__LINE__);
return 0;
}
if (sbytes != (ssize_t) inl) {
ALG_WARN("Cipher operation send bytes %zd != inlen %zd\n", sbytes,
inl);
return 0;
}
# endif
return 1;
}
static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ciphertype;
int ret, len;
afalg_ctx *actx;
const char *ciphername;
if (ctx == NULL || key == NULL) {
ALG_WARN("%s(%d): Null Parameter\n", __FILE__, __LINE__);
return 0;
}
if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) {
ALG_WARN("%s(%d): Cipher object NULL\n", __FILE__, __LINE__);
return 0;
}
actx = EVP_CIPHER_CTX_get_cipher_data(ctx);
if (actx == NULL) {
ALG_WARN("%s(%d): Cipher data NULL\n", __FILE__, __LINE__);
return 0;
}
ciphertype = EVP_CIPHER_CTX_get_nid(ctx);
switch (ciphertype) {
case NID_aes_128_cbc:
case NID_aes_192_cbc:
case NID_aes_256_cbc:
ciphername = "cbc(aes)";
break;
default:
ALG_WARN("%s(%d): Unsupported Cipher type %d\n", __FILE__, __LINE__,
ciphertype);
return 0;
}
if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_get_iv_length(ctx)) {
ALG_WARN("%s(%d): Unsupported IV length :%d\n", __FILE__, __LINE__,
EVP_CIPHER_CTX_get_iv_length(ctx));
return 0;
}
/* Setup AFALG socket for crypto processing */
ret = afalg_create_sk(actx, "skcipher", ciphername);
if (ret < 1)
return 0;
if ((len = EVP_CIPHER_CTX_get_key_length(ctx)) <= 0)
goto err;
ret = afalg_set_key(actx, key, len);
if (ret < 1)
goto err;
/* Setup AIO ctx to allow async AFALG crypto processing */
if (afalg_init_aio(&actx->aio) == 0)
goto err;
# ifdef ALG_ZERO_COPY
pipe(actx->zc_pipe);
# endif
actx->init_done = MAGIC_INIT_NUM;
return 1;
err:
close(actx->sfd);
close(actx->bfd);
return 0;
}
static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
afalg_ctx *actx;
int ret;
char nxtiv[ALG_AES_IV_LEN] = { 0 };
if (ctx == NULL || out == NULL || in == NULL) {
ALG_WARN("NULL parameter passed to function %s(%d)\n", __FILE__,
__LINE__);
return 0;
}
actx = (afalg_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
if (actx == NULL || actx->init_done != MAGIC_INIT_NUM) {
ALG_WARN("%s afalg ctx passed\n",
ctx == NULL ? "NULL" : "Uninitialised");
return 0;
}
/*
* set iv now for decrypt operation as the input buffer can be
* overwritten for inplace operation where in = out.
*/
if (EVP_CIPHER_CTX_is_encrypting(ctx) == 0) {
memcpy(nxtiv, in + (inl - ALG_AES_IV_LEN), ALG_AES_IV_LEN);
}
/* Send input data to kernel space */
ret = afalg_start_cipher_sk(actx, (unsigned char *)in, inl,
EVP_CIPHER_CTX_iv(ctx),
EVP_CIPHER_CTX_is_encrypting(ctx));
if (ret < 1) {
return 0;
}
/* Perform async crypto operation in kernel space */
ret = afalg_fin_cipher_aio(&actx->aio, actx->sfd, out, inl);
if (ret < 1)
return 0;
if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), out + (inl - ALG_AES_IV_LEN),
ALG_AES_IV_LEN);
} else {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), nxtiv, ALG_AES_IV_LEN);
}
return 1;
}
static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx)
{
afalg_ctx *actx;
if (ctx == NULL) {
ALG_WARN("NULL parameter passed to function %s(%d)\n", __FILE__,
__LINE__);
return 0;
}
actx = (afalg_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
if (actx == NULL || actx->init_done != MAGIC_INIT_NUM)
return 1;
close(actx->sfd);
close(actx->bfd);
# ifdef ALG_ZERO_COPY
close(actx->zc_pipe[0]);
close(actx->zc_pipe[1]);
# endif
/* close efd in sync mode, async mode is closed in afalg_waitfd_cleanup() */
if (actx->aio.mode == MODE_SYNC)
close(actx->aio.efd);
io_destroy(actx->aio.aio_ctx);
return 1;
}
static cbc_handles *get_cipher_handle(int nid)
{
switch (nid) {
case NID_aes_128_cbc:
return &cbc_handle[AES_CBC_128];
case NID_aes_192_cbc:
return &cbc_handle[AES_CBC_192];
case NID_aes_256_cbc:
return &cbc_handle[AES_CBC_256];
default:
return NULL;
}
}
static const EVP_CIPHER *afalg_aes_cbc(int nid)
{
cbc_handles *cipher_handle = get_cipher_handle(nid);
if (cipher_handle == NULL)
return NULL;
if (cipher_handle->_hidden == NULL
&& ((cipher_handle->_hidden =
EVP_CIPHER_meth_new(nid,
AES_BLOCK_SIZE,
cipher_handle->key_size)) == NULL
|| !EVP_CIPHER_meth_set_iv_length(cipher_handle->_hidden,
AES_IV_LEN)
|| !EVP_CIPHER_meth_set_flags(cipher_handle->_hidden,
EVP_CIPH_CBC_MODE |
EVP_CIPH_FLAG_DEFAULT_ASN1)
|| !EVP_CIPHER_meth_set_init(cipher_handle->_hidden,
afalg_cipher_init)
|| !EVP_CIPHER_meth_set_do_cipher(cipher_handle->_hidden,
afalg_do_cipher)
|| !EVP_CIPHER_meth_set_cleanup(cipher_handle->_hidden,
afalg_cipher_cleanup)
|| !EVP_CIPHER_meth_set_impl_ctx_size(cipher_handle->_hidden,
sizeof(afalg_ctx)))) {
EVP_CIPHER_meth_free(cipher_handle->_hidden);
cipher_handle->_hidden= NULL;
}
return cipher_handle->_hidden;
}
static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid)
{
int r = 1;
if (cipher == NULL) {
*nids = afalg_cipher_nids;
return (sizeof(afalg_cipher_nids) / sizeof(afalg_cipher_nids[0]));
}
switch (nid) {
case NID_aes_128_cbc:
case NID_aes_192_cbc:
case NID_aes_256_cbc:
*cipher = afalg_aes_cbc(nid);
break;
default:
*cipher = NULL;
r = 0;
}
return r;
}
static int bind_afalg(ENGINE *e)
{
/* Ensure the afalg error handling is set up */
unsigned short i;
ERR_load_AFALG_strings();
if (!ENGINE_set_id(e, engine_afalg_id)
|| !ENGINE_set_name(e, engine_afalg_name)
|| !ENGINE_set_destroy_function(e, afalg_destroy)
|| !ENGINE_set_init_function(e, afalg_init)
|| !ENGINE_set_finish_function(e, afalg_finish)) {
AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
return 0;
}
/*
* Create _hidden_aes_xxx_cbc by calling afalg_aes_xxx_cbc
* now, as bind_aflag can only be called by one thread at a
* time.
*/
for(i = 0; i < OSSL_NELEM(afalg_cipher_nids); i++) {
if (afalg_aes_cbc(afalg_cipher_nids[i]) == NULL) {
AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
return 0;
}
}
if (!ENGINE_set_ciphers(e, afalg_ciphers)) {
AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
return 0;
}
return 1;
}
# ifndef OPENSSL_NO_DYNAMIC_ENGINE
static int bind_helper(ENGINE *e, const char *id)
{
if (id && (strcmp(id, engine_afalg_id) != 0))
return 0;
if (!afalg_chk_platform())
return 0;
if (!bind_afalg(e)) {
afalg_destroy(e);
return 0;
}
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
# endif
static int afalg_chk_platform(void)
{
int ret;
int i;
int kver[3] = { -1, -1, -1 };
int sock;
char *str;
struct utsname ut;
ret = uname(&ut);
if (ret != 0) {
AFALGerr(AFALG_F_AFALG_CHK_PLATFORM,
AFALG_R_FAILED_TO_GET_PLATFORM_INFO);
return 0;
}
str = strtok(ut.release, ".");
for (i = 0; i < 3 && str != NULL; i++) {
kver[i] = atoi(str);
str = strtok(NULL, ".");
}
if (KERNEL_VERSION(kver[0], kver[1], kver[2])
< KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2)) {
ALG_ERR("ASYNC AFALG not supported this kernel(%d.%d.%d)\n",
kver[0], kver[1], kver[2]);
ALG_ERR("ASYNC AFALG requires kernel version %d.%d.%d or later\n",
K_MAJ, K_MIN1, K_MIN2);
AFALGerr(AFALG_F_AFALG_CHK_PLATFORM,
AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG);
return 0;
}
/* Test if we can actually create an AF_ALG socket */
sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (sock == -1) {
AFALGerr(AFALG_F_AFALG_CHK_PLATFORM, AFALG_R_SOCKET_CREATE_FAILED);
return 0;
}
close(sock);
return 1;
}
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
static ENGINE *engine_afalg(void)
{
ENGINE *ret = ENGINE_new();
if (ret == NULL)
return NULL;
if (!bind_afalg(ret)) {
ENGINE_free(ret);
return NULL;
}
return ret;
}
void engine_load_afalg_int(void)
{
ENGINE *toadd;
if (!afalg_chk_platform())
return;
toadd = engine_afalg();
if (toadd == NULL)
return;
ERR_set_mark();
ENGINE_add(toadd);
/*
* If the "add" worked, it gets a structural reference. So either way, we
* release our just-created reference.
*/
ENGINE_free(toadd);
/*
* If the "add" didn't work, it was probably a conflict because it was
* already added (eg. someone calling ENGINE_load_blah then calling
* ENGINE_load_builtin_engines() perhaps).
*/
ERR_pop_to_mark();
}
# endif
static int afalg_init(ENGINE *e)
{
return 1;
}
static int afalg_finish(ENGINE *e)
{
return 1;
}
static int free_cbc(void)
{
short unsigned int i;
for(i = 0; i < OSSL_NELEM(afalg_cipher_nids); i++) {
EVP_CIPHER_meth_free(cbc_handle[i]._hidden);
cbc_handle[i]._hidden = NULL;
}
return 1;
}
static int afalg_destroy(ENGINE *e)
{
ERR_unload_AFALG_strings();
free_cbc();
return 1;
}
#endif /* KERNEL VERSION */
diff --git a/crypto/openssl/engines/e_loader_attic.c b/crypto/openssl/engines/e_loader_attic.c
index a20e04da1a5b..08c9c16cbbfd 100644
--- a/crypto/openssl/engines/e_loader_attic.c
+++ b/crypto/openssl/engines/e_loader_attic.c
@@ -1,1773 +1,1773 @@
/*
* Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 ENGINE IS FOR TESTING PURPOSES ONLY. */
/* This file has quite some overlap with providers/implementations/storemgmt/file_store.c */
/* We need to use some engine deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
#include <string.h>
#include <sys/stat.h>
#include <ctype.h>
#include <assert.h>
#include <openssl/bio.h>
#include <openssl/dsa.h> /* For d2i_DSAPrivateKey */
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h> /* For the PKCS8 stuff o.O */
#include <openssl/rsa.h> /* For d2i_RSAPrivateKey */
#include <openssl/safestack.h>
#include <openssl/store.h>
#include <openssl/ui.h>
#include <openssl/engine.h>
#include <openssl/x509.h> /* For the PKCS8 stuff o.O */
#include "internal/asn1.h" /* For asn1_d2i_read_bio */
#include "internal/o_dir.h"
#include "internal/cryptlib.h"
#include "crypto/ctype.h" /* For ossl_isdigit */
#include "crypto/pem.h" /* For PVK and "blob" PEM headers */
#include "e_loader_attic_err.c"
DEFINE_STACK_OF(OSSL_STORE_INFO)
#ifdef _WIN32
# define stat _stat
#endif
#ifndef S_ISDIR
# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
#endif
/*-
* Password prompting
* ------------------
*/
static char *file_get_pass(const UI_METHOD *ui_method, char *pass,
size_t maxsize, const char *desc, const char *info,
void *data)
{
UI *ui = UI_new();
char *prompt = NULL;
if (ui == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (ui_method != NULL)
UI_set_method(ui, ui_method);
UI_add_user_data(ui, data);
if ((prompt = UI_construct_prompt(ui, desc, info)) == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
pass = NULL;
} else if (UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD,
pass, 0, maxsize - 1) <= 0) {
ATTICerr(0, ERR_R_UI_LIB);
pass = NULL;
} else {
switch (UI_process(ui)) {
case -2:
ATTICerr(0, ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED);
pass = NULL;
break;
case -1:
ATTICerr(0, ERR_R_UI_LIB);
pass = NULL;
break;
default:
break;
}
}
OPENSSL_free(prompt);
UI_free(ui);
return pass;
}
struct pem_pass_data {
const UI_METHOD *ui_method;
void *data;
const char *prompt_desc;
const char *prompt_info;
};
static int file_fill_pem_pass_data(struct pem_pass_data *pass_data,
const char *desc, const char *info,
const UI_METHOD *ui_method, void *ui_data)
{
if (pass_data == NULL)
return 0;
pass_data->ui_method = ui_method;
pass_data->data = ui_data;
pass_data->prompt_desc = desc;
pass_data->prompt_info = info;
return 1;
}
/* This is used anywhere a pem_password_cb is needed */
static int file_get_pem_pass(char *buf, int num, int w, void *data)
{
struct pem_pass_data *pass_data = data;
char *pass = file_get_pass(pass_data->ui_method, buf, num,
pass_data->prompt_desc, pass_data->prompt_info,
pass_data->data);
return pass == NULL ? 0 : strlen(pass);
}
/*
* Check if |str| ends with |suffix| preceded by a space, and if it does,
* return the index of that space. If there is no such suffix in |str|,
* return -1.
* For |str| == "FOO BAR" and |suffix| == "BAR", the returned value is 3.
*/
static int check_suffix(const char *str, const char *suffix)
{
int str_len = strlen(str);
int suffix_len = strlen(suffix) + 1;
const char *p = NULL;
if (suffix_len >= str_len)
return -1;
p = str + str_len - suffix_len;
if (*p != ' '
|| strcmp(p + 1, suffix) != 0)
return -1;
return p - str;
}
/*
* EMBEDDED is a special type of OSSL_STORE_INFO, specially for the file
* handlers, so we define it internally. This uses the possibility to
* create an OSSL_STORE_INFO with a generic data pointer and arbitrary
* type number.
*
* This is used by a FILE_HANDLER's try_decode function to signal that it
* has decoded the incoming blob into a new blob, and that the attempted
* decoding should be immediately restarted with the new blob, using the
* new PEM name.
*/
/* Negative numbers are never used for public OSSL_STORE_INFO types */
#define STORE_INFO_EMBEDDED -1
/* This is the embedded data */
struct embedded_st {
BUF_MEM *blob;
char *pem_name;
};
/* Helper functions */
static struct embedded_st *get0_EMBEDDED(OSSL_STORE_INFO *info)
{
return OSSL_STORE_INFO_get0_data(STORE_INFO_EMBEDDED, info);
}
static void store_info_free(OSSL_STORE_INFO *info)
{
struct embedded_st *data;
if (info != NULL && (data = get0_EMBEDDED(info)) != NULL) {
BUF_MEM_free(data->blob);
OPENSSL_free(data->pem_name);
OPENSSL_free(data);
}
OSSL_STORE_INFO_free(info);
}
static OSSL_STORE_INFO *new_EMBEDDED(const char *new_pem_name,
BUF_MEM *embedded)
{
OSSL_STORE_INFO *info = NULL;
struct embedded_st *data = NULL;
if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL
|| (info = OSSL_STORE_INFO_new(STORE_INFO_EMBEDDED, data)) == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
OPENSSL_free(data);
return NULL;
}
data->blob = embedded;
data->pem_name =
new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
if (new_pem_name != NULL && data->pem_name == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
store_info_free(info);
info = NULL;
}
return info;
}
/*-
* The file scheme decoders
* ------------------------
*
* Each possible data type has its own decoder, which either operates
* through a given PEM name, or attempts to decode to see if the blob
* it's given is decodable for its data type. The assumption is that
* only the correct data type will match the content.
*/
/*-
* The try_decode function is called to check if the blob of data can
* be used by this handler, and if it can, decodes it into a supported
* OpenSSL type and returns a OSSL_STORE_INFO with the decoded data.
* Input:
* pem_name: If this blob comes from a PEM file, this holds
* the PEM name. If it comes from another type of
* file, this is NULL.
* pem_header: If this blob comes from a PEM file, this holds
* the PEM headers. If it comes from another type of
* file, this is NULL.
* blob: The blob of data to match with what this handler
* can use.
* len: The length of the blob.
* handler_ctx: For a handler marked repeatable, this pointer can
* be used to create a context for the handler. IT IS
* THE HANDLER'S RESPONSIBILITY TO CREATE AND DESTROY
* THIS CONTEXT APPROPRIATELY, i.e. create on first call
* and destroy when about to return NULL.
* matchcount: A pointer to an int to count matches for this data.
* Usually becomes 0 (no match) or 1 (match!), but may
* be higher in the (unlikely) event that the data matches
* more than one possibility. The int will always be
* zero when the function is called.
* ui_method: Application UI method for getting a password, pin
* or any other interactive data.
* ui_data: Application data to be passed to ui_method when
* it's called.
* libctx: The library context to be used if applicable
* propq: The property query string for any algorithm fetches
* Output:
* a OSSL_STORE_INFO
*/
typedef OSSL_STORE_INFO *(*file_try_decode_fn)(const char *pem_name,
const char *pem_header,
const unsigned char *blob,
size_t len, void **handler_ctx,
int *matchcount,
const UI_METHOD *ui_method,
void *ui_data, const char *uri,
OSSL_LIB_CTX *libctx,
const char *propq);
/*
* The eof function should return 1 if there's no more data to be found
* with the handler_ctx, otherwise 0. This is only used when the handler is
* marked repeatable.
*/
typedef int (*file_eof_fn)(void *handler_ctx);
/*
* The destroy_ctx function is used to destroy the handler_ctx that was
* initiated by a repeatable try_decode function. This is only used when
* the handler is marked repeatable.
*/
typedef void (*file_destroy_ctx_fn)(void **handler_ctx);
typedef struct file_handler_st {
const char *name;
file_try_decode_fn try_decode;
file_eof_fn eof;
file_destroy_ctx_fn destroy_ctx;
/* flags */
int repeatable;
} FILE_HANDLER;
/*
* PKCS#12 decoder. It operates by decoding all of the blob content,
* extracting all the interesting data from it and storing them internally,
* then serving them one piece at a time.
*/
static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
const char *pem_header,
const unsigned char *blob,
size_t len, void **pctx,
int *matchcount,
const UI_METHOD *ui_method,
void *ui_data, const char *uri,
OSSL_LIB_CTX *libctx,
const char *propq)
{
OSSL_STORE_INFO *store_info = NULL;
STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
if (ctx == NULL) {
/* Initial parsing */
PKCS12 *p12;
if (pem_name != NULL)
/* No match, there is no PEM PKCS12 tag */
return NULL;
if ((p12 = d2i_PKCS12(NULL, &blob, len)) != NULL) {
char *pass = NULL;
char tpass[PEM_BUFSIZE];
EVP_PKEY *pkey = NULL;
X509 *cert = NULL;
STACK_OF(X509) *chain = NULL;
*matchcount = 1;
if (!PKCS12_mac_present(p12)
|| PKCS12_verify_mac(p12, "", 0)
|| PKCS12_verify_mac(p12, NULL, 0)) {
pass = "";
} else {
if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE,
"PKCS12 import", uri,
ui_data)) == NULL) {
ATTICerr(0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR);
goto p12_end;
}
if (!PKCS12_verify_mac(p12, pass, strlen(pass))) {
ATTICerr(0, ATTIC_R_ERROR_VERIFYING_PKCS12_MAC);
goto p12_end;
}
}
if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) {
OSSL_STORE_INFO *osi_pkey = NULL;
OSSL_STORE_INFO *osi_cert = NULL;
OSSL_STORE_INFO *osi_ca = NULL;
int ok = 1;
if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL) {
if (pkey != NULL) {
if ((osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL
/* clearing pkey here avoids case distinctions */
&& (pkey = NULL) == NULL
&& sk_OSSL_STORE_INFO_push(ctx, osi_pkey) != 0)
osi_pkey = NULL;
else
ok = 0;
}
if (ok && cert != NULL) {
if ((osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL
/* clearing cert here avoids case distinctions */
&& (cert = NULL) == NULL
&& sk_OSSL_STORE_INFO_push(ctx, osi_cert) != 0)
osi_cert = NULL;
else
ok = 0;
}
while (ok && sk_X509_num(chain) > 0) {
X509 *ca = sk_X509_value(chain, 0);
if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) != NULL
&& sk_X509_shift(chain) != NULL
&& sk_OSSL_STORE_INFO_push(ctx, osi_ca) != 0)
osi_ca = NULL;
else
ok = 0;
}
}
EVP_PKEY_free(pkey);
X509_free(cert);
sk_X509_pop_free(chain, X509_free);
store_info_free(osi_pkey);
store_info_free(osi_cert);
store_info_free(osi_ca);
if (!ok) {
sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free);
ctx = NULL;
}
*pctx = ctx;
}
}
p12_end:
PKCS12_free(p12);
if (ctx == NULL)
return NULL;
}
*matchcount = 1;
store_info = sk_OSSL_STORE_INFO_shift(ctx);
return store_info;
}
static int eof_PKCS12(void *ctx_)
{
STACK_OF(OSSL_STORE_INFO) *ctx = ctx_;
return ctx == NULL || sk_OSSL_STORE_INFO_num(ctx) == 0;
}
static void destroy_ctx_PKCS12(void **pctx)
{
STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free);
*pctx = NULL;
}
static FILE_HANDLER PKCS12_handler = {
"PKCS12",
try_decode_PKCS12,
eof_PKCS12,
destroy_ctx_PKCS12,
1 /* repeatable */
};
/*
* Encrypted PKCS#8 decoder. It operates by just decrypting the given blob
* into a new blob, which is returned as an EMBEDDED STORE_INFO. The whole
* decoding process will then start over with the new blob.
*/
static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
const char *pem_header,
const unsigned char *blob,
size_t len, void **pctx,
int *matchcount,
const UI_METHOD *ui_method,
void *ui_data,
const char *uri,
OSSL_LIB_CTX *libctx,
const char *propq)
{
X509_SIG *p8 = NULL;
char kbuf[PEM_BUFSIZE];
char *pass = NULL;
const X509_ALGOR *dalg = NULL;
const ASN1_OCTET_STRING *doct = NULL;
OSSL_STORE_INFO *store_info = NULL;
BUF_MEM *mem = NULL;
unsigned char *new_data = NULL;
int new_data_len;
if (pem_name != NULL) {
if (strcmp(pem_name, PEM_STRING_PKCS8) != 0)
return NULL;
*matchcount = 1;
}
if ((p8 = d2i_X509_SIG(NULL, &blob, len)) == NULL)
return NULL;
*matchcount = 1;
if ((mem = BUF_MEM_new()) == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
goto nop8;
}
if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE,
"PKCS8 decrypt pass phrase", uri,
ui_data)) == NULL) {
ATTICerr(0, ATTIC_R_BAD_PASSWORD_READ);
goto nop8;
}
X509_SIG_get0(p8, &dalg, &doct);
if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), doct->data, doct->length,
&new_data, &new_data_len, 0))
goto nop8;
mem->data = (char *)new_data;
mem->max = mem->length = (size_t)new_data_len;
X509_SIG_free(p8);
p8 = NULL;
store_info = new_EMBEDDED(PEM_STRING_PKCS8INF, mem);
if (store_info == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
goto nop8;
}
return store_info;
nop8:
X509_SIG_free(p8);
BUF_MEM_free(mem);
return NULL;
}
static FILE_HANDLER PKCS8Encrypted_handler = {
"PKCS8Encrypted",
try_decode_PKCS8Encrypted
};
/*
* Private key decoder. Decodes all sorts of private keys, both PKCS#8
* encoded ones and old style PEM ones (with the key type is encoded into
* the PEM name).
*/
static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
const char *pem_header,
const unsigned char *blob,
size_t len, void **pctx,
int *matchcount,
const UI_METHOD *ui_method,
void *ui_data, const char *uri,
OSSL_LIB_CTX *libctx,
const char *propq)
{
OSSL_STORE_INFO *store_info = NULL;
EVP_PKEY *pkey = NULL;
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
if (pem_name != NULL) {
if (strcmp(pem_name, PEM_STRING_PKCS8INF) == 0) {
PKCS8_PRIV_KEY_INFO *p8inf =
d2i_PKCS8_PRIV_KEY_INFO(NULL, &blob, len);
*matchcount = 1;
if (p8inf != NULL)
pkey = EVP_PKCS82PKEY_ex(p8inf, libctx, propq);
PKCS8_PRIV_KEY_INFO_free(p8inf);
} else {
int slen;
int pkey_id;
if ((slen = check_suffix(pem_name, "PRIVATE KEY")) > 0
&& (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name,
slen)) != NULL
&& EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
ameth)) {
*matchcount = 1;
pkey = d2i_PrivateKey_ex(pkey_id, NULL, &blob, len,
libctx, propq);
}
}
} else {
int i;
#ifndef OPENSSL_NO_ENGINE
ENGINE *curengine = ENGINE_get_first();
while (curengine != NULL) {
ENGINE_PKEY_ASN1_METHS_PTR asn1meths =
ENGINE_get_pkey_asn1_meths(curengine);
if (asn1meths != NULL) {
const int *nids = NULL;
int nids_n = asn1meths(curengine, NULL, &nids, 0);
for (i = 0; i < nids_n; i++) {
EVP_PKEY_ASN1_METHOD *ameth2 = NULL;
EVP_PKEY *tmp_pkey = NULL;
const unsigned char *tmp_blob = blob;
int pkey_id, pkey_flags;
if (!asn1meths(curengine, &ameth2, NULL, nids[i])
|| !EVP_PKEY_asn1_get0_info(&pkey_id, NULL,
&pkey_flags, NULL, NULL,
ameth2)
|| (pkey_flags & ASN1_PKEY_ALIAS) != 0)
continue;
ERR_set_mark(); /* prevent flooding error queue */
tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL,
&tmp_blob, len,
libctx, propq);
if (tmp_pkey != NULL) {
if (pkey != NULL)
EVP_PKEY_free(tmp_pkey);
else
pkey = tmp_pkey;
(*matchcount)++;
}
ERR_pop_to_mark();
}
}
curengine = ENGINE_get_next(curengine);
}
#endif
for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
EVP_PKEY *tmp_pkey = NULL;
const unsigned char *tmp_blob = blob;
int pkey_id, pkey_flags;
ameth = EVP_PKEY_asn1_get0(i);
if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL,
NULL, ameth)
|| (pkey_flags & ASN1_PKEY_ALIAS) != 0)
continue;
ERR_set_mark(); /* prevent flooding error queue */
tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL, &tmp_blob, len,
libctx, propq);
if (tmp_pkey != NULL) {
if (pkey != NULL)
EVP_PKEY_free(tmp_pkey);
else
pkey = tmp_pkey;
(*matchcount)++;
}
ERR_pop_to_mark();
}
if (*matchcount > 1) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
}
if (pkey == NULL)
/* No match */
return NULL;
store_info = OSSL_STORE_INFO_new_PKEY(pkey);
if (store_info == NULL)
EVP_PKEY_free(pkey);
return store_info;
}
static FILE_HANDLER PrivateKey_handler = {
"PrivateKey",
try_decode_PrivateKey
};
/*
* Public key decoder. Only supports SubjectPublicKeyInfo formatted keys.
*/
static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name,
const char *pem_header,
const unsigned char *blob,
size_t len, void **pctx,
int *matchcount,
const UI_METHOD *ui_method,
void *ui_data, const char *uri,
OSSL_LIB_CTX *libctx,
const char *propq)
{
OSSL_STORE_INFO *store_info = NULL;
EVP_PKEY *pkey = NULL;
if (pem_name != NULL) {
if (strcmp(pem_name, PEM_STRING_PUBLIC) != 0)
/* No match */
return NULL;
*matchcount = 1;
}
if ((pkey = d2i_PUBKEY(NULL, &blob, len)) != NULL) {
*matchcount = 1;
store_info = OSSL_STORE_INFO_new_PUBKEY(pkey);
}
return store_info;
}
static FILE_HANDLER PUBKEY_handler = {
"PUBKEY",
try_decode_PUBKEY
};
/*
* Key parameter decoder.
*/
static OSSL_STORE_INFO *try_decode_params(const char *pem_name,
const char *pem_header,
const unsigned char *blob,
size_t len, void **pctx,
int *matchcount,
const UI_METHOD *ui_method,
void *ui_data, const char *uri,
OSSL_LIB_CTX *libctx,
const char *propq)
{
OSSL_STORE_INFO *store_info = NULL;
EVP_PKEY *pkey = NULL;
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
if (pem_name != NULL) {
int slen;
int pkey_id;
if ((slen = check_suffix(pem_name, "PARAMETERS")) > 0
&& (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, slen)) != NULL
&& EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
ameth)) {
*matchcount = 1;
pkey = d2i_KeyParams(pkey_id, NULL, &blob, len);
}
} else {
int i;
for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
EVP_PKEY *tmp_pkey = NULL;
const unsigned char *tmp_blob = blob;
int pkey_id, pkey_flags;
ameth = EVP_PKEY_asn1_get0(i);
if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL,
NULL, ameth)
|| (pkey_flags & ASN1_PKEY_ALIAS) != 0)
continue;
ERR_set_mark(); /* prevent flooding error queue */
tmp_pkey = d2i_KeyParams(pkey_id, NULL, &tmp_blob, len);
if (tmp_pkey != NULL) {
if (pkey != NULL)
EVP_PKEY_free(tmp_pkey);
else
pkey = tmp_pkey;
(*matchcount)++;
}
ERR_pop_to_mark();
}
if (*matchcount > 1) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
}
if (pkey == NULL)
/* No match */
return NULL;
store_info = OSSL_STORE_INFO_new_PARAMS(pkey);
if (store_info == NULL)
EVP_PKEY_free(pkey);
return store_info;
}
static FILE_HANDLER params_handler = {
"params",
try_decode_params
};
/*
* X.509 certificate decoder.
*/
static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name,
const char *pem_header,
const unsigned char *blob,
size_t len, void **pctx,
int *matchcount,
const UI_METHOD *ui_method,
void *ui_data,
const char *uri,
OSSL_LIB_CTX *libctx,
const char *propq)
{
OSSL_STORE_INFO *store_info = NULL;
X509 *cert = NULL;
/*
* In most cases, we can try to interpret the serialized data as a trusted
* cert (X509 + X509_AUX) and fall back to reading it as a normal cert
* (just X509), but if the PEM name specifically declares it as a trusted
* cert, then no fallback should be engaged. |ignore_trusted| tells if
* the fallback can be used (1) or not (0).
*/
int ignore_trusted = 1;
if (pem_name != NULL) {
if (strcmp(pem_name, PEM_STRING_X509_TRUSTED) == 0)
ignore_trusted = 0;
else if (strcmp(pem_name, PEM_STRING_X509_OLD) != 0
&& strcmp(pem_name, PEM_STRING_X509) != 0)
/* No match */
return NULL;
*matchcount = 1;
}
cert = X509_new_ex(libctx, propq);
if (cert == NULL)
return NULL;
if ((d2i_X509_AUX(&cert, &blob, len)) != NULL
|| (ignore_trusted && (d2i_X509(&cert, &blob, len)) != NULL)) {
*matchcount = 1;
store_info = OSSL_STORE_INFO_new_CERT(cert);
}
if (store_info == NULL)
X509_free(cert);
return store_info;
}
static FILE_HANDLER X509Certificate_handler = {
"X509Certificate",
try_decode_X509Certificate
};
/*
* X.509 CRL decoder.
*/
static OSSL_STORE_INFO *try_decode_X509CRL(const char *pem_name,
const char *pem_header,
const unsigned char *blob,
size_t len, void **pctx,
int *matchcount,
const UI_METHOD *ui_method,
void *ui_data, const char *uri,
OSSL_LIB_CTX *libctx,
const char *propq)
{
OSSL_STORE_INFO *store_info = NULL;
X509_CRL *crl = NULL;
if (pem_name != NULL) {
if (strcmp(pem_name, PEM_STRING_X509_CRL) != 0)
/* No match */
return NULL;
*matchcount = 1;
}
if ((crl = d2i_X509_CRL(NULL, &blob, len)) != NULL) {
*matchcount = 1;
store_info = OSSL_STORE_INFO_new_CRL(crl);
}
if (store_info == NULL)
X509_CRL_free(crl);
return store_info;
}
static FILE_HANDLER X509CRL_handler = {
"X509CRL",
try_decode_X509CRL
};
/*
* To finish it all off, we collect all the handlers.
*/
static const FILE_HANDLER *file_handlers[] = {
&PKCS12_handler,
&PKCS8Encrypted_handler,
&X509Certificate_handler,
&X509CRL_handler,
&params_handler,
&PUBKEY_handler,
&PrivateKey_handler,
};
/*-
* The loader itself
* -----------------
*/
struct ossl_store_loader_ctx_st {
char *uri; /* The URI we currently try to load */
enum {
is_raw = 0,
is_pem,
is_dir
} type;
int errcnt;
#define FILE_FLAG_SECMEM (1<<0)
#define FILE_FLAG_ATTACHED (1<<1)
unsigned int flags;
union {
struct { /* Used with is_raw and is_pem */
BIO *file;
/*
* The following are used when the handler is marked as
* repeatable
*/
const FILE_HANDLER *last_handler;
void *last_handler_ctx;
} file;
struct { /* Used with is_dir */
OPENSSL_DIR_CTX *ctx;
int end_reached;
/*
* When a search expression is given, these are filled in.
* |search_name| contains the file basename to look for.
* The string is exactly 8 characters long.
*/
char search_name[9];
/*
* The directory reading utility we have combines opening with
* reading the first name. To make sure we can detect the end
* at the right time, we read early and cache the name.
*/
const char *last_entry;
int last_errno;
} dir;
} _;
/* Expected object type. May be unspecified */
int expected_type;
OSSL_LIB_CTX *libctx;
char *propq;
};
static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
{
if (ctx == NULL)
return;
OPENSSL_free(ctx->propq);
OPENSSL_free(ctx->uri);
if (ctx->type != is_dir) {
if (ctx->_.file.last_handler != NULL) {
ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx);
ctx->_.file.last_handler_ctx = NULL;
ctx->_.file.last_handler = NULL;
}
}
OPENSSL_free(ctx);
}
static int file_find_type(OSSL_STORE_LOADER_CTX *ctx)
{
BIO *buff = NULL;
char peekbuf[4096] = { 0, };
if ((buff = BIO_new(BIO_f_buffer())) == NULL)
return 0;
ctx->_.file.file = BIO_push(buff, ctx->_.file.file);
if (BIO_buffer_peek(ctx->_.file.file, peekbuf, sizeof(peekbuf) - 1) > 0) {
peekbuf[sizeof(peekbuf) - 1] = '\0';
if (strstr(peekbuf, "-----BEGIN ") != NULL)
ctx->type = is_pem;
}
return 1;
}
static OSSL_STORE_LOADER_CTX *file_open_ex
(const OSSL_STORE_LOADER *loader, const char *uri,
OSSL_LIB_CTX *libctx, const char *propq,
const UI_METHOD *ui_method, void *ui_data)
{
OSSL_STORE_LOADER_CTX *ctx = NULL;
struct stat st;
struct {
const char *path;
unsigned int check_absolute:1;
} path_data[2];
size_t path_data_n = 0, i;
const char *path;
/*
* First step, just take the URI as is.
*/
path_data[path_data_n].check_absolute = 0;
path_data[path_data_n++].path = uri;
/*
* Second step, if the URI appears to start with the 'file' scheme,
* extract the path and make that the second path to check.
* There's a special case if the URI also contains an authority, then
* the full URI shouldn't be used as a path anywhere.
*/
if (OPENSSL_strncasecmp(uri, "file:", 5) == 0) {
const char *p = &uri[5];
if (strncmp(&uri[5], "//", 2) == 0) {
path_data_n--; /* Invalidate using the full URI */
if (OPENSSL_strncasecmp(&uri[7], "localhost/", 10) == 0) {
p = &uri[16];
} else if (uri[7] == '/') {
p = &uri[7];
} else {
ATTICerr(0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED);
return NULL;
}
}
path_data[path_data_n].check_absolute = 1;
#ifdef _WIN32
/* Windows file: URIs with a drive letter start with a / */
if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
- char c = tolower(p[1]);
+ char c = tolower((unsigned char)p[1]);
if (c >= 'a' && c <= 'z') {
p++;
/* We know it's absolute, so no need to check */
path_data[path_data_n].check_absolute = 0;
}
}
#endif
path_data[path_data_n++].path = p;
}
for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) {
/*
* If the scheme "file" was an explicit part of the URI, the path must
* be absolute. So says RFC 8089
*/
if (path_data[i].check_absolute && path_data[i].path[0] != '/') {
ATTICerr(0, ATTIC_R_PATH_MUST_BE_ABSOLUTE);
ERR_add_error_data(1, path_data[i].path);
return NULL;
}
if (stat(path_data[i].path, &st) < 0) {
ERR_raise_data(ERR_LIB_SYS, errno,
"calling stat(%s)",
path_data[i].path);
} else {
path = path_data[i].path;
}
}
if (path == NULL) {
return NULL;
}
/* Successfully found a working path */
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
ctx->uri = OPENSSL_strdup(uri);
if (ctx->uri == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
goto err;
}
if (S_ISDIR(st.st_mode)) {
ctx->type = is_dir;
ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path);
ctx->_.dir.last_errno = errno;
if (ctx->_.dir.last_entry == NULL) {
if (ctx->_.dir.last_errno != 0) {
ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
goto err;
}
ctx->_.dir.end_reached = 1;
}
} else if ((ctx->_.file.file = BIO_new_file(path, "rb")) == NULL
|| !file_find_type(ctx)) {
BIO_free_all(ctx->_.file.file);
goto err;
}
if (propq != NULL) {
ctx->propq = OPENSSL_strdup(propq);
if (ctx->propq == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
goto err;
}
}
ctx->libctx = libctx;
return ctx;
err:
OSSL_STORE_LOADER_CTX_free(ctx);
return NULL;
}
static OSSL_STORE_LOADER_CTX *file_open
(const OSSL_STORE_LOADER *loader, const char *uri,
const UI_METHOD *ui_method, void *ui_data)
{
return file_open_ex(loader, uri, NULL, NULL, ui_method, ui_data);
}
static OSSL_STORE_LOADER_CTX *file_attach
(const OSSL_STORE_LOADER *loader, BIO *bp,
OSSL_LIB_CTX *libctx, const char *propq,
const UI_METHOD *ui_method, void *ui_data)
{
OSSL_STORE_LOADER_CTX *ctx = NULL;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL
|| (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
OSSL_STORE_LOADER_CTX_free(ctx);
return NULL;
}
ctx->libctx = libctx;
ctx->flags |= FILE_FLAG_ATTACHED;
ctx->_.file.file = bp;
if (!file_find_type(ctx)) {
/* Safety measure */
ctx->_.file.file = NULL;
goto err;
}
return ctx;
err:
OSSL_STORE_LOADER_CTX_free(ctx);
return NULL;
}
static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
{
int ret = 1;
switch (cmd) {
case OSSL_STORE_C_USE_SECMEM:
{
int on = *(va_arg(args, int *));
switch (on) {
case 0:
ctx->flags &= ~FILE_FLAG_SECMEM;
break;
case 1:
ctx->flags |= FILE_FLAG_SECMEM;
break;
default:
ATTICerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
ret = 0;
break;
}
}
break;
default:
break;
}
return ret;
}
static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
{
ctx->expected_type = expected;
return 1;
}
static int file_find(OSSL_STORE_LOADER_CTX *ctx,
const OSSL_STORE_SEARCH *search)
{
/*
* If ctx == NULL, the library is looking to know if this loader supports
* the given search type.
*/
if (OSSL_STORE_SEARCH_get_type(search) == OSSL_STORE_SEARCH_BY_NAME) {
unsigned long hash = 0;
if (ctx == NULL)
return 1;
if (ctx->type != is_dir) {
ATTICerr(0, ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
return 0;
}
hash = X509_NAME_hash_ex(OSSL_STORE_SEARCH_get0_name(search),
NULL, NULL, NULL);
BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name),
"%08lx", hash);
return 1;
}
if (ctx != NULL)
ATTICerr(0, ATTIC_R_UNSUPPORTED_SEARCH_TYPE);
return 0;
}
static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
const char *pem_name,
const char *pem_header,
unsigned char *data, size_t len,
const UI_METHOD *ui_method,
void *ui_data, int *matchcount)
{
OSSL_STORE_INFO *result = NULL;
BUF_MEM *new_mem = NULL;
char *new_pem_name = NULL;
int t = 0;
again:
{
size_t i = 0;
void *handler_ctx = NULL;
const FILE_HANDLER **matching_handlers =
OPENSSL_zalloc(sizeof(*matching_handlers)
* OSSL_NELEM(file_handlers));
if (matching_handlers == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
goto err;
}
*matchcount = 0;
for (i = 0; i < OSSL_NELEM(file_handlers); i++) {
const FILE_HANDLER *handler = file_handlers[i];
int try_matchcount = 0;
void *tmp_handler_ctx = NULL;
OSSL_STORE_INFO *tmp_result;
unsigned long err;
ERR_set_mark();
tmp_result =
handler->try_decode(pem_name, pem_header, data, len,
&tmp_handler_ctx, &try_matchcount,
ui_method, ui_data, ctx->uri,
ctx->libctx, ctx->propq);
/* avoid flooding error queue with low-level ASN.1 parse errors */
err = ERR_peek_last_error();
if (ERR_GET_LIB(err) == ERR_LIB_ASN1
&& ERR_GET_REASON(err) == ERR_R_NESTED_ASN1_ERROR)
ERR_pop_to_mark();
else
ERR_clear_last_mark();
if (try_matchcount > 0) {
matching_handlers[*matchcount] = handler;
if (handler_ctx)
handler->destroy_ctx(&handler_ctx);
handler_ctx = tmp_handler_ctx;
if ((*matchcount += try_matchcount) > 1) {
/* more than one match => ambiguous, kill any result */
store_info_free(result);
store_info_free(tmp_result);
if (handler->destroy_ctx != NULL)
handler->destroy_ctx(&handler_ctx);
handler_ctx = NULL;
tmp_result = NULL;
result = NULL;
}
if (result == NULL)
result = tmp_result;
if (result == NULL) /* e.g., PKCS#12 file decryption error */
break;
}
}
if (result != NULL
&& *matchcount == 1 && matching_handlers[0]->repeatable) {
ctx->_.file.last_handler = matching_handlers[0];
ctx->_.file.last_handler_ctx = handler_ctx;
}
OPENSSL_free(matching_handlers);
}
err:
OPENSSL_free(new_pem_name);
BUF_MEM_free(new_mem);
if (result != NULL
&& (t = OSSL_STORE_INFO_get_type(result)) == STORE_INFO_EMBEDDED) {
struct embedded_st *embedded = get0_EMBEDDED(result);
/* "steal" the embedded data */
pem_name = new_pem_name = embedded->pem_name;
new_mem = embedded->blob;
data = (unsigned char *)new_mem->data;
len = new_mem->length;
embedded->pem_name = NULL;
embedded->blob = NULL;
store_info_free(result);
result = NULL;
goto again;
}
return result;
}
static OSSL_STORE_INFO *file_load_try_repeat(OSSL_STORE_LOADER_CTX *ctx,
const UI_METHOD *ui_method,
void *ui_data)
{
OSSL_STORE_INFO *result = NULL;
int try_matchcount = 0;
if (ctx->_.file.last_handler != NULL) {
result =
ctx->_.file.last_handler->try_decode(NULL, NULL, NULL, 0,
&ctx->_.file.last_handler_ctx,
&try_matchcount,
ui_method, ui_data, ctx->uri,
ctx->libctx, ctx->propq);
if (result == NULL) {
ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx);
ctx->_.file.last_handler_ctx = NULL;
ctx->_.file.last_handler = NULL;
}
}
return result;
}
static void pem_free_flag(void *pem_data, int secure, size_t num)
{
if (secure)
OPENSSL_secure_clear_free(pem_data, num);
else
OPENSSL_free(pem_data);
}
static int file_read_pem(BIO *bp, char **pem_name, char **pem_header,
unsigned char **data, long *len,
const UI_METHOD *ui_method, void *ui_data,
const char *uri, int secure)
{
int i = secure
? PEM_read_bio_ex(bp, pem_name, pem_header, data, len,
PEM_FLAG_SECURE | PEM_FLAG_EAY_COMPATIBLE)
: PEM_read_bio(bp, pem_name, pem_header, data, len);
if (i <= 0)
return 0;
/*
* 10 is the number of characters in "Proc-Type:", which
* PEM_get_EVP_CIPHER_INFO() requires to be present.
* If the PEM header has less characters than that, it's
* not worth spending cycles on it.
*/
if (strlen(*pem_header) > 10) {
EVP_CIPHER_INFO cipher;
struct pem_pass_data pass_data;
if (!PEM_get_EVP_CIPHER_INFO(*pem_header, &cipher)
|| !file_fill_pem_pass_data(&pass_data, "PEM pass phrase", uri,
ui_method, ui_data)
|| !PEM_do_header(&cipher, *data, len, file_get_pem_pass,
&pass_data)) {
return 0;
}
}
return 1;
}
static OSSL_STORE_INFO *file_try_read_msblob(BIO *bp, int *matchcount)
{
OSSL_STORE_INFO *result = NULL;
int ispub = -1;
{
unsigned int magic = 0, bitlen = 0;
int isdss = 0;
unsigned char peekbuf[16] = { 0, };
const unsigned char *p = peekbuf;
if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
return 0;
if (ossl_do_blob_header(&p, sizeof(peekbuf), &magic, &bitlen,
&isdss, &ispub) <= 0)
return 0;
}
(*matchcount)++;
{
EVP_PKEY *tmp = ispub
? b2i_PublicKey_bio(bp)
: b2i_PrivateKey_bio(bp);
if (tmp == NULL
|| (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) {
EVP_PKEY_free(tmp);
return 0;
}
}
return result;
}
static OSSL_STORE_INFO *file_try_read_PVK(BIO *bp, const UI_METHOD *ui_method,
void *ui_data, const char *uri,
int *matchcount)
{
OSSL_STORE_INFO *result = NULL;
{
unsigned int saltlen = 0, keylen = 0;
unsigned char peekbuf[24] = { 0, };
const unsigned char *p = peekbuf;
if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
return 0;
if (!ossl_do_PVK_header(&p, sizeof(peekbuf), 0, &saltlen, &keylen))
return 0;
}
(*matchcount)++;
{
EVP_PKEY *tmp = NULL;
struct pem_pass_data pass_data;
if (!file_fill_pem_pass_data(&pass_data, "PVK pass phrase", uri,
ui_method, ui_data)
|| (tmp = b2i_PVK_bio(bp, file_get_pem_pass, &pass_data)) == NULL
|| (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) {
EVP_PKEY_free(tmp);
return 0;
}
}
return result;
}
static int file_read_asn1(BIO *bp, unsigned char **data, long *len)
{
BUF_MEM *mem = NULL;
if (asn1_d2i_read_bio(bp, &mem) < 0)
return 0;
*data = (unsigned char *)mem->data;
*len = (long)mem->length;
OPENSSL_free(mem);
return 1;
}
static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name,
char **data)
{
assert(name != NULL);
assert(data != NULL);
{
const char *pathsep = ossl_ends_with_dirsep(ctx->uri) ? "" : "/";
long calculated_length = strlen(ctx->uri) + strlen(pathsep)
+ strlen(name) + 1 /* \0 */;
*data = OPENSSL_zalloc(calculated_length);
if (*data == NULL) {
ATTICerr(0, ERR_R_MALLOC_FAILURE);
return 0;
}
OPENSSL_strlcat(*data, ctx->uri, calculated_length);
OPENSSL_strlcat(*data, pathsep, calculated_length);
OPENSSL_strlcat(*data, name, calculated_length);
}
return 1;
}
static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
{
const char *p = NULL;
size_t len = strlen(ctx->_.dir.search_name);
/* If there are no search criteria, all names are accepted */
if (ctx->_.dir.search_name[0] == '\0')
return 1;
/* If the expected type isn't supported, no name is accepted */
if (ctx->expected_type != 0
&& ctx->expected_type != OSSL_STORE_INFO_CERT
&& ctx->expected_type != OSSL_STORE_INFO_CRL)
return 0;
/*
* First, check the basename
*/
if (OPENSSL_strncasecmp(name, ctx->_.dir.search_name, len) != 0
|| name[len] != '.')
return 0;
p = &name[len + 1];
/*
* Then, if the expected type is a CRL, check that the extension starts
* with 'r'
*/
if (*p == 'r') {
p++;
if (ctx->expected_type != 0
&& ctx->expected_type != OSSL_STORE_INFO_CRL)
return 0;
} else if (ctx->expected_type == OSSL_STORE_INFO_CRL) {
return 0;
}
/*
* Last, check that the rest of the extension is a decimal number, at
* least one digit long.
*/
if (!isdigit((unsigned char)*p))
return 0;
while (isdigit((unsigned char)*p))
p++;
#ifdef __VMS
/*
* One extra step here, check for a possible generation number.
*/
if (*p == ';')
for (p++; *p != '\0'; p++)
if (!ossl_isdigit(*p))
break;
#endif
/*
* If we've reached the end of the string at this point, we've successfully
* found a fitting file name.
*/
return *p == '\0';
}
static int file_eof(OSSL_STORE_LOADER_CTX *ctx);
static int file_error(OSSL_STORE_LOADER_CTX *ctx);
static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
const UI_METHOD *ui_method,
void *ui_data)
{
OSSL_STORE_INFO *result = NULL;
ctx->errcnt = 0;
if (ctx->type == is_dir) {
do {
char *newname = NULL;
if (ctx->_.dir.last_entry == NULL) {
if (!ctx->_.dir.end_reached) {
assert(ctx->_.dir.last_errno != 0);
ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
ctx->errcnt++;
}
return NULL;
}
if (ctx->_.dir.last_entry[0] != '.'
&& file_name_check(ctx, ctx->_.dir.last_entry)
&& !file_name_to_uri(ctx, ctx->_.dir.last_entry, &newname))
return NULL;
/*
* On the first call (with a NULL context), OPENSSL_DIR_read()
* cares about the second argument. On the following calls, it
* only cares that it isn't NULL. Therefore, we can safely give
* it our URI here.
*/
ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, ctx->uri);
ctx->_.dir.last_errno = errno;
if (ctx->_.dir.last_entry == NULL && ctx->_.dir.last_errno == 0)
ctx->_.dir.end_reached = 1;
if (newname != NULL
&& (result = OSSL_STORE_INFO_new_NAME(newname)) == NULL) {
OPENSSL_free(newname);
ATTICerr(0, ERR_R_OSSL_STORE_LIB);
return NULL;
}
} while (result == NULL && !file_eof(ctx));
} else {
int matchcount = -1;
again:
result = file_load_try_repeat(ctx, ui_method, ui_data);
if (result != NULL)
return result;
if (file_eof(ctx))
return NULL;
do {
char *pem_name = NULL; /* PEM record name */
char *pem_header = NULL; /* PEM record header */
unsigned char *data = NULL; /* DER encoded data */
long len = 0; /* DER encoded data length */
matchcount = -1;
if (ctx->type == is_pem) {
if (!file_read_pem(ctx->_.file.file, &pem_name, &pem_header,
&data, &len, ui_method, ui_data, ctx->uri,
(ctx->flags & FILE_FLAG_SECMEM) != 0)) {
ctx->errcnt++;
goto endloop;
}
} else {
if ((result = file_try_read_msblob(ctx->_.file.file,
&matchcount)) != NULL
|| (result = file_try_read_PVK(ctx->_.file.file,
ui_method, ui_data, ctx->uri,
&matchcount)) != NULL)
goto endloop;
if (!file_read_asn1(ctx->_.file.file, &data, &len)) {
ctx->errcnt++;
goto endloop;
}
}
result = file_load_try_decode(ctx, pem_name, pem_header, data, len,
ui_method, ui_data, &matchcount);
if (result != NULL)
goto endloop;
/*
* If a PEM name matches more than one handler, the handlers are
* badly coded.
*/
if (!ossl_assert(pem_name == NULL || matchcount <= 1)) {
ctx->errcnt++;
goto endloop;
}
if (matchcount > 1) {
ATTICerr(0, ATTIC_R_AMBIGUOUS_CONTENT_TYPE);
} else if (matchcount == 1) {
/*
* If there are other errors on the stack, they already show
* what the problem is.
*/
if (ERR_peek_error() == 0) {
ATTICerr(0, ATTIC_R_UNSUPPORTED_CONTENT_TYPE);
if (pem_name != NULL)
ERR_add_error_data(3, "PEM type is '", pem_name, "'");
}
}
if (matchcount > 0)
ctx->errcnt++;
endloop:
pem_free_flag(pem_name, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0);
pem_free_flag(pem_header, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0);
pem_free_flag(data, (ctx->flags & FILE_FLAG_SECMEM) != 0, len);
} while (matchcount == 0 && !file_eof(ctx) && !file_error(ctx));
/* We bail out on ambiguity */
if (matchcount > 1) {
store_info_free(result);
return NULL;
}
if (result != NULL
&& ctx->expected_type != 0
&& ctx->expected_type != OSSL_STORE_INFO_get_type(result)) {
store_info_free(result);
goto again;
}
}
return result;
}
static int file_error(OSSL_STORE_LOADER_CTX *ctx)
{
return ctx->errcnt > 0;
}
static int file_eof(OSSL_STORE_LOADER_CTX *ctx)
{
if (ctx->type == is_dir)
return ctx->_.dir.end_reached;
if (ctx->_.file.last_handler != NULL
&& !ctx->_.file.last_handler->eof(ctx->_.file.last_handler_ctx))
return 0;
return BIO_eof(ctx->_.file.file);
}
static int file_close(OSSL_STORE_LOADER_CTX *ctx)
{
if ((ctx->flags & FILE_FLAG_ATTACHED) == 0) {
if (ctx->type == is_dir)
OPENSSL_DIR_end(&ctx->_.dir.ctx);
else
BIO_free_all(ctx->_.file.file);
} else {
/*
* Because file_attach() called file_find_type(), we know that a
* BIO_f_buffer() has been pushed on top of the regular BIO.
*/
BIO *buff = ctx->_.file.file;
/* Detach buff */
(void)BIO_pop(ctx->_.file.file);
/* Safety measure */
ctx->_.file.file = NULL;
BIO_free(buff);
}
OSSL_STORE_LOADER_CTX_free(ctx);
return 1;
}
/*-
* ENGINE management
*/
static const char *loader_attic_id = "loader_attic";
static const char *loader_attic_name = "'file:' loader";
static OSSL_STORE_LOADER *loader_attic = NULL;
static int loader_attic_init(ENGINE *e)
{
return 1;
}
static int loader_attic_finish(ENGINE *e)
{
return 1;
}
static int loader_attic_destroy(ENGINE *e)
{
OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader("file");
if (loader == NULL)
return 0;
ERR_unload_ATTIC_strings();
OSSL_STORE_LOADER_free(loader);
return 1;
}
static int bind_loader_attic(ENGINE *e)
{
/* Ensure the ATTIC error handling is set up on best effort basis */
ERR_load_ATTIC_strings();
if (/* Create the OSSL_STORE_LOADER */
(loader_attic = OSSL_STORE_LOADER_new(e, "file")) == NULL
|| !OSSL_STORE_LOADER_set_open_ex(loader_attic, file_open_ex)
|| !OSSL_STORE_LOADER_set_open(loader_attic, file_open)
|| !OSSL_STORE_LOADER_set_attach(loader_attic, file_attach)
|| !OSSL_STORE_LOADER_set_ctrl(loader_attic, file_ctrl)
|| !OSSL_STORE_LOADER_set_expect(loader_attic, file_expect)
|| !OSSL_STORE_LOADER_set_find(loader_attic, file_find)
|| !OSSL_STORE_LOADER_set_load(loader_attic, file_load)
|| !OSSL_STORE_LOADER_set_eof(loader_attic, file_eof)
|| !OSSL_STORE_LOADER_set_error(loader_attic, file_error)
|| !OSSL_STORE_LOADER_set_close(loader_attic, file_close)
/* Init the engine itself */
|| !ENGINE_set_id(e, loader_attic_id)
|| !ENGINE_set_name(e, loader_attic_name)
|| !ENGINE_set_destroy_function(e, loader_attic_destroy)
|| !ENGINE_set_init_function(e, loader_attic_init)
|| !ENGINE_set_finish_function(e, loader_attic_finish)
/* Finally, register the method with libcrypto */
|| !OSSL_STORE_register_loader(loader_attic)) {
OSSL_STORE_LOADER_free(loader_attic);
loader_attic = NULL;
ATTICerr(0, ATTIC_R_INIT_FAILED);
return 0;
}
return 1;
}
#ifdef OPENSSL_NO_DYNAMIC_ENGINE
# error "Only allowed as dynamically shared object"
#endif
static int bind_helper(ENGINE *e, const char *id)
{
if (id && (strcmp(id, loader_attic_id) != 0))
return 0;
if (!bind_loader_attic(e))
return 0;
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
diff --git a/crypto/openssl/include/crypto/bn.h b/crypto/openssl/include/crypto/bn.h
index c5f328156d3a..0b8489bb7550 100644
--- a/crypto/openssl/include/crypto/bn.h
+++ b/crypto/openssl/include/crypto/bn.h
@@ -1,125 +1,128 @@
/*
- * Copyright 2014-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 OSSL_CRYPTO_BN_H
# define OSSL_CRYPTO_BN_H
# pragma once
# include <openssl/bn.h>
# include <limits.h>
BIGNUM *bn_wexpand(BIGNUM *a, int words);
BIGNUM *bn_expand2(BIGNUM *a, int words);
void bn_correct_top(BIGNUM *a);
/*
* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
* This is an array r[] of values that are either zero or odd with an
* absolute value less than 2^w satisfying scalar = \sum_j r[j]*2^j where at
* most one of any w+1 consecutive digits is non-zero with the exception that
* the most significant digit may be only w-1 zeros away from that next
* non-zero digit.
*/
signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len);
int bn_get_top(const BIGNUM *a);
int bn_get_dmax(const BIGNUM *a);
/* Set all words to zero */
void bn_set_all_zero(BIGNUM *a);
/*
* Copy the internal BIGNUM words into out which holds size elements (and size
* must be bigger than top)
*/
int bn_copy_words(BN_ULONG *out, const BIGNUM *in, int size);
BN_ULONG *bn_get_words(const BIGNUM *a);
/*
* Set the internal data words in a to point to words which contains size
* elements. The BN_FLG_STATIC_DATA flag is set
*/
void bn_set_static_words(BIGNUM *a, const BN_ULONG *words, int size);
/*
* Copy words into the BIGNUM |a|, reallocating space as necessary.
* The negative flag of |a| is not modified.
* Returns 1 on success and 0 on failure.
*/
/*
* |num_words| is int because bn_expand2 takes an int. This is an internal
* function so we simply trust callers not to pass negative values.
*/
int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words);
/*
* Some BIGNUM functions assume most significant limb to be non-zero, which
* is customarily arranged by bn_correct_top. Output from below functions
* is not processed with bn_correct_top, and for this reason it may not be
* returned out of public API. It may only be passed internally into other
* functions known to support non-minimal or zero-padded BIGNUMs. Even
* though the goal is to facilitate constant-time-ness, not each subroutine
* is constant-time by itself. They all have pre-conditions, consult source
* code...
*/
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mont, BN_CTX *ctx);
+int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *in_mont);
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx);
int bn_from_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx);
int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m);
int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m);
int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);
int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n);
int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n);
int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
const BIGNUM *d, BN_CTX *ctx);
int ossl_bn_mask_bits_fixed_top(BIGNUM *a, int n);
int ossl_bn_is_word_fixed_top(const BIGNUM *a, const BN_ULONG w);
int ossl_bn_priv_rand_range_fixed_top(BIGNUM *r, const BIGNUM *range,
unsigned int strength, BN_CTX *ctx);
int ossl_bn_gen_dsa_nonce_fixed_top(BIGNUM *out, const BIGNUM *range,
const BIGNUM *priv,
const unsigned char *message,
size_t message_len, BN_CTX *ctx);
#define BN_PRIMETEST_COMPOSITE 0
#define BN_PRIMETEST_COMPOSITE_WITH_FACTOR 1
#define BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME 2
#define BN_PRIMETEST_PROBABLY_PRIME 3
int ossl_bn_miller_rabin_is_prime(const BIGNUM *w, int iterations, BN_CTX *ctx,
BN_GENCB *cb, int enhanced, int *status);
const BIGNUM *ossl_bn_get0_small_factors(void);
int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout,
BIGNUM *p1, BIGNUM *p2,
const BIGNUM *Xp, const BIGNUM *Xp1,
const BIGNUM *Xp2, int nlen,
const BIGNUM *e, BN_CTX *ctx,
BN_GENCB *cb);
int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
const BIGNUM *r1, const BIGNUM *r2,
int nlen, const BIGNUM *e, BN_CTX *ctx,
BN_GENCB *cb);
OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx);
extern const BIGNUM ossl_bn_inv_sqrt_2;
#endif
diff --git a/crypto/openssl/include/crypto/cmserr.h b/crypto/openssl/include/crypto/cmserr.h
index 1de2f9c7d51d..f53530ae2352 100644
--- a/crypto/openssl/include/crypto/cmserr.h
+++ b/crypto/openssl/include/crypto/cmserr.h
@@ -1,30 +1,30 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 OSSL_CRYPTO_CMSERR_H
# define OSSL_CRYPTO_CMSERR_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# ifdef __cplusplus
extern "C" {
# endif
# ifndef OPENSSL_NO_CMS
int ossl_err_load_CMS_strings(void);
# endif
# ifdef __cplusplus
}
# endif
#endif
diff --git a/crypto/openssl/include/openssl/cmserr.h b/crypto/openssl/include/openssl/cmserr.h
index f2d7708f10c8..52a186520fe4 100644
--- a/crypto/openssl/include/openssl/cmserr.h
+++ b/crypto/openssl/include/openssl/cmserr.h
@@ -1,124 +1,125 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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_CMSERR_H
# define OPENSSL_CMSERR_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# include <openssl/cryptoerr_legacy.h>
# ifndef OPENSSL_NO_CMS
/*
* CMS reason codes.
*/
# define CMS_R_ADD_SIGNER_ERROR 99
# define CMS_R_ATTRIBUTE_ERROR 161
# define CMS_R_CERTIFICATE_ALREADY_PRESENT 175
# define CMS_R_CERTIFICATE_HAS_NO_KEYID 160
# define CMS_R_CERTIFICATE_VERIFY_ERROR 100
# define CMS_R_CIPHER_AEAD_SET_TAG_ERROR 184
# define CMS_R_CIPHER_GET_TAG 185
# define CMS_R_CIPHER_INITIALISATION_ERROR 101
# define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 102
# define CMS_R_CMS_DATAFINAL_ERROR 103
# define CMS_R_CMS_LIB 104
# define CMS_R_CONTENTIDENTIFIER_MISMATCH 170
# define CMS_R_CONTENT_NOT_FOUND 105
# define CMS_R_CONTENT_TYPE_MISMATCH 171
# define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 106
# define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 107
# define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA 108
# define CMS_R_CONTENT_VERIFY_ERROR 109
# define CMS_R_CTRL_ERROR 110
# define CMS_R_CTRL_FAILURE 111
# define CMS_R_DECODE_ERROR 187
# define CMS_R_DECRYPT_ERROR 112
# define CMS_R_ERROR_GETTING_PUBLIC_KEY 113
# define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114
# define CMS_R_ERROR_SETTING_KEY 115
# define CMS_R_ERROR_SETTING_RECIPIENTINFO 116
+# define CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT 196
# define CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR 183
# define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117
# define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176
# define CMS_R_INVALID_KEY_LENGTH 118
# define CMS_R_INVALID_LABEL 190
# define CMS_R_INVALID_OAEP_PARAMETERS 191
# define CMS_R_KDF_PARAMETER_ERROR 186
# define CMS_R_MD_BIO_INIT_ERROR 119
# define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120
# define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 121
# define CMS_R_MSGSIGDIGEST_ERROR 172
# define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE 162
# define CMS_R_MSGSIGDIGEST_WRONG_LENGTH 163
# define CMS_R_NEED_ONE_SIGNER 164
# define CMS_R_NOT_A_SIGNED_RECEIPT 165
# define CMS_R_NOT_ENCRYPTED_DATA 122
# define CMS_R_NOT_KEK 123
# define CMS_R_NOT_KEY_AGREEMENT 181
# define CMS_R_NOT_KEY_TRANSPORT 124
# define CMS_R_NOT_PWRI 177
# define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 125
# define CMS_R_NO_CIPHER 126
# define CMS_R_NO_CONTENT 127
# define CMS_R_NO_CONTENT_TYPE 173
# define CMS_R_NO_DEFAULT_DIGEST 128
# define CMS_R_NO_DIGEST_SET 129
# define CMS_R_NO_KEY 130
# define CMS_R_NO_KEY_OR_CERT 174
# define CMS_R_NO_MATCHING_DIGEST 131
# define CMS_R_NO_MATCHING_RECIPIENT 132
# define CMS_R_NO_MATCHING_SIGNATURE 166
# define CMS_R_NO_MSGSIGDIGEST 167
# define CMS_R_NO_PASSWORD 178
# define CMS_R_NO_PRIVATE_KEY 133
# define CMS_R_NO_PUBLIC_KEY 134
# define CMS_R_NO_RECEIPT_REQUEST 168
# define CMS_R_NO_SIGNERS 135
# define CMS_R_PEER_KEY_ERROR 188
# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136
# define CMS_R_RECEIPT_DECODE_ERROR 169
# define CMS_R_RECIPIENT_ERROR 137
# define CMS_R_SHARED_INFO_ERROR 189
# define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 138
# define CMS_R_SIGNFINAL_ERROR 139
# define CMS_R_SMIME_TEXT_ERROR 140
# define CMS_R_STORE_INIT_ERROR 141
# define CMS_R_TYPE_NOT_COMPRESSED_DATA 142
# define CMS_R_TYPE_NOT_DATA 143
# define CMS_R_TYPE_NOT_DIGESTED_DATA 144
# define CMS_R_TYPE_NOT_ENCRYPTED_DATA 145
# define CMS_R_TYPE_NOT_ENVELOPED_DATA 146
# define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 147
# define CMS_R_UNKNOWN_CIPHER 148
# define CMS_R_UNKNOWN_DIGEST_ALGORITHM 149
# define CMS_R_UNKNOWN_ID 150
# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151
# define CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM 194
# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152
# define CMS_R_UNSUPPORTED_ENCRYPTION_TYPE 192
# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153
# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179
# define CMS_R_UNSUPPORTED_LABEL_SOURCE 193
# define CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE 155
# define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154
# define CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM 195
# define CMS_R_UNSUPPORTED_TYPE 156
# define CMS_R_UNWRAP_ERROR 157
# define CMS_R_UNWRAP_FAILURE 180
# define CMS_R_VERIFICATION_FAILURE 158
# define CMS_R_WRAP_ERROR 159
# endif
#endif
diff --git a/crypto/openssl/include/openssl/http.h b/crypto/openssl/include/openssl/http.h
index f7ab214265e4..c63762b70deb 100644
--- a/crypto/openssl/include/openssl/http.h
+++ b/crypto/openssl/include/openssl/http.h
@@ -1,109 +1,110 @@
/*
* Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Siemens AG 2018-2020
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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_HTTP_H
# define OPENSSL_HTTP_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/bio.h>
# include <openssl/asn1.h>
# include <openssl/conf.h>
# ifdef __cplusplus
extern "C" {
# endif
# define OSSL_HTTP_NAME "http"
# define OSSL_HTTPS_NAME "https"
# define OSSL_HTTP_PREFIX OSSL_HTTP_NAME"://"
# define OSSL_HTTPS_PREFIX OSSL_HTTPS_NAME"://"
# define OSSL_HTTP_PORT "80"
# define OSSL_HTTPS_PORT "443"
# define OPENSSL_NO_PROXY "NO_PROXY"
# define OPENSSL_HTTP_PROXY "HTTP_PROXY"
# define OPENSSL_HTTPS_PROXY "HTTPS_PROXY"
-#define OSSL_HTTP_DEFAULT_MAX_LINE_LEN (4 * 1024)
-#define OSSL_HTTP_DEFAULT_MAX_RESP_LEN (100 * 1024)
+# define OSSL_HTTP_DEFAULT_MAX_LINE_LEN (4 * 1024)
+# define OSSL_HTTP_DEFAULT_MAX_RESP_LEN (100 * 1024)
+# define OSSL_HTTP_DEFAULT_MAX_CRL_LEN (32 * 1024 * 1024)
/* Low-level HTTP API */
OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size);
void OSSL_HTTP_REQ_CTX_free(OSSL_HTTP_REQ_CTX *rctx);
int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx, int method_POST,
const char *server, const char *port,
const char *path);
int OSSL_HTTP_REQ_CTX_add1_header(OSSL_HTTP_REQ_CTX *rctx,
const char *name, const char *value);
int OSSL_HTTP_REQ_CTX_set_expected(OSSL_HTTP_REQ_CTX *rctx,
const char *content_type, int asn1,
int timeout, int keep_alive);
int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type,
const ASN1_ITEM *it, const ASN1_VALUE *req);
int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx);
int OSSL_HTTP_REQ_CTX_nbio_d2i(OSSL_HTTP_REQ_CTX *rctx,
ASN1_VALUE **pval, const ASN1_ITEM *it);
BIO *OSSL_HTTP_REQ_CTX_exchange(OSSL_HTTP_REQ_CTX *rctx);
BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx);
size_t OSSL_HTTP_REQ_CTX_get_resp_len(const OSSL_HTTP_REQ_CTX *rctx);
void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx,
unsigned long len);
int OSSL_HTTP_is_alive(const OSSL_HTTP_REQ_CTX *rctx);
/* High-level HTTP API */
typedef BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail);
OSSL_HTTP_REQ_CTX *OSSL_HTTP_open(const char *server, const char *port,
const char *proxy, const char *no_proxy,
int use_ssl, BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, int overall_timeout);
int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
const char *proxyuser, const char *proxypass,
int timeout, BIO *bio_err, const char *prog);
int OSSL_HTTP_set1_request(OSSL_HTTP_REQ_CTX *rctx, const char *path,
const STACK_OF(CONF_VALUE) *headers,
const char *content_type, BIO *req,
const char *expected_content_type, int expect_asn1,
size_t max_resp_len, int timeout, int keep_alive);
BIO *OSSL_HTTP_exchange(OSSL_HTTP_REQ_CTX *rctx, char **redirection_url);
BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, const STACK_OF(CONF_VALUE) *headers,
const char *expected_content_type, int expect_asn1,
size_t max_resp_len, int timeout);
BIO *OSSL_HTTP_transfer(OSSL_HTTP_REQ_CTX **prctx,
const char *server, const char *port,
const char *path, int use_ssl,
const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
int buf_size, const STACK_OF(CONF_VALUE) *headers,
const char *content_type, BIO *req,
const char *expected_content_type, int expect_asn1,
size_t max_resp_len, int timeout, int keep_alive);
int OSSL_HTTP_close(OSSL_HTTP_REQ_CTX *rctx, int ok);
/* Auxiliary functions */
int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
char **pport, int *pport_num,
char **ppath, char **pquery, char **pfrag);
int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost,
char **pport, int *pport_num,
char **ppath, char **pquery, char **pfrag);
const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy,
const char *server, int use_ssl);
# ifdef __cplusplus
}
# endif
#endif /* !defined(OPENSSL_HTTP_H) */
diff --git a/crypto/openssl/providers/fips-sources.checksums b/crypto/openssl/providers/fips-sources.checksums
index 2075eca274d6..1ab5d0348c6c 100644
--- a/crypto/openssl/providers/fips-sources.checksums
+++ b/crypto/openssl/providers/fips-sources.checksums
@@ -1,595 +1,595 @@
0e22ea0cf34ef3871e30df0bc302dc29352d38001d1622ddb78a27a374b6aee8 crypto/aes/aes_cbc.c
c049a936d74100fcced225f575d46662792a6a0039777d2d4df0cf61eff90a68 crypto/aes/aes_core.c
3fac41ce96acb9189eac2d5571425c3ff33a34c884ae7e275e1fd3068b5fc662 crypto/aes/aes_ecb.c
c1e674d08683a25bc053f6233f73a0d0b3a90aafe591ff57b702c7da1582e4a5 crypto/aes/aes_local.h
a2466f18da5847c7d9fbced17524633c10ce024671a72f53f9c9c55b9b9923dd crypto/aes/aes_misc.c
6979c133f76f4623e62e6e970deae70fa025e713a72b71aead5a048d49e47f6f crypto/aes/asm/aes-586.pl
-2eef5f20f1410b48bdaaafa24ded24f56f34c4ca79db1d38fa6bf1b3b19535bf crypto/aes/asm/aes-armv4.pl
-38c2cf8ed3910efd89d8721e1b0763a8fde073b91f6529d251165a0496ef9555 crypto/aes/asm/aes-c64xplus.pl
+92be9ff608331a432e95247a8f4fb9e46897d0cb76f2b6db809b61d44287964a crypto/aes/asm/aes-armv4.pl
+953897f86e2de9fa27ef411155ab3aed133af94885f1507e76449c142da78656 crypto/aes/asm/aes-c64xplus.pl
00196f01f5218ad731e6a058d406078f7228a9756d9d73f51c0d0c2a68f885af crypto/aes/asm/aes-ia64.S
-b4ef595194fe1692e1ab2b561f385da01b277cf004902e8fc99e8ac5389bbd35 crypto/aes/asm/aes-mips.pl
-123c4498c94040b70708fdd911cb08c6411b020b4cf3eb761d6fa22c583c3e6f crypto/aes/asm/aes-parisc.pl
-7a7f2f90791415ef4ffc1ba2a6f6b6fe994bfe0e03d3bf9dab6e428e6874695c crypto/aes/asm/aes-ppc.pl
-d139e5ad69560fd0ffd8aa2e72304e463650cea4c657be7a90e0d1eb782d580a crypto/aes/asm/aes-s390x.pl
-133ba35d77002abcd430414749c4e98c4a319630da898e45ff8dbc5800176df1 crypto/aes/asm/aes-sparcv9.pl
-c98690249d490d23e6fee84f672f1463ffc029427110a4329244a59e4e4aaed8 crypto/aes/asm/aes-x86_64.pl
-7ec99947b47e56595f0b085b8bda0b3113112f694e78b1f71b63ecd1f0fa2c67 crypto/aes/asm/aesfx-sparcv9.pl
-ab94a27e533e164bcf09898a6f6019f43609d51a3b374cf75482dcf2914d464e crypto/aes/asm/aesni-mb-x86_64.pl
-74939261340a0056eb9333fff1c843c8758b9f93de3d94650cd6d2899c6790d8 crypto/aes/asm/aesni-sha1-x86_64.pl
-ce91f0893a2a35fdf4c024ccb0fd8329b30fdbd955f0ae011ab948101ee14951 crypto/aes/asm/aesni-sha256-x86_64.pl
+88b6f8396cd9d86004743d5c3b0f72b7b8c3d5a2b00b0bbb761ba91ae5a7cdc8 crypto/aes/asm/aes-mips.pl
+7ff9c96ef3d591d45d776fa4b244601ea0d9328e289aeab1e1b92436ce7d02ad crypto/aes/asm/aes-parisc.pl
+f1244cdeadcb4e48f35bc5df19d4cfaf07e0086ad951b84f07ff6966501faa5b crypto/aes/asm/aes-ppc.pl
+ecbfe826f4c514810c3ee20e265f4f621149694c298554b2682e5de4f029f14f crypto/aes/asm/aes-s390x.pl
+ee4e8cacef972942d2a89c1a83c984df9cad87c61a54383403c5c4864c403ba1 crypto/aes/asm/aes-sparcv9.pl
+2b3b9ac56bf54334d053857a24bdb08592151e8a7a60b89b8195846b7f8ee7b5 crypto/aes/asm/aes-x86_64.pl
+c56c324667b67d726e040d70379efba5b270e2937f403c1b5979018b836903c7 crypto/aes/asm/aesfx-sparcv9.pl
+14359dc32b7f4e5c08227fb9ac8f9232c1287399463b233fec4a2ab0c19f68d1 crypto/aes/asm/aesni-mb-x86_64.pl
+2fe016e8098d1c959b6199ce98e91dfed9a3a543d6b068daf88d4c4c402701ec crypto/aes/asm/aesni-sha1-x86_64.pl
+1d3acabadedb88d1327eeb76201ea9b3f4814f44898018ffae6c73e3f400b89b crypto/aes/asm/aesni-sha256-x86_64.pl
4ff74d4e629a88ef5a9e3d3f5b340fc0a4793d16d7cc7f1b70da62512a856248 crypto/aes/asm/aesni-x86.pl
-30103cfe3b29d06b34feff48a927e0fa649e9109d35a3db64b09cfeb15426fa2 crypto/aes/asm/aesni-x86_64.pl
-f3490c936a80e012c49e577ec6e1d4d36df324dfef6264e788e6225e20b5fd52 crypto/aes/asm/aesp8-ppc.pl
-a5807ed92ec8a16d123061487c385bf1f65e50878cee95c8e8096844454129f8 crypto/aes/asm/aest4-sparcv9.pl
-d34cf129a8c63e2b77a74117ed4440a4f35408dabd90e21e70eae92d208fa516 crypto/aes/asm/aesv8-armx.pl
-a0b578b7d2787c91013547df07dfa73d8d7a420446dd624c66f7c55159817eb2 crypto/aes/asm/bsaes-armv7.pl
-34accd08242a6bf4a751105f89b0c4de2cd7e54320753587815647abff7124de crypto/aes/asm/bsaes-x86_64.pl
-d9bc047db9b2f54f27fe0d6e2ede9239b4a1f57a14bf89fa3cfba6b836599386 crypto/aes/asm/vpaes-armv8.pl
-516421b1a321b842f879ad69e7b82ae3e1f3efc8288c83bb34d6577996e85787 crypto/aes/asm/vpaes-ppc.pl
+c7c6694480bb5319690f94826139a93f5c460ebea6dba101b520a76cb956ec93 crypto/aes/asm/aesni-x86_64.pl
+0489a10fbb1a8ca3652848d5c1e14e519501e189bad3e5827a573c26df359691 crypto/aes/asm/aesp8-ppc.pl
+e397a5781893e97dd90a5a52049633be12a43f379ec5751bca2a6350c39444c8 crypto/aes/asm/aest4-sparcv9.pl
+e3955352a92d56905d63e68937e4758f13190a14a10a3dcb1e5c641c49913c0c crypto/aes/asm/aesv8-armx.pl
+5e8005fdb6641df465bdda20c3476f7176e6bcd63d5073044a0c02a327c7f172 crypto/aes/asm/bsaes-armv7.pl
+0726a2c4c15c27a12b2f7d5e16863df4a1b1daa7b7d9b728f621b2b224d290e6 crypto/aes/asm/bsaes-x86_64.pl
+1ff94d6bf6c8ae4809f64657eb89260fe3cb22137f649d3c73f72cb190258196 crypto/aes/asm/vpaes-armv8.pl
+c3541865cd02d81101cdbab4877ed82772e6980d2c677b9008b38fa1b26d36d4 crypto/aes/asm/vpaes-ppc.pl
3ec24185750a995377516bc2fb2eae8b1c52094c6fff093bff591837fc12d6c3 crypto/aes/asm/vpaes-x86.pl
-47bedbe6a04254eede121e71f11a657b1f1940aee1916bbfc04fa9fb8454f9b8 crypto/aes/asm/vpaes-x86_64.pl
-1c9a2a0e8cee4a1283c74b2e306f46f79890f6d236394de2a80d1994fd411d1d crypto/alphacpuid.pl
-7a37cadacdbecb50304228dfcb087ad7fbb6e31f6ab69c52dd161e79afb2f9ca crypto/arm64cpuid.pl
+060bb6620f50af9afecdf97df051b45b9a50be9daf343dfec1cbb29693ce00a4 crypto/aes/asm/vpaes-x86_64.pl
+2bc67270155e2d6c7da87d9070e005ee79cea18311004907edfd6a078003532a crypto/alphacpuid.pl
+0255a480b78bdcc71f76676f496962a9828eb900f53b7be13be96ae3f67fe6db crypto/arm64cpuid.pl
e0daf54f72dd8fd1bc537d93f34e2a6a887a9ed6027bb33e15a327ef5ff37a42 crypto/armcap.c
-24cc7611225df0e20e414c14e80516c36d48bf99659946e85a876d8757356686 crypto/armv4cpuid.pl
+a43f2c1eef16146943745f684f2add7d186924932a47abf7fb0760cba02804e6 crypto/armv4cpuid.pl
16739d54200fb81ca7835b5814f965022a2ab41589c7787e2697e3ea72d4fafa crypto/asn1_dsa.c
-155eff9d747eed808398cfa2af4b276dfc1f9aac8a0f9d801b314ab3f2bf5b56 crypto/bn/asm/alpha-mont.pl
-894cc71b2d783e4e1b54dbef45e9e9280165a2c43981ebdd03282f0e90914928 crypto/bn/asm/armv4-gf2m.pl
-0d2e31dc9cdce02c619adfc9ac720ccf7171384e76a84cdf0e686a805dd7006e crypto/bn/asm/armv4-mont.pl
-d7df31176f725c1ae7241fee8f681fdcf2ab9eb4d3cc6c80d49c2248ae40a56a crypto/bn/asm/armv8-mont.pl
+819c9fd2b0cae9aab81c3cbd1815c2e22949d75f132f649b5883812d0bbaa39a crypto/bn/asm/alpha-mont.pl
+0070595128b250b9ebdebe48ce53d2d27ca16ec4f7c6c8bd169ab2e4a913b2d1 crypto/bn/asm/armv4-gf2m.pl
+8c1c53a725b8a4f92b8a353bfeeb393be94198df41c912e3270f9e654417b250 crypto/bn/asm/armv4-mont.pl
+a0d926004bddb4613552ffa325fac57ab64b085255f2e72881d8478f55890f5a crypto/bn/asm/armv8-mont.pl
cb4ad7b7461fcb8e2a0d52881158d0211b79544842d4eae36fc566869a2d62c8 crypto/bn/asm/bn-586.pl
-10fb73a6cc1bc064ebdcf6d7fe3c7407ea1c28b0d65ad0123046f8b1518fa75a crypto/bn/asm/c64xplus-gf2m.pl
+636da7e2a66272a81f9c99e90b36c6f132ad6236c739e8b9f2e7315f30b72edd crypto/bn/asm/c64xplus-gf2m.pl
c86664fb974362ee52a454c83c2c4b23fd5b7d64b3c9e23ef1e0dfd130a46ee5 crypto/bn/asm/co-586.pl
-b88190d748056e6a64988bf1a3d19efc4c292e3d338a65f4505cf769a2041077 crypto/bn/asm/ia64-mont.pl
+199b9b100f194a2a128c14f2a71be5a04d50d069666d90ca5b69baee1318ccb7 crypto/bn/asm/ia64-mont.pl
a511aafbf76647a0c83705d4491c898a5584d300aa449fa6166c8803372946eb crypto/bn/asm/ia64.S
-fee42cabeeb87cdf0fa0a6ff3698b2fe98a8a47d10a756052df572097161a8b9 crypto/bn/asm/mips-mont.pl
-b197a8e1be79b8c21f8d26b34b9a282ca42ec4bcd1f3212fde3889747082a1f7 crypto/bn/asm/mips.pl
-13df09cee06a21669137294f92e5c31b4bf05a8035be6800c1cb4403d7cd8290 crypto/bn/asm/parisc-mont.pl
-25c96e545b4981d45557eb14ea5c83aa2d6375ae0df806cb6e6ded2f59ddfed3 crypto/bn/asm/ppc-mont.pl
-1c057083546fa1a3bb1b9819dc5110f5a3b11b7bf5a2fb275012323bd7412403 crypto/bn/asm/ppc.pl
+687c5d6606fdfd0e242005972d15db74a9cbac2b8a9a54a56fcb1e99d3880ff3 crypto/bn/asm/mips-mont.pl
+8aca83d2ec45a40af15e59cff1ac2dc33737a3d25f0a0b74d401fa778a5c5eb8 crypto/bn/asm/mips.pl
+b27ec5181e387e812925bb26823b830f49d7a6e4971b6d11ea583f5632a1504b crypto/bn/asm/parisc-mont.pl
+9973523b361db963eea4938a7a8a3adc692e1a4e1aec4fa1f1e57dc93da37921 crypto/bn/asm/ppc-mont.pl
+59cd27e1e10c4984b7fb684b27f491e7634473b1bcff197a07e0ca653124aa9a crypto/bn/asm/ppc.pl
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 crypto/bn/asm/ppc64-mont-fixed.pl
-fe9278a2504fb40257637a4718081775c29c4eb81f87a8528e5c85f8d0c6281a crypto/bn/asm/ppc64-mont.pl
-94b2d5cf0faf2efddeb5fb7c575dabc35c1791715cc9299d59a01d9f96cb2d6f crypto/bn/asm/rsaz-avx2.pl
-cd0861a565231f67252e172420f6914fe47a324b35916c29f6304491447fe84c crypto/bn/asm/rsaz-avx512.pl
-c19c717d87dd1ba74f138af05c044c05f5d025e26323637f46ba54a8c871a378 crypto/bn/asm/rsaz-x86_64.pl
-ae26becda9f6d30e9edde8bb89c251a0c40a9a6c879c4cdaec273d8c09af9cd6 crypto/bn/asm/s390x-gf2m.pl
-2700337ef133d6688047a1a8e1c671db06016aae777679923ce2b301896762cf crypto/bn/asm/s390x-mont.pl
+a25be64867ab837d93855af232e2bfa71b85b2c6f00e35e620fdc5618187fb6f crypto/bn/asm/ppc64-mont.pl
+231579e532443665020d4d522d9f11713d9c5d5c814b95b434b0f65452e16de4 crypto/bn/asm/rsaz-avx2.pl
+1657600d320ea549b527b2d878a7658533d60d26eeb38f42ea470fc612f9bb53 crypto/bn/asm/rsaz-avx512.pl
+31e84dc905b13e38850071528d3abbfcaf8910bbc8b46f38d19c2b386a5f838e crypto/bn/asm/rsaz-x86_64.pl
+30fedf48dfc5fec1c2044b6c226dd9fc42a92522cc589797a23a79d452bdd2cf crypto/bn/asm/s390x-gf2m.pl
+590388d69d7ac3a0e9af4014792f4f0fdb9552719e8fb48ebc7e5dfca2a491d4 crypto/bn/asm/s390x-mont.pl
aa02597f3dc09cfbc190aedb75711859ba0f3efff87067ebfba1ec78ebee40d7 crypto/bn/asm/s390x.S
-87d49e83a7df467097fdfc577aa206be9ee622c40fcbbbe5133b35d9783b7816 crypto/bn/asm/sparct4-mont.pl
+2f7cbc2c3d93b1bbc4953dda38b9ae0ab3a0a8331a0418d94d9b286183736c9e crypto/bn/asm/sparct4-mont.pl
ca21a9ccbc54e19fb7c2e6cdf286ce7cb08b0fba960c777c6edce5c57ccc2101 crypto/bn/asm/sparcv8.S
fbc93c8dbbecefe66086f58fe9719ed87b13b2cdc61454a10e841228296fecef crypto/bn/asm/sparcv8plus.S
-2ec1497fa06826f7bc574239e425dd8dda0d4a2743e1fe87669ede900291fcb6 crypto/bn/asm/sparcv9-gf2m.pl
-1f490fe184c7a51b2d0646a59e69aa659bfe51270ad21594951b8d7b785bac38 crypto/bn/asm/sparcv9-mont.pl
-277dcb7faa1913b25fd43946c50039bcdd45cb643fd9ddeedd6c207cefa4dd50 crypto/bn/asm/sparcv9a-mont.pl
+127832c1e3d298aad805236776488f5f8836b6a0fdbce3f6b42678163df3909f crypto/bn/asm/sparcv9-gf2m.pl
+1622f04a8918724ac0e8804baf285fdafa0eeaaecc36c7facd459d0ff13a8cac crypto/bn/asm/sparcv9-mont.pl
+b69083f78b4b4f7097de4462d16649532fb82c453a82cdd9cc1393122661d6e2 crypto/bn/asm/sparcv9a-mont.pl
d404375a21d33396824a3da212d6646d4f3150dd141ee4b4a250aefae3482efb crypto/bn/asm/via-mont.pl
-d632edf9b9bab7d2cd2d616512a98d15cf4b3ebba7a8e7b83650d654ceb52ecb crypto/bn/asm/vis3-mont.pl
+d24f3e97239c8eed5efc721521b025b7256c15e67a54ea6b5c4cf8f7cd0f89ea crypto/bn/asm/vis3-mont.pl
89278854f44d95be916516609ce6f79dcd346bab52574b9b6336a9952aa94bee crypto/bn/asm/x86-gf2m.pl
90d4ae234c08267adce9ed38d56e0edc223f7480cb9605f5d7399d0b3914c6be crypto/bn/asm/x86-mont.pl
d444ca73875e97e0ea88b20e4c02f2fcf3850e8b9311e3b67a2d04fe2796d543 crypto/bn/asm/x86_64-gcc.c
-a5481ca55d94dc7ebdc93173610d38ae2569cea1fe9b5180debe0ab94e455ce1 crypto/bn/asm/x86_64-gf2m.pl
-d8cc080824a72774cb3343a3d50ddf8f41a5b8321203d4c9a764762b62498b96 crypto/bn/asm/x86_64-mont.pl
-03788cb685268e6a50ddfa742ea1fe937570c9b86f2ebc88ee35f3304f67c045 crypto/bn/asm/x86_64-mont5.pl
+709ddee92e9222ee0ed27bfb90db556e85e2d302e4a9131afa25fdc14c4d858f crypto/bn/asm/x86_64-gf2m.pl
+da7f7780d27eed164797e5334cd45b35d9c113e86afaca051463aef9a8fd787c crypto/bn/asm/x86_64-mont.pl
+259fb8d7f40c0dba46920b1f169d5b37de03b0fda645463d19e3ae2b56de851d crypto/bn/asm/x86_64-mont5.pl
0ea8185a037a2951bb3d1e590bbbdeac305176d5e618f3e43a04c09733a9de34 crypto/bn/bn_add.c
759c2b9df808b3562fe8b0c7778dbadbf35f261e14fc2d5090d18c35b4181760 crypto/bn/bn_asm.c
14bd5a35c05fcf454854b92fb30b356d7ac618c1eb699dd798f6ad2936d1f5ee crypto/bn/bn_blind.c
7b761d541e3b7f6a3f2b14a09b2b3836a079a845cf67a54db4853e3fd38277c6 crypto/bn/bn_const.c
58b587e20404efa408b31a88ba9c357059ced709bea78c07deb91df7b687db81 crypto/bn/bn_conv.c
2893b6d03d4850d09c15959941b0759bbb50d8c20e873bed088e7cde4e15a65a crypto/bn/bn_ctx.c
d94295953ab91469fe2b9da2a542b8ea11ac38551ecde8f8202b7f645c2dea16 crypto/bn/bn_dh.c
74b63a4515894592b7241fb30b91b21510beaa3d397809e3d74bc9a73e879d18 crypto/bn/bn_div.c
-49e59eac540db304ab0ca7bee3ba9d45f89548fff98155561bbdb6602d0aab1d crypto/bn/bn_exp.c
+46357d2d30109ae59482332adf604a5ef1bd64c7de08cc808db028c45190ba93 crypto/bn/bn_exp.c
ec2b6e3af6df473a23e7f1a8522f2554cb0eb5d34e3282458c4a66d242278434 crypto/bn/bn_exp2.c
baba7c8ae95af6aa36bc9f4be3a2eed33d500451e568ca4bfc6bc7cb48d4f7ea crypto/bn/bn_gcd.c
-5fbb1ab8463cd5544a1d95cf7996b6387ae634984a42256b7a21482ce3ac30a2 crypto/bn/bn_gf2m.c
+99325cf50bf72b5d77048c20d7fa4f80a179dc6357023745f9a58c8e914ae136 crypto/bn/bn_gf2m.c
081e8a6abc23599307dab3b1a92113a65e0bf8717cbc40c970c7469350bc4581 crypto/bn/bn_intern.c
602ed46fbfe12c899dfb7d9d99ff0dbfff96b454fce3cd02817f3e2488dd9192 crypto/bn/bn_kron.c
81a4afc27dd1e90c4bfa81c8d385214ce8a2b5884537752944a71ebebd91f4b0 crypto/bn/bn_lib.c
d5beb9fbac2ff5dc3ccbdfa4d1aabca7225c778cff4e3b05b6d6c63e182637f5 crypto/bn/bn_local.h
96f98cdf50087c5b567c31bf2581728623206d79b3f97f5a0c5fdaa0009e6e3c crypto/bn/bn_mod.c
f60f3d49b183b04bcdf9b82f7c961b8c1bcb00e68a2c1166fe9edd95a783356e crypto/bn/bn_mont.c
2da73a76b746a47d8cf8ec8b3e0708c2a34e810abde4b4f1241a49e7f5bb2b60 crypto/bn/bn_mpi.c
76982b18b0803d59b33168b260677e7412970757d3b9513de5c80025290f211d crypto/bn/bn_mul.c
b3677b73ac29aab660c9a549f7af154ca14347fac5cffd43b153a75211f1373f crypto/bn/bn_nist.c
c6760a724d696b7209f0a71f8483fabcf4f081f7e93e2628284c32ef78f69365 crypto/bn/bn_prime.c
c56ad3073108a0de21c5820a48beae2bccdbf5aa8075ec21738878222eb9adc3 crypto/bn/bn_prime.h
71186d5bd40d467a919e6449d8aa23d13df88e0c85765d1a165f3eeec6bd33a7 crypto/bn/bn_rand.c
4df8f204c8a06de2b4395be613ca0b9943613c523586e2005876d5c7bb891c75 crypto/bn/bn_recp.c
a5c5c9f99961a5a7f22a3dcdce964c8a330f822be17f08652223a20fed747d0a crypto/bn/bn_rsa_fips186_4.c
6889866bca4673bccb8adf870859a867757ccd3c8ad4652675615afff710add3 crypto/bn/bn_shift.c
622e90766b29e0d25f46474429aebda8eba2246835b9e85dc26da7cdbd49334f crypto/bn/bn_sqr.c
42c8ce944c889abcfcf089d0ad2744b7587696d8d7785efa91b3f7ec53dc062a crypto/bn/bn_sqrt.c
24e62baa56e02f2db6454e10168b7c7fa7638db9221b9acda1803d43f38f36e0 crypto/bn/bn_word.c
be27115efd36f0077a3ec26b1ff1f586b0b8969ba05d8ffa34b2ff4badf227bf crypto/bn/rsaz_exp.c
c4d64da1cdc732ea918fccd6a7bb2746b03365dd26f7ba1e74e08c307ca4c58e crypto/bn/rsaz_exp.h
-5b82cb8dbf3087c2e671871cb0a92e4039223a51af533a2ee996f3bfd47453a7 crypto/bn/rsaz_exp_x2.c
+9bc3bf8965f98915f9019d2f516345e73c435c5bd8ad94bb4b7057809a7d1383 crypto/bn/rsaz_exp_x2.c
834db8ff36006e5cb53e09ca6c44290124bd23692f4341ea6563b66fcade4cea crypto/bsearch.c
c39334b70e1394e43f378ae8d31b6e6dc125e4d9181e6536d38e649c4eaadb75 crypto/buffer/buffer.c
-d2bfdfd96b182741d2d51f91478ffcc48491b0da44662bc1c32bc506b3eef1ba crypto/c64xpluscpuid.pl
+5f43844b5d8665de9ab895f93599150a327d73ec2674bbf7d7c512d30163022d crypto/c64xpluscpuid.pl
0e1a41a2d81b5765bca3df448f60bf1fad91e485fe89dd65a7300ffc419e316d crypto/cmac/cmac.c
5113d8d12d884f845cad3d35d92f0a1ee20ebafd7a169273642f4e8178711de9 crypto/context.c
c309d81ea991ddf5be4337afad2fd132169f7443c76f863349d3f3c82f3374e4 crypto/core_algorithm.c
-f0fd9eb38bf7f196bbb4d26ce8fdf86d0a4f9db219157e66b2c0ffefb4f42005 crypto/core_fetch.c
+65ba41169f8fec7cb8466c3458721e3150057fb587db087a70752e5e08201381 crypto/core_fetch.c
799c84d224639c6760c5c28e0e287500a973ca6d0c3d7c1bdcd61b0da4018b3c crypto/core_namemap.c
469e2f53b5f76cd487a60d3d4c44c8fc3a6c4d08405597ba664661ba485508d3 crypto/cpuid.c
71f0fff881eb4c5505fb17662f0ea4bbff24c6858c045a013ad8f786b07da5c4 crypto/cryptlib.c
66dbfc58916709d5a6913777346083247942a8d9458ee9b2bf443f0ea4988d64 crypto/ctype.c
51e56541daea6d4a26d5bae2ea458414063bf08b045bab8df370f6695903e0a5 crypto/der_writer.c
fea3ba4225df97aee90690adf387625b746d8edfdc5af2357ee65151a3d236ac crypto/des/des_enc.c
4971cdc016ee262d81e31f96c1617a33a63c0d90139e440c2ff32a368ee07bbd crypto/des/des_local.h
eeef5722ad56bf1af2ff71681bcc8b8525bc7077e973c98cee920ce9bcc66c81 crypto/des/ecb3_enc.c
04d4cc355200b57f1e7d265a2cebdf094df1eb6e96621b533adddc3d60d31fbe crypto/des/fcrypt_b.c
499513b3ad386fe694c4e04b3c8a9fd4c4e18fc44bb6c4f94d6bf2d9362a3a5a crypto/des/ncbc_enc.c
61926e30dd940616e80936d1c94c5f522daf0d475fb3a40a9e589e78f322901e crypto/des/set_key.c
8344811b14d151f6cd40a7bc45c8f4a1106252b119c1d5e6a589a023f39b107d crypto/des/spr.h
816472a54c273906d0a2b58650e0b9d28cc2c8023d120f0d77160f1fe34c4ca3 crypto/dh/dh_backend.c
24cf9462da6632c52b726041271f8a43dfb3f74414abe460d9cc9c7fd2fd2d7d crypto/dh/dh_check.c
7838e9a35870b0fbcba0aff2f52a2439f64d026e9922bce6e5978c2f22c51120 crypto/dh/dh_gen.c
6b17861887b2535159b9e6ca4f927767dad3e71b6e8be50055bc784f78e92d64 crypto/dh/dh_group_params.c
a5cf5cb464b40f1bc5457dc2a6f2c5ec0f050196603cd2ba7037a23ab64adbf7 crypto/dh/dh_kdf.c
b0c248efc7dad48eaceb939a18cb2592cbfe5b02dd406592e5e590645488b153 crypto/dh/dh_key.c
92345c259ea2a8c09e6d6b069d0942bd6ca4642231580f3e8148ae7a832a1115 crypto/dh/dh_lib.c
8300775d88db0a1aa26a77eb49d6c4f7252e7fee69e1440de4c40edadc9da044 crypto/dh/dh_local.h
bbcf4fc3067ac462a27d7277973180b7dc140df9262a686c7fbe4318ca01f7b8 crypto/dsa/dsa_backend.c
786d6c65ced7ee4e25f5dd7c3150259ec95b6aa321a7590d905757b8139f8230 crypto/dsa/dsa_check.c
ae727bf6319eb57e682de35d75ea357921987953b3688365c710e7fba51c7c58 crypto/dsa/dsa_gen.c
b1de1624e590dbf76f76953802ff162cc8de7c5e2eaba897313c866424d6902b crypto/dsa/dsa_key.c
9f4837c5abe53613a2dc1c5db81d073d4f42bd28b6a2d1e93a2b350d8e25d52a crypto/dsa/dsa_lib.c
f4d52d3897219786c6046bf76abb2f174655c584caa50272bf5d281720df5022 crypto/dsa/dsa_local.h
196dc024873e413d92672c3a9b6c062ed6269250b0da6d41c0da1c03cfec9ef8 crypto/dsa/dsa_ossl.c
9f501a59c09fc3cb3caafaff25abd44397a94d1062950a4d62e855d2c8986b5a crypto/dsa/dsa_sign.c
53fa10cc87ac63e35df661882852dc46ae68e6fee83b842f1aeefe00b8900ee1 crypto/dsa/dsa_vrf.c
-786779d7014bc04846832f80638743784a3850c7ee36e4a8062fe8eb7ac31c9b crypto/ec/asm/ecp_nistp521-ppc64.pl
-2e3056ea14fab8b306b0281d6a6f4317a6e86dbf652a79ade726e716cd79bb1e crypto/ec/asm/ecp_nistz256-armv4.pl
-a02edef19d22c5aba196080942111ab0172fc2ebe6d6c40db2beb6a1a2d885c6 crypto/ec/asm/ecp_nistz256-armv8.pl
-729729f8233c95138158f4647b33a36cf175e707ce29563db0eedc811f324ec0 crypto/ec/asm/ecp_nistz256-ppc64.pl
-78a5b172f7c13ae8ac622439ffb9d99b240dbb4bbda3f5c88d1533ae74a445ad crypto/ec/asm/ecp_nistz256-sparcv9.pl
+d9722ad8c6b6e209865a921f3cda831d09bf54a55cacd1edd9802edb6559190a crypto/ec/asm/ecp_nistp521-ppc64.pl
+78ad06b88fcc8689a3a846b82f9ee01546e5734acd1bccf2494e523b71dc74d1 crypto/ec/asm/ecp_nistz256-armv4.pl
+4617351d2de4d0b2abfd358c58050cee00702d0b4c1acca09312ec870e351c7d crypto/ec/asm/ecp_nistz256-armv8.pl
+3715ddd921425f3018741037f01455ed26a840ace08691a800708170a66cf4d2 crypto/ec/asm/ecp_nistz256-ppc64.pl
+cfe7e75a2fddc87a7251684469a8808b9da82b2f5725eafad5806920f89932bd crypto/ec/asm/ecp_nistz256-sparcv9.pl
922725c4761cfa567af6ed9ecab04f2c7729ae2595f2fc0fa46dc67879dc87b0 crypto/ec/asm/ecp_nistz256-x86.pl
-19ba01af58788e2873ebc1d5b503a76604bec0b9b6296fa794946e141fc945a4 crypto/ec/asm/ecp_nistz256-x86_64.pl
-e806141073aa3792e2748f6feeee6d3017124b3bc6059a9eca0d53a2f5785346 crypto/ec/asm/x25519-ppc64.pl
-a397592dc9fdb13016311db6184b4a3a4f2e198aacb03528f770f30ea4966cc4 crypto/ec/asm/x25519-x86_64.pl
+ac327475c7ec828d11aa05628b4e3b81ec3b1400f30fe7bec01daf3cf71f2dc9 crypto/ec/asm/ecp_nistz256-x86_64.pl
+cc727533130f5f1a29229929b3d4e8454585d647be25d6344f3c6a0240998368 crypto/ec/asm/x25519-ppc64.pl
+ee897e230964511baa0d1bf95fb938312407a40a88ebe01476879c2763e5f732 crypto/ec/asm/x25519-x86_64.pl
340336e01aa04fcde9bfd56536f90c9bc0ad56a002b6cfa321a1e421f1e93ceb crypto/ec/curve25519.c
9a95ec8366154bb20aeb24f4767a8cbb9953ca0380708eb2f39caca6078cd59e crypto/ec/curve448/arch_32/f_impl32.c
063dac1e4a9573c47532123e9e03e3532a7473cc3e146521ba9ec6f486ddf3b1 crypto/ec/curve448/arch_64/arch_intrinsics.h
43423b7ee85a5c740c1d81499ee06f4a17732c7731a598e7429d5e402ee77cf4 crypto/ec/curve448/arch_64/f_impl.h
012d4a9c8aed4a66cd3a3eef17d4b4d8f3c6f384449cd057bd292b98e072a283 crypto/ec/curve448/arch_64/f_impl64.c
9b408ec0d43f3b6d714ef5963147e2c2abaddc88633db7dd759193d3c56ed727 crypto/ec/curve448/curve448.c
3c12d90e3fdd59b5d32d63186f1a6f15c75eb73f5035b844a2054356a9459780 crypto/ec/curve448/curve448_local.h
178fb9863c33174b633c2e7607160b1bedb506d66cc06d53382d87431441f306 crypto/ec/curve448/curve448_tables.c
f30e13bba5a136ab9ba5225c98b9b94c2cd73fb3aef60f9dcde3cd471cfa1ca4 crypto/ec/curve448/curve448utils.h
4a45e7828831fbe9f282f933cda54b12cd393ec9bffe5c0ace8e4d1c4d5d6358 crypto/ec/curve448/ed448.h
a1211ed3991af967c728b9f6d0774b9ea098d43cef0631ff88984a2580d2ac4f crypto/ec/curve448/eddsa.c
450946e1cccb81e45e5601b6154e2311666b06e294aab926369995af06d1a328 crypto/ec/curve448/f_generic.c
f6447921a0031fa5beddedd298e82096fb3fdb189b712fab328b61f6beae0c23 crypto/ec/curve448/field.h
2ad8331e893b5db33198e27603891587686c0dfdab29706dc52a7097c5d6f219 crypto/ec/curve448/point_448.h
1ff6e467d72530c71d21c310180d04a24f0a9cb41168fba94b43309ecdda3888 crypto/ec/curve448/scalar.c
3052a044afae2e91b677542fc8b34b3ec9d033e0c6562b0d43098cfb34ab3c9d crypto/ec/curve448/word.h
ae1637d89287c9d22a34bdc0d67f6e01262a2f8dcef9b61369dba8c334f5a80d crypto/ec/ec2_oct.c
6bbbf570ce31f5b579f7e03ec9f8a774663c7c1eb5e475bd31f8fee94a021ffc crypto/ec/ec2_smpl.c
2a71bd8dbe4f427c117d990581709a4ddce07fa8e530794b5a9574fef7c48a0c crypto/ec/ec_asn1.c
-69b1b3acb4295f5fff961b339e8ace913176ca63fcedf4af0da4c27171f24f94 crypto/ec/ec_backend.c
+e959960fe9a78ea67346048c9c02428203819d5b443d18fe7bb26cd1ca28fcdc crypto/ec/ec_backend.c
86e2becf9b3870979e2abefa1bd318e1a31820d275e2b50e03b17fc287abb20a crypto/ec/ec_check.c
265f911b9d4aada326a2d52cd8a589b556935c8b641598dcd36c6f85d29ce655 crypto/ec/ec_curve.c
8cfd0dcfb5acbf6105691a2d5e2826dba1ff3906707bc9dd6ff9bffcc306468f crypto/ec/ec_cvt.c
95ce53663ab8a1d05bd6f4999f30113e1edce771fb6d218a772fe02de7bdaf4d crypto/ec/ec_key.c
7e40fc646863e0675bbb90f075b809f61bdf0600d8095c8366858d9533ab7700 crypto/ec/ec_kmeth.c
-bbd6f618c3dfe425ce0ba1c6710fe59418130e06351881162a590475e6438c44 crypto/ec/ec_lib.c
+fea5cd863cd94b4e543b72942ed8c23175359cfab99ca65203af4ebecb001a15 crypto/ec/ec_lib.c
a8a4690e42b4af60aad822aa8b16196df337906af53ea4db926707f7b596ff27 crypto/ec/ec_local.h
fa901b996eb0e460359cd470843bdb03af7a77a2f1136c5e1d30daef70f3e4d2 crypto/ec/ec_mult.c
-129c6b42417bfcf582f4a959cfd65433e6f85b158274f4fa38f9c62615ac9166 crypto/ec/ec_oct.c
+205b17b41e6678f40ec2a92e7856e87904e57121e7dc3120d14a4c4eeafb15b0 crypto/ec/ec_oct.c
c7fba2f2c33f67dafa23caef8c3abd12f5336274a9a07d412b83be0366969ee6 crypto/ec/ecdh_kdf.c
b2cf8f052a5716137da7b0e857ed7a5df5fb513b6d14534199a05e32f2b5a866 crypto/ec/ecdh_ossl.c
2e00c2e0e6f6d58b81fc23fe500f59e98793dc828ca87d64eba10cc0fddd0dc1 crypto/ec/ecdsa_ossl.c
b6baa42b16e8df69a12e0ab101033100cddc808ec2682ba1574373e6ec86ae93 crypto/ec/ecdsa_sign.c
f686cea8c8a3259d95c1e6142813d9da47b6d624c62f26c7e4a16d5607cddb35 crypto/ec/ecdsa_vrf.c
141cfc1459214555b623517a054a9e8d5e4065a11301237b7247be2c6f397a0a crypto/ec/ecp_mont.c
13b30f34aeeb0c98747239bfe91b5f0f14e91b2c1f11db62ebb5950c7219daa0 crypto/ec/ecp_nist.c
f288c23b6f83740956886b2303c64d5a3098c98b530859c3bb4b698c01c1643b crypto/ec/ecp_nistz256.c
51cb98e7e9c241e33261589f0d74103238baaa850e333c61ff1da360e127518a crypto/ec/ecp_oct.c
b4b7c683279454ba41438f50a015cb63ef056ccb9be0168918dfbae00313dc68 crypto/ec/ecp_smpl.c
e2705097cfab64e8d7eb2feba37c3f12b18aec74b135ad0c7f073efccf336d4c crypto/ec/ecx_backend.c
5ee19c357c318b2948ff5d9118a626a6207af2b2eade7d8536051d4a522668d3 crypto/ec/ecx_backend.h
22c44f561ab42d1bd7fd3a3c538ebaba375a704f98056b035e7949d73963c580 crypto/ec/ecx_key.c
28abc295dad8888b5482eb61d31cd78dd80545ecb67dc6f9446a36deb8c40a5e crypto/evp/asymcipher.c
0e75a058dcbbb62cfe39fec6c4a85385dc1a8fce794e4278ce6cebb29763b82b crypto/evp/dh_support.c
8f9e9da65ab1d0fb3feae5abd6b5c3649d3a4d03e936bb7624a431080de181ae crypto/evp/digest.c
838277f228cd3025cf95a9cd435e5606ad1fb5d207bbb057aa29892e6a657c55 crypto/evp/ec_support.c
61df3942752307b7006f09d7628348a0cc9e5555469a3a8862349067a52824b7 crypto/evp/evp_enc.c
62c994fd91dc4a5a1a81dfa9391d6eadae62d3549b2e1b22acb2e7c4cd278f27 crypto/evp/evp_fetch.c
ebe32b2895f7f9767710674352c8949efe93b4bbb5e7b71c27bb5d1822339b46 crypto/evp/evp_lib.c
78f07bf50b6999611a4e9414ab3a20b219b0ab29ca2bd05002d6919a3f67b8eb crypto/evp/evp_local.h
117e679d49d2ae87e49d3c942ff0ce768959e8b9713f84a99025cabba462ccd5 crypto/evp/evp_rand.c
2a128617ec0178e9eeacbe41d75a5530755f41ea524cd124607543cf73456a0c crypto/evp/evp_utils.c
ca8c6cfd30efd53f2e5d1f19bcf09a3a3d0dff6d8947c3943d07a3f4b354aa86 crypto/evp/exchange.c
9e25042581b73e295c059c6217f3ecf809134d518eb79b1b67f34e3ca9145677 crypto/evp/kdf_lib.c
1d72f5506984df1df8606e8c7045f041cf517223e2e1b50c4da8ba8bf1c6c186 crypto/evp/kdf_meth.c
5179624b8e03615dc9caedc9ec16d094fa081495613dd552d71c2c39475bcd83 crypto/evp/kem.c
5cf3e490bf917bd37ae70313d126ae4720432fbec518e4a45e8fa886d5e1689a crypto/evp/keymgmt_lib.c
46ffdc73f8a7fc314dc8988f2751a6e9f9784719f4f162dc4be2450b65b55261 crypto/evp/keymgmt_meth.c
e1a052839b8b70dca20dbac1282d61abd1c415bf4fb6afb56b811e8770d8a2e1 crypto/evp/m_sigver.c
4290c95f63b43688a8da57690d122add5161a6811f9753da1444d28f46739961 crypto/evp/mac_lib.c
e7e8eb5683cd3fbd409df888020dc353b65ac291361829cc4131d5bc86c9fcb3 crypto/evp/mac_meth.c
546d83abecf8973e2d872102a03bde5a46552909fa9e7d1402e1464a27453801 crypto/evp/p_lib.c
3b4228b92eebd04616ecc3ee58684095313dd5ffd1b43cf698a7d6c202cb4622 crypto/evp/pmeth_check.c
1f0e9e94e9b0ad322956521b438b78d44cfcd8eb974e8921d05f9e21ba1c05cf crypto/evp/pmeth_gn.c
76511fba789089a50ef87774817a5482c33633a76a94ecf7b6e8eb915585575d crypto/evp/pmeth_lib.c
53058617c153a7676e7ca18c98c23df867a93087d67935907076f3c5bd65c15e crypto/evp/signature.c
f2acfb82aac20251d05a9c252cc6c282bd44e43feac4ac2e0faf68b9a38aef57 crypto/ex_data.c
1c8389c5d49616d491978f0f2b2a54ba82d805ec41c8f75c67853216953cf46a crypto/ffc/ffc_backend.c
a12af33e605315cdddd6d759e70cd9632f0f33682b9aa7103ed1ecd354fc7e55 crypto/ffc/ffc_dh.c
854378f57707e31ad02cca6eec94369f91f327288d3665713e249c12f7b13211 crypto/ffc/ffc_key_generate.c
4e973d956d4ec2087994de8e963be1a512da1441f22e6e7b9cd7ee536e3ff834 crypto/ffc/ffc_key_validate.c
8b72d5a7452b2c15aec6d20027053a83f7df89d49a3b6cfedd77e2b1a29e9fc1 crypto/ffc/ffc_params.c
1a1d227f9a0f427d2ec93bc646c726c9cd49a84a343b4aff0c9c744fa6df05a9 crypto/ffc/ffc_params_generate.c
73dac805abab36cd9df53a421221c71d06a366a4ce479fa788be777f11b47159 crypto/ffc/ffc_params_validate.c
0a4fc92e408b0562cf95c480df93a9907a318a2c92356642903a5d50ed04fd88 crypto/hmac/hmac.c
0395c1b0834f2f4a0ca1756385f4dc1a4ef6fb925b2db3743df7f57256c5166f crypto/hmac/hmac_local.h
0e2d6129504d15ffaf5baa63158ccec0e4b6193a8275333956d8f868ef35127e crypto/ia64cpuid.S
f897493b50f4e9dd4cacb2a7accda6683c10ece602641874cdff1dac7128a751 crypto/initthread.c
7290d8d7ec31a98b17618f218d4f27b393501c7606c814a43db8af1975ad1d10 crypto/lhash/lhash.c
5d49ce00fc06df1b64cbc139ef45c71e0faf08a33f966bc608c82d574521a49e crypto/lhash/lhash_local.h
f866aafae928db1b439ac950dc90744a2397dfe222672fe68b3798396190c8b0 crypto/mem_clr.c
-78a20112586dbce2b8b6e509a0f46f6a36f2a4acf53c3f3511daf7932a71c391 crypto/modes/asm/aes-gcm-armv8_64.pl
-e482f02932d77d61142548ca4f3c8d5709d88ec14ab84723d82331444c0f57da crypto/modes/asm/aesni-gcm-x86_64.pl
-8fdcb4313fa3a6e541a697525856b9527a06ddf4c794f9393e843f86d67f543c crypto/modes/asm/ghash-alpha.pl
-ace8c376b394439301cecaf468d2a9a8adae21eff1d43191cefbf6765023452d crypto/modes/asm/ghash-armv4.pl
-c22f4945e7de3bd7bfef73447f09983e40a3e4dd0938244d902a1c44c98a8467 crypto/modes/asm/ghash-c64xplus.pl
-315a76491cdba48c88df6549c9efd96b50515400810b185a568b7a871681e03d crypto/modes/asm/ghash-ia64.pl
-25e9f494fcb6eb636c04af2f322736fae8aa339037e199332c96b8c9c3a50afa crypto/modes/asm/ghash-parisc.pl
-f22d5fa646b4fc2db008b6b05ec07c8790d3ad5485d2b10218fd11d0e81030ba crypto/modes/asm/ghash-s390x.pl
-de97107e0c19ff9dd4069f0761eccb00e0b3ced345e1f119ab3b918dd2f9c5f6 crypto/modes/asm/ghash-sparcv9.pl
+e14f48d4112c0efe3826b4aa390cc24045a85298cc551ec7f3f36ac4236d7d81 crypto/modes/asm/aes-gcm-armv8_64.pl
+1d686af304f94743038f916125effcb51790c025f3165d8d37b526bbeee781f0 crypto/modes/asm/aesni-gcm-x86_64.pl
+c2e874a8deb418b5d8c935b2e256370566a5150e040c9fa008cdb5b463c26904 crypto/modes/asm/ghash-alpha.pl
+6bc7d63569c73d7020ede481f2de05221ac92403c7cc11e7263ada7644f6aa9b crypto/modes/asm/ghash-armv4.pl
+097975df63370de7ebea012d17de14fc1f361fb83acf03b432a99ae7d5bceb24 crypto/modes/asm/ghash-c64xplus.pl
+fdde3bc48b37790c6e0006014da71e7a831bbb4fdbfcda2d01dbe0ceb0ba88fa crypto/modes/asm/ghash-ia64.pl
+e472d73d06933667a51a0af973479993eed333c71b43af03095450acb36dbeb4 crypto/modes/asm/ghash-parisc.pl
+6fb4332ac88113a20915ad4de1931ef88b0114b5379b16e1d967820e1229fbb0 crypto/modes/asm/ghash-s390x.pl
+6af1a05981e1d41e4dea51e58938360e3abc4a4f58e179908242466d032b1a8a crypto/modes/asm/ghash-sparcv9.pl
26f55a57e77f774d17dfba93d757f78edfa3a03f68a71ffa37ccf3bfc468b1e2 crypto/modes/asm/ghash-x86.pl
-2a0d23a644083e46745c7cb1ca79de393af9336a2e8eab7c85ffeb3b7b1a286f crypto/modes/asm/ghash-x86_64.pl
-b407d9fc6ea65fe1a05edc2d139298d78391f3c165314fa6d56dd375b8e453cd crypto/modes/asm/ghashp8-ppc.pl
-d8436f6dc43a18d49b1a16999ecb513ccf4483f418f75edc01ce68e777c614a9 crypto/modes/asm/ghashv8-armx.pl
+72744131007d2389c09665a59a862f5f6bb61b64bd3456e9b400985cb56586b8 crypto/modes/asm/ghash-x86_64.pl
+a4e9f2e496bd9362b17a1b5989aa4682647cefcff6117f0607122a9e11a9dfd9 crypto/modes/asm/ghashp8-ppc.pl
+69a13f423ca74c22543900c14aef4a848e3bc75504b65d2f51c6903aebcc17a7 crypto/modes/asm/ghashv8-armx.pl
65112dfe63cd59487e7bdb1706b44acfcf48ecede12cc3ae51daa5b661f41f06 crypto/modes/cbc128.c
1611e73dc1e01b5c2201f51756a7405b7673aa0bb872e2957d1ec80c3530486f crypto/modes/ccm128.c
d8c2f256532a4b94db6d03aea5cb609cccc938069f644b2fc77c5015648d148d crypto/modes/cfb128.c
af1c034152d82b29cb7c938c8516cfd136b62bac0908c1d40eb50790d23b288c crypto/modes/ctr128.c
2413852b46ee90bcbb711c0d4fb79fc6b0cac1f837b4df4896a0003935d4211a crypto/modes/gcm128.c
bdf25257b15eca206be4d950d2dd807ca5f058f91f54edbd7a0d312ed83eef8e crypto/modes/ofb128.c
e55a816c356b2d526bc6e40c8b81afa02576e4d44c7d7b6bbe444fb8b01aad41 crypto/modes/wrap128.c
608a04f387be2a509b4d4ad414b7015ab833e56b85020e692e193160f36883a2 crypto/modes/xts128.c
abba788a11469f5c01c766fdac64eccd4fb598b2d4d9a12efb086ae87009acb8 crypto/o_str.c
8ddbbdf43131c10dcd4428aef0eff2b1e98b0410accada0fad41a4925868beef crypto/packet.c
c698d5166d091d6bb6e9df3c211fe1cc916fd43a26ec844f28f547cd708f9c55 crypto/param_build.c
2a0f272dd553b698e8c6fa57962694ebd6064cb03fe26a60df529205568d315d crypto/param_build_set.c
0e4a5388a92fabbe5a540176c0b4c5ce258b78dc9168ecc2e805352a06aaf0ba crypto/params.c
4fda13f6af05d80b0ab89ec4f5813c274a21a9b4565be958a02d006236cef05c crypto/params_dup.c
b6cbfc8791b31587f32a3f9e4c117549793528ebddc34a361bad1ad8cf8d4c42 crypto/params_from_text.c
97cb7414dc2f165d5849ee3b46cdfff0afb067729435d9c01a747e0ca41e230c crypto/ppccap.c
-826a78afb376cbf1e87f12a2a67eef2ee47059a0fd3f9cba7ce7f035e34f8052 crypto/ppccpuid.pl
+3ca43596a7528dec8ff9d1a3cd0d68b62640f84b1d6a8b5e4842cfd0be1133ad crypto/ppccpuid.pl
b4d34272a0bd1fbe6562022bf7ea6259b6a5a021a48222d415be47ef5ef2a905 crypto/property/defn_cache.c
c3709986fd2ab18f3c6136d8dd7705a4538986aa789ceafe770c3a376db3c569 crypto/property/property.c
66da4f28d408133fb544b14aeb9ad4913e7c5c67e2826e53f0dc5bf4d8fada26 crypto/property/property_local.h
b0b382ce829192d2537561cfb0fb5c7afb04305f321f7b3c91441b4ba99b9c92 crypto/property/property_parse.c
a7cefda6a117550e2c76e0f307565ce1e11640b11ba10c80e469a837fd1212a3 crypto/property/property_query.c
065698c8d88a5facc0cbc02a3bd0c642c94687a8c5dd79901c942138b406067d crypto/property/property_string.c
dcc44eba5d01dc248c37ec7b394d48660627c0fa4933d2b93993e1f2ac4b71da crypto/provider_core.c
d0af10d4091b2032aac1b7db80f8c2e14fa7176592716b25b9437ab6b53c0a89 crypto/provider_local.h
5ba2e1c74ddcd0453d02e32612299d1eef18eff8493a7606c15d0dc3738ad1d9 crypto/provider_predefined.c
a5a4472636b8b0095ad8d4acd37e275ad79da1a67ecff7b7b5c3e46c9ebc65b7 crypto/rand/rand_lib.c
fd03b9bb2c23470fa40880ed3bf9847bb17d50592101a78c0ad7a0f121209788 crypto/rand/rand_local.h
f0c8792a99132e0b9c027cfa7370f45594a115934cdc9e8f23bdd64abecaf7fd crypto/rsa/rsa_acvp_test_params.c
5834d7c518ad53ea0dd3db811c0e51568c81cc6c117012030101d29003d0725c crypto/rsa/rsa_backend.c
38a102cd1da1f6ca5a46e6a22f018237964336274385f5c70cbedcaa6997647e crypto/rsa/rsa_chk.c
e32cfa04221a2a3ea33f7bcb93ee51b84cbeba97e94c1fbf6e420b24f97fc9ce crypto/rsa/rsa_crpt.c
e995da1c2e5007bd7f5907f369fe45ed15f4e657143a85078c755bd5e6863d0b crypto/rsa/rsa_gen.c
f2222f270e57559537d3da8abbeb1390bc5376b73dae59d536af6e73eb48bba0 crypto/rsa/rsa_lib.c
a65e85be5269d8cb88e86b3413c978fa8994419a671092cbf104ff1a08fda23b crypto/rsa/rsa_local.h
cf0b75cd54b61b9b9a290ef18d0ddce9fb26a029a54eb3f720d9b25188440f00 crypto/rsa/rsa_mp_names.c
5c60f6e05db82e13178d805deb1947b8eee4a905e6e77523d3b288da70a46bb5 crypto/rsa/rsa_none.c
f733d03a7f633514bfb33862cd0fa46ac952a86f84000f109c0d37937bac9a1e crypto/rsa/rsa_oaep.c
e05fcad237b7e4e7842ad6e142789fe25d060247283c337c78703be6ecc31ed9 crypto/rsa/rsa_ossl.c
be3f39c1fcb777d6c0122061f9ef735d10a6bee95d67fcc1ca6ae2a664022d2b crypto/rsa/rsa_pk1.c
174a42e156be48927fe6d6bf0d95575619b8e643a99761275bff933bc3449722 crypto/rsa/rsa_pss.c
bf6d300b7e7e9e512a47c5bd1f8713806ae3033a140d83dfae4a16ad58d11170 crypto/rsa/rsa_schemes.c
f01af62704dbf9457e2669c3e7c1d4d740f0388faa49df93611b987a8aa2bf11 crypto/rsa/rsa_sign.c
42d821612b0b0d62f587beb8a0cab8b8d876fedccd6913fec6d2044f8ac52b63 crypto/rsa/rsa_sp800_56b_check.c
3aba73dacebb046faf8d09dc279149b52c629004b524ec33e6d81c8ad0bc31a8 crypto/rsa/rsa_sp800_56b_gen.c
1c1c2aeeb18bf1d69e8f134315b7e50d8f43d30eb1aa5bf42983eec9136a2fdc crypto/rsa/rsa_x931.c
0acbebed48f6242d595c21e3c1ad69da0daa960d62062e8970209deda144f337 crypto/s390xcap.c
-370d98549d4d98e04b60677b319b85904259359bd9401dd5385aa728278e6626 crypto/s390xcpuid.pl
+22205848cfb55116ebf999dced8331b575886a609ce29e6886e6267b2310c337 crypto/s390xcpuid.pl
5fa59240ca885cbc0c1cd026934b226d44fc9c3fdf0c2e7e3a7bd7f4963ca2e5 crypto/self_test_core.c
-58a1a8aeb45421954fa0e4bc87157addb96d086ac4e6aade47da96523cecaa74 crypto/sha/asm/keccak1600-armv4.pl
-d6df6cfdd4e2fee52dc16fd31c91768c45c48c22700c486406d70ecb37e8a8bb crypto/sha/asm/keccak1600-armv8.pl
-81bfb4484d68a3a3e1d704855f76356090867fe10a75db7707b6f7364e8ee8da crypto/sha/asm/keccak1600-avx2.pl
-b7bb35d51d439abbf3810454ccb9bfb5a51e2111eaf389fb95796ad6220a61a0 crypto/sha/asm/keccak1600-avx512.pl
-37365dcc576f99006132271968bab990e2bebdab7f4168c726bd449a2fa51c6a crypto/sha/asm/keccak1600-avx512vl.pl
-2767ae2f379a7a3d0c6dd1471d4d90dd896545b456cb6efd6c230df29e511d70 crypto/sha/asm/keccak1600-c64x.pl
+05c533fde7fdba0c76103e97d881b7224c8427451b453e2f6413552996063e31 crypto/sha/asm/keccak1600-armv4.pl
+ca3b2b654f9a8c4bc2fa2538c1f19d17acd4a6b9e0df6a4b81df04efa697e67e crypto/sha/asm/keccak1600-armv8.pl
+12b7acce2fba0bc0e1ca07842ec84be6a022f141c86e077abb42c864af1d8d9c crypto/sha/asm/keccak1600-avx2.pl
+faf0cccb685d5abc807e08db194f847c67b940da2fc3c235c210dc31d73a5334 crypto/sha/asm/keccak1600-avx512.pl
+be1e7dd9998e3f31cfa6e1b17bc198aeec584a8b76820e38f71d51b05f8a9f2a crypto/sha/asm/keccak1600-avx512vl.pl
+33bdcc6f7668460c3bdf779633e43bfad62b937042a73acb007b462fc5b0a034 crypto/sha/asm/keccak1600-c64x.pl
09fc831dd39bd90a701e9b16d9e9987cc215252a22e1e0355f5da6c495fca35a crypto/sha/asm/keccak1600-mmx.pl
-485dcc50a51705b86c6dc47e6f58d092fec05dfbfcdf4f2785e4235c67cfe742 crypto/sha/asm/keccak1600-ppc64.pl
-49535b60a1a981059a2a9636fdeeab22942d2a15e775b1ec9b5af8937a46aa76 crypto/sha/asm/keccak1600-s390x.pl
-093751655b460d33b2fa6aa4d63a86e902f7f20b2d2a02ed948b78e5698c0dd5 crypto/sha/asm/keccak1600-x86_64.pl
-e0a4a1df82716053a3f01ec0b096c735a0e3c4f6c9d9ec6b2006b37aaac64448 crypto/sha/asm/keccak1600p8-ppc.pl
+ce4a58129e5ee3ac4c9dfec5ecc010440570ebf7bf869e3e9977f2121a64b27a crypto/sha/asm/keccak1600-ppc64.pl
+a859fc8cb073b2d0012a93f3155a75fb6eb677441462b0de4f8cf8df1445e970 crypto/sha/asm/keccak1600-s390x.pl
+618dcd4891b4064d3b8aa6dcd74bea7ef55f4962a64957b05a05448f6e3e0f17 crypto/sha/asm/keccak1600-x86_64.pl
+831b8b02ab25d78ba6300ce960d96c13439bfba5844e13061e19c4e25cbacc3d crypto/sha/asm/keccak1600p8-ppc.pl
75d832db9bf0e98e7a5c522169060a6dd276c5118cfb297fc3f1111f55cd4007 crypto/sha/asm/sha1-586.pl
-8d937771993f04407f5fdcca8ca8565f9f8a4d9c9a8f7bfd4e9f9121dd0450bb crypto/sha/asm/sha1-alpha.pl
-ab7ecd62896324393b1fd9020515b9c0d2b9cc34d559f2efafa35affc9a1485d crypto/sha/asm/sha1-armv4-large.pl
-0acc4e40f793d4d2b960af2baaecc91176ba6742ddd62dca0c33ddc838c58772 crypto/sha/asm/sha1-armv8.pl
-c36f51761e7f59bdd0f61230297fb802542ac5d2d1c6d2b1096ed937131bd583 crypto/sha/asm/sha1-c64xplus.pl
-4ab7c9153b085274a579b388ddff97a4ac7e11585e01811ca95b93a3ec786605 crypto/sha/asm/sha1-ia64.pl
-7a392c5ef7dc19c39d67c7080e0c5214e7a80572c85c022be7e7d4378a5f740d crypto/sha/asm/sha1-mb-x86_64.pl
-c0fea5a0d32001263c8bcf7fc0757aa68c6a7377f20fef8d28708e1b81de5dec crypto/sha/asm/sha1-mips.pl
-f11b75a54c5f42aa3a052de8091bfba47d7cac01920b2fe0ddcb637d4c9d0eb9 crypto/sha/asm/sha1-parisc.pl
-d46ef3fc166271a83144d90985034e2c514bd1020b84ec0fe5427ad593bfeb74 crypto/sha/asm/sha1-ppc.pl
-a48c7d9403fe99fbd4daec60e96eb22058da766ab9e606d084a63613962851a2 crypto/sha/asm/sha1-s390x.pl
-0e2951e0574c64ee055ffddf16ceefdec00823107d60362976605f139ad8ae68 crypto/sha/asm/sha1-sparcv9.pl
-5da48400d4fae85e205e95a2fa368e7bf525e51e274b1dd680dfb48645426c85 crypto/sha/asm/sha1-sparcv9a.pl
-04b73c902d36c28b5a7eab47cb85f743eb9c648ed5936f64f655524a1010a1b5 crypto/sha/asm/sha1-thumb.pl
-f36d7ec7464c932230585a754b91f13cea4cde5a381fc9f798d959256d07910e crypto/sha/asm/sha1-x86_64.pl
+c96e87d4f5311cd73bbdf499acc03418588be12426d878e157dd67e0099e0219 crypto/sha/asm/sha1-alpha.pl
+4ba6d1c7f12fe76bf39babea966f0a4b7f8769e0c0510cbfc2c46a65dd62d45c crypto/sha/asm/sha1-armv4-large.pl
+efc69cb0d867b7fac6b3fa8985c343d1f984d552bc8e75bbbbace0adf9ee5f15 crypto/sha/asm/sha1-armv8.pl
+11d332b4e058e9fa418d6633316d2e9f9bf520a08b2d933e877bdf38b2edefcf crypto/sha/asm/sha1-c64xplus.pl
+32ff0e701a7b8f25bcfe8477b20795de54f536527bd87d3ce694fd9aaae356d4 crypto/sha/asm/sha1-ia64.pl
+471c27efca685b2a82ad7fefe329ca54172df9f49b9785da6d706b913b75e693 crypto/sha/asm/sha1-mb-x86_64.pl
+0f5c63cf09e950d1b488935ab3b5562e3e9d5cd1a563fb88a41e3dae90a35e6d crypto/sha/asm/sha1-mips.pl
+b5ffd7b6dbb04c05de7efa2945adb67ea845e7e61a3bf163a532f7b6acdf4267 crypto/sha/asm/sha1-parisc.pl
+482cd23ca6ec38d6f62b90c68f9f20643579c50f2c0fbb0dab1c10a0e35efe77 crypto/sha/asm/sha1-ppc.pl
+28cf69efd53d7a5a8c32e0f8db32c193f41b91faf44f5f59944334bc3f5aa337 crypto/sha/asm/sha1-s390x.pl
+7fd355b412ddfa1c510e0ba3284f75b1c0d621b6db2ecb1d2a935d5cdb706628 crypto/sha/asm/sha1-sparcv9.pl
+24554e68b0e7b7db7b635ff149549015f623ca0bcd9ae90439586a2076f6ae80 crypto/sha/asm/sha1-sparcv9a.pl
+74d197cdd72400cabbff7e173f72c8976723081508b095dc995e8cd1abf3daa6 crypto/sha/asm/sha1-thumb.pl
+a59a86293e28f5600609dc8af2b39c5285580ae8636520990b000eeeb67bb889 crypto/sha/asm/sha1-x86_64.pl
c099059ef107f548ea2c2bab64a4eb8c277070ce6d74c4d32bb9808dc19c5fa3 crypto/sha/asm/sha256-586.pl
-3a8cf38dd398a7ab1d9c6701fa61c428b07c4431a0041ed3a2ddf937897825c1 crypto/sha/asm/sha256-armv4.pl
-c394bb5b0ff05595a9e6848b6602a0f29f73a79fc006593740f3ca645ad9d316 crypto/sha/asm/sha256-c64xplus.pl
-f33af8e2e2f57b7b63b8c8b35722d7d11ca6ef1f73fb6c4ccebdd3e86912f4b1 crypto/sha/asm/sha256-mb-x86_64.pl
+b9cee5c5a283f61f601d2dba68a7a76e7aba10bfafffc1a5c4987f9c0aa6f87d crypto/sha/asm/sha256-armv4.pl
+93ddc97651ee3e779144a3c6b3e46a1bc4aa81e75cd7b9df068a2aef8743d25f crypto/sha/asm/sha256-c64xplus.pl
+8be5c5d69733ecb16774aa8410b4bcb3623a9f060d2be103d8aa67bf6e4c5843 crypto/sha/asm/sha256-mb-x86_64.pl
dd82e1311703abb019975fc7b61fb87d67e1ed916dddd065aced051e851114b9 crypto/sha/asm/sha512-586.pl
-1f9ba79b1d591b7aa37b62382422cb025f5b45784d26cc5790c05cf4eb52b792 crypto/sha/asm/sha512-armv4.pl
-8136196fce18b736f671a4b4945cd4aa4ab25a28c90c6fc9ab31ff771e8e0d9f crypto/sha/asm/sha512-armv8.pl
-5b6796a9978b69fd78ee2ff1adc5cf35d44cad8194a38d1c2aba2023012cf252 crypto/sha/asm/sha512-c64xplus.pl
-e8df660671ba61aa2e8f51358baf5d8ca913093e2ee1a40c9cb46d9c2c0851f6 crypto/sha/asm/sha512-ia64.pl
-525f253ef8051bfb0e344ac2e40688ce359a42707fe360d23a03f522cc88c81a crypto/sha/asm/sha512-mips.pl
-3c3e03529d8514467f8d77c01978348636bb339315feb8041fbde7640565001e crypto/sha/asm/sha512-parisc.pl
-952ef1b10e8bbe3f638cc798b91ab9c5b47b66ed8fe94647b1beec9874f2e71e crypto/sha/asm/sha512-ppc.pl
-193a0ea240264b29dd68a425f604a6da4b18e28838dcf909dd7e711af880f782 crypto/sha/asm/sha512-s390x.pl
-dcb466a1e5938fb64ecb38b0533602192d61334da864ee8dfdcfa12d3cdfa273 crypto/sha/asm/sha512-sparcv9.pl
-bb6503967a58b767a3e73441cfabc77f15c8ac747f377e276d4aa63d05f2c3c4 crypto/sha/asm/sha512-x86_64.pl
-68d2f3b2dccb978ee42640f4fb4d2eae6b74d071017a3eedd9e7cb77762817dc crypto/sha/asm/sha512p8-ppc.pl
+8d84164f3cfd53290c0c14bb5655510b7a9238857866328c0604d64b4e76fe21 crypto/sha/asm/sha512-armv4.pl
+dadacb6d66b160913bffb4e1a6c3e5f7be6509b26e2c099701d8d3fdb92c1be0 crypto/sha/asm/sha512-armv8.pl
+6f548a088feae3b6faa179653ba449df9d3f5cda1e0561e5b5f120b32274d1eb crypto/sha/asm/sha512-c64xplus.pl
+9fa54fbc34fd881f4b344374b9b4f8fb15b641424be7af9a31c71af89ae5d577 crypto/sha/asm/sha512-ia64.pl
+fb06844e7c3b014a58dccc8ec6020c71843cfdc5be08288bc7d204f0a840c474 crypto/sha/asm/sha512-mips.pl
+11548f06d213947104a80898e000218ec0d6ff3f6913f6582de498476482ce9f crypto/sha/asm/sha512-parisc.pl
+7c0c490ce6bb11a228853aecad5e164ce84e5bdabb8a6658ae7184782076c7d3 crypto/sha/asm/sha512-ppc.pl
+38e0455fd6a2b93a7a5385379ca92bc6526585ca1eb4af365fac4c78f7285c72 crypto/sha/asm/sha512-s390x.pl
+0611845c52091b0208dd41f22ddef9dd1e68d3d92fa4c4360738b840a6314de6 crypto/sha/asm/sha512-sparcv9.pl
+f64d16c1e5c3fa4a7969de494a8372127502171a517c14be7a1e3a43a7308699 crypto/sha/asm/sha512-x86_64.pl
+8725cabb8d695c576619f19283b034074a3fa0f1c0be952a9dbe9793be15b907 crypto/sha/asm/sha512p8-ppc.pl
57f6cf54b1b5d2cac7a8f622b7b6bd1878f360fff3fa0f02352061c24162ebbb crypto/sha/keccak1600.c
306cacd3f86e5cacaca74c58ef862516515e5c0cafaff48636d537fd84f1c2fb crypto/sha/sha1dgst.c
4d8cf04f5806611e7586aab47fb28165ec1afb00168e2c9876bb36cb5c29bf8b crypto/sha/sha256.c
3d972a11be18bfbfcd45790028635d63548bfe0a2e45d2fc56b6051b759d22f0 crypto/sha/sha3.c
8038a5a97f826f519424db634be5b082b3f7eca3ccb89875ca40fa6bd7dfdcfd crypto/sha/sha512.c
6c6f0e6069ac98e407a5810b84deace2d1396d252c584703bcd154d1a015c3ea crypto/sha/sha_local.h
9ef5a01caccc2eb15f72e367d0424737040ac8018479bbbbce3d216c655765c2 crypto/sparccpuid.S
5056b14a55665ffa342a9a1bb32c1c36886add5d0819869193427f33cee028f7 crypto/sparcv9cap.c
c50c584c55e56347bb43aca4b796b5344d70daece3061f586b79c871c21f5d1a crypto/sparse_array.c
8da78169fa8c09dc3c29c9bf1602b22e88c5eac4815e274ba1864c166e31584b crypto/stack/stack.c
7b4efa594d8d1f3ecbf4605cf54f72fb296a3b1d951bdc69e415aaa08f34e5c8 crypto/threads_lib.c
a41ae93a755e2ec89b3cb5b4932e2b508fdda92ace2e025a2650a6da0e9e972c crypto/threads_none.c
3729e2bd36f945808b578e0d89fac0fcb3114e4fc9381614bcbd8a9869991716 crypto/threads_pthread.c
-88423960f0414f6fd41fba4f4c67f9f7260c2741e4788adcd52493e895ec8027 crypto/threads_win.c
-af0af59fe2cb8668a96751f343232d7faa3e7a937beb2bda09ed74fe60b9cb5f crypto/x86_64cpuid.pl
+f82715745b668297d71b66d05e6bfc3c817bf80bd967c0f33ca7ffbb6e347645 crypto/threads_win.c
+fd6c27cf7c6b5449b17f2b725f4203c4c10207f1973db09fd41571efe5de08fd crypto/x86_64cpuid.pl
bbec287bb9bf35379885f8f8998b7fd9e8fc22efee9e1b299109af0f33a7ee16 crypto/x86cpuid.pl
acbb841170d4d3eb91d969be1c0e4973b1babfd5fcd76440b0628f509f82fd76 e_os.h
249a0e58e9692920eddc1ada2ac772a0cfd749cfbf618f2f5da08280df545d8f include/crypto/aes_platform.h
8c6f308c1ca774e6127e325c3b80511dbcdc99631f032694d8db53a5c02364ee include/crypto/asn1_dsa.h
-2e8c284672c4e8e395b3da56a3abf3e65bb4346313fb6f7358e925d077a2e1e2 include/crypto/bn.h
+3bded0eaa7ccdebd0b4217b7fdb82676d5c0762a88aca462dbceaef851fafa99 include/crypto/bn.h
1c46818354d42bd1b1c4e5fdae9e019814936e775fd8c918ca49959c2a6416df include/crypto/bn_conf.h.in
7a43a4898fcc8446065e6c99249bcc14e475716e8c1d40d50408c0ab179520e6 include/crypto/bn_dh.h
e69b2b20fb415e24b970941c84a62b752b5d0175bc68126e467f7cc970495504 include/crypto/cryptlib.h
6c72cfa9e59d276c1debcfd36a0aff277539b43d2272267147fad4165d72747c include/crypto/ctype.h
89693e0a7528a9574e1d2f80644b29e3b895d3684111dd07c18cc5bed28b45b7 include/crypto/des_platform.h
daf508bb7ed5783f1c8c622f0c230e179244dd3f584e1223a19ab95930fbcb4f include/crypto/dh.h
20d99c9a740e4d7d67e23fa4ae4c6a39d114e486c66ad41b65d91a8244cd1dea include/crypto/dsa.h
2ea47c059e84ce9d14cc31f4faf45f64d631de9e2937aa1d7a83de5571c63574 include/crypto/ec.h
edbfae8720502a4708983b60eac72aa04f031059f197ada31627cb5e72812858 include/crypto/ecx.h
9dab9af8b0a657fe5de46375b71aefcad7e98af272b69ed69c7c104e9e057414 include/crypto/evp.h
bbe5e52d84e65449a13e42cd2d6adce59b8ed6e73d6950917aa77dc1f3f5dff6 include/crypto/lhash.h
162812058c69f65a824906193057cd3edeabc22f51a4220aea7cb9064379a9b6 include/crypto/md32_common.h
f12bfc145290444bcc7bf408874bded348e742443c145b8b5bc70ae558d96c31 include/crypto/modes.h
f326212c978576c5346c89ae0336c2428594494b54054f6045b1f1038bfbc004 include/crypto/rand.h
90930fc8788d6e04e57829346e0405293ac7a678c3cef23d0692c742e9586d09 include/crypto/rand_pool.h
306abf9d327a9e63fff2cdef730275abc4d2781254a032b1f370f3428eb5a2ef include/crypto/rsa.h
32f0149ab1d82fddbdfbbc44e3078b4a4cc6936d35187e0f8d02cc0bc19f2401 include/crypto/security_bits.h
0f743762f646656b5480648c05632575fe8acc7506460c63e0fcdf42cf20c08a include/crypto/sha.h
7676b02824b2d68df6bddeb251e9b8a8fa2e35a95dad9a7ebeca53f9ab8d2dad include/crypto/sparse_array.h
7ad02c7de77304c3b298deeb038ab2550cf8b2bce03021994477c6c43dbcf86e include/crypto/types.h
782a83d4e489fd865e2768a20bfa31e78c2071fd0ceeb9eb077276ae2bcc6590 include/internal/bio.h
8e984890c7c62cdd6356963f034831831f7167c65096cb4d23bc765d84d2c598 include/internal/constant_time.h
c5bb97f654984130c8b44c09a52395bce0b22985d5dbc9c4d9377d86283f11f8 include/internal/core.h
0b572801dfb8a41cc239e3439f8097a0ad11bbdf5d54811d10ceba3175cf2f17 include/internal/cryptlib.h
9571cfd3d5666749084b354a6d65adee443deeb5713a58c098c7b03bc69dbc63 include/internal/deprecated.h
3325b895d15c0a6341f456a8d866a0f83e80fc8a31a01c34fcfd717715b33075 include/internal/der.h
fd1722d6b79520ee4ac477280d5131eb1b744c3b422fd15f5e737ef966a97c3b include/internal/dso.h
f144daebef828a5bd4416466257a50f06b894e0ce0adf1601aa381f34f25a9e7 include/internal/dsoerr.h
70d3e0d5a1bd8db58dcc57bea4d1c3ed816c735fe0e6b2f4b07073712d2dc5ef include/internal/endian.h
7854b5c1cd786dc01d052204c5b3ea946dc9929590f47ec4c27697387c5b7ce5 include/internal/ffc.h
100053a1bad1a85a98c5b919cf81ace0ee147b2164732963e40474d7b5fbbb99 include/internal/namemap.h
b02701592960eb4608bb83b297eed90184004828c7fc03ea81568062f347623d include/internal/nelem.h
ae41a2fb41bf592bbb47e4855cf4efd9ef85fc11f910a7e195ceef78fb4321dc include/internal/numbers.h
b89cca3b727d4526b459246de11e768a20333555bf3a9ed9a9b8beb2b565dc7f include/internal/packet.h
dd7ddecf30bef3002313e6b776ce34d660931e783b2f6edacf64c7c6e729e688 include/internal/param_build_set.h
d4ac19b28ea61f03383364cfad1e941cac44fc36787d80882c5b76ecc9d34e29 include/internal/property.h
727326afb3d33fdffdf26471e313f27892708318c0934089369e4b28267e2635 include/internal/propertyerr.h
6a899ef3e360c7144d84d3c3dbbd14aa457f5d38b83b13c0be7ec7f372076595 include/internal/provider.h
34432d71c49dc8ee9926218ba78bdcd03c46cee4e966ee20d100e4519d85b064 include/internal/refcount.h
11ee9893f7774c83fcfdee6e0ca593af3d28b779107883553facdbfdae3a68f5 include/internal/sha3.h
494ab5c802716bf38032986674fb094dde927a21752fe395d82e6044d81801d1 include/internal/sizes.h
24f41a1985fa305833c3f58030c494d2563d15fc922cdf3eeb6a7ea8c135a880 include/internal/symhacks.h
640cc6a2aae208073a7f495c08b4c5006a69e8ac1c2d9aaaafd56b0e74d5f859 include/internal/thread_once.h
415b725d7f949a6191ab7bb30b48931bafc01c7aa93607e529fabbc853a4ddc5 include/internal/tlsgroups.h
fc0f9199487ef278b9fd317d1572db3e3fb95e182055f0e49c4d8faf78ed7dd2 include/internal/tsan_assist.h
2b38fb6e65d549aca3b2c76907daf67124f395251c0261dec26faa54da8d6d73 include/openssl/aes.h
98aa2fc5eae9ef2a36d3d0053212696d58893baa083fa1fcf720660fb4bc0a9f include/openssl/asn1.h.in
d4733dcd490b3a2554eaf859d1ea964fe76f7d24f78e42be1094bdad6dee7429 include/openssl/asn1err.h
1550474ee05423896ec4abfb6346f1bc44c7be22329efac9ea25de10e81d549c include/openssl/asn1t.h.in
dbd1501acb0804eec0f2aa7bbac4dbc483cf2b4691c6eb1436461b5ed4685b42 include/openssl/bio.h.in
0a26138aaded05cafe2326e11fdc19b28408e054cfe3dda40d45ef95ce8136b0 include/openssl/bioerr.h
7d1f9880976a926ba6e0cad08e8de6f326aae48d8350b499aa79127f63d4d108 include/openssl/bn.h
9ad8b04764797f5138f01f549ba18b44cf698ffc7fe795fef42c1822d84a6ff4 include/openssl/bnerr.h
93954e6c450716e158948d67f64736a451ea9473d02f3a908f3bc8a96cf049a5 include/openssl/buffer.h
9d48e6cab2ee98ae94d7113e4c65f000d97e125fdb3445642865ace3f34d06ac include/openssl/buffererr.h
8e772c24b051e59d2f65339f54584e3e44165a3eaf997d497faea764990130f5 include/openssl/cmac.h
55aa91482d327d1784484922389e8277bdcdff7a7df27e84200d5c908bd40454 include/openssl/conf.h.in
bb45de4eafdd89c14096e9af9b0aee12b09adcee43b9313a3a373294dec99142 include/openssl/conferr.h
02a1baff7b71a298419c6c5dcb43eaa9cc13e9beeb88c03fb14854b4e84e8862 include/openssl/configuration.h.in
6b3810dac6c9d6f5ee36a10ad6d895a5e4553afdfb9641ce9b7dc5db7eef30b7 include/openssl/conftypes.h
df5e60af861665675e4a00d40d15e36884f940e3379c7b45c9f717eaf1942697 include/openssl/core.h
00110e80b9b4f621c604ea99f05e7a75d3db4721fc2779224e6fa7e52f06e345 include/openssl/core_dispatch.h
cbd9d7855ca3ba4240207fc025c22bbfef7411116446ff63511e336a0559bed0 include/openssl/core_names.h
194f96a30bdc4dab3f65693c09326ef53c54ebfd613c2513d8258a0aa35a6996 include/openssl/crypto.h.in
1d1697bd3e35920ff9eaec23c29472d727a7fc4d108150957f41f6f5ecf80f1a include/openssl/cryptoerr.h
bbc82260cbcadd406091f39b9e3b5ea63146d9a4822623ead16fa12c43ab9fc6 include/openssl/cryptoerr_legacy.h
fa3e6b6c2e6222424b9cd7005e3c5499a2334c831cd5d6a29256ce945be8cb1d include/openssl/des.h
75fba45d6fc66e3aaef216959327157613f08070935aae4a5260e740184f031f include/openssl/dh.h
ab7ba5d7eb18d2ea8abc6862ae2ceaa1fa116a702c2bff617c5ae1651d97b6bc include/openssl/dherr.h
92ae2c907fd56859e3ae28a085071611be5c9245879305cdf8bad027219e64b6 include/openssl/dsa.h
276d1f6e111ba933bc708e6a0670047cbe0d0b67aabe31807abbbc231de4d8cf include/openssl/dsaerr.h
41bf49e64e1c341a8c17778147ddeba35e88dfd7ff131db6210e801ef25a8fd5 include/openssl/e_os2.h
bc9ec2be442a4f49980ba2c63c8f0da701de1f6e23d7db35d781658f833dd7b9 include/openssl/ebcdic.h
33b6321d1c6b7b1621198346946401bb81472054aa236b03c6f22f247248d2ad include/openssl/ec.h
7aa8c5bee779af59d4733f6a50f7f6be39f1eb43409e5b3357440f9a7d0ca115 include/openssl/ecerr.h
61c76ee3f12ed0e42503a56421ca00f1cb9a0f4caa5f9c4421c374bcd45917d7 include/openssl/encoder.h
69dd983f45b8ccd551f084796519446552963a18c52b70470d978b597c81b2dc include/openssl/encodererr.h
c6ee8f17d7252bdd0807a124dc6d50a95c32c04e17688b7c2e061998570b7028 include/openssl/err.h.in
b23bf3e2d0a60fe4d768afbe7aab48b47791e1274ae42b28895255119ae7f61d include/openssl/evp.h
5bd1b5dcd14067a1fe490d49df911002793c0b4f0bd4492cd8f71cfed7bf9f2a include/openssl/evperr.h
5381d96fe867a4ee0ebc09b9e3a262a0d7a27edc5f91dccfb010c7d713cd0820 include/openssl/fips_names.h
b1d41beba560a41383f899a361b786e04f889106fb5960ec831b0af7996c9783 include/openssl/fipskey.h.in
47a088c98ad536ea99f2c6a9333e372507cb61b9bdffb930c586ed52f8f261eb include/openssl/hmac.h
faab8accc9520269dd874126ae164a43526d5784e6280521c7ab3772c02b0a0c include/openssl/kdf.h
c6db6926e90c9efd530a7bdb018be8c62f2c2b3c2f7b90228e9f73b8437dd785 include/openssl/lhash.h.in
fd5c049ac6c3498750fa8f8dcbf88b2a31c02fa62dfe43a33d7b490fb86f61c8 include/openssl/macros.h
9184207c562fd1fa7bd3a4f1fadcb984130561279818f0cdfcf3e9c55be8a7d1 include/openssl/modes.h
7c71200e35f4cc1b4011a4bc14e521e4dc037b9b2d640a74bc30ef334b813de3 include/openssl/obj_mac.h
157797b450215f973eb10be96a04e58048ab9c131ad29427e80d0e37e230ed98 include/openssl/objects.h
d25537af264684dff033dd8ae62b0348f868fcfec4aa51fa8f07bcfa4bd807ad include/openssl/objectserr.h
fe6acd42c3e90db31aaafc2236a7d30ebfa53c4c07ea4d8265064c7fcb951970 include/openssl/opensslconf.h
1bf52d136e94f727a96651c1f48ad040482f35dae152519ccd585efd410b92f0 include/openssl/opensslv.h.in
767d9d7d5051c937a3ce8a268c702902fda93eeaa210a94dfde1f45c23277d20 include/openssl/param_build.h
30085f4d1b4934bb25ffe7aa9a30859966318a1b4d4dcea937c426e90e6e1984 include/openssl/params.h
097615b849375e2903967521f76c570512e5be47b8159fdbcd31e433f8a4cca7 include/openssl/prov_ssl.h
bdadffba7b7b8294c9f7450ce2563ae31145ca0f196f5ce7b8c2f19ed7fba816 include/openssl/proverr.h
b97e8ad49b38683817387596aefec0abd5f4d572643beef48be4f7acba26768d include/openssl/provider.h
7c9b5f479d9b22cfc8db0976dddfc2a1ee6e757b436e01a2b4d2744bcb6d81a5 include/openssl/rand.h
108966f56c82fedff53df76a4aa7861c82be4db1fd1ddafb59dc086ea155831c include/openssl/randerr.h
c1015b77c444a3816d2ea7ad770f1c3b79a1e54887930af6dd662895701f3323 include/openssl/rsa.h
2f339ba2f22b8faa406692289a6e51fdbbb04b03f85cf3ca849835e58211ad23 include/openssl/rsaerr.h
6586f2187991731835353de0ffad0b6b57609b495e53d0f32644491ece629eb2 include/openssl/safestack.h.in
af5cc56fb31161ccd87cf925f3d3f22119dfbca78bc39a2e2d65d78bfcf0f0c6 include/openssl/self_test.h
2964274ab32b1ba8578a06b06663db2eda4317ae806369271d889176bb5a7d04 include/openssl/sha.h
c169a015d7be52b7b99dd41c418a48d97e52ad21687c39c512a83a7c3f3ddb70 include/openssl/stack.h
22d7584ad609e30e818b54dca1dfae8dea38913fffedd25cd540c550372fb9a6 include/openssl/symhacks.h
5e452bf61d802fdf7b6a65d1c8a1e3f72a7885e4bf2f521eca6443cea69f4ce5 include/openssl/trace.h
873d2ec2054ec24c52df4abe830cb2b9666fe4e75cc62b4de0f50ef9d20c5812 include/openssl/types.h
c0a9551efccf43f3dd748d4fd8ec897ddaabbc629c00ec1ad76ce983e1195a13 providers/common/bio_prov.c
4546387d6642603c81ec4cd8d5fc4af8ba60ac7359eb6f31e7d24827031e68ad providers/common/capabilities.c
f94b7435d4ec888ec30df1c611afa8b9eedbb59e905a2c7cb17cfc8c4b9b85b8 providers/common/der/der_digests_gen.c.in
424d7b2ece984a0904b80c73e541400c6e2d50a285c397dd323b440a4f2a8d8e providers/common/der/der_dsa_gen.c.in
27ff361a5fbfc97cd41690ab26639708961d0507b60912f55f5919649842c6ae providers/common/der/der_dsa_key.c
2529d253b3e45c33249461fdedb2c32b3c16a7a305fe4920f2a79e7b3f16ed3f providers/common/der/der_dsa_sig.c
a81d36446eb8afa5c2318e24b86b52647059b4721ee52309b741e4ee78af29dd providers/common/der/der_ec_gen.c.in
b8f2f94daeaf20c636c90e386284c246cfded0c8275411fa02fe68b534520b95 providers/common/der/der_ec_key.c
9104cd39dddd6e1a6e8f267656482131f4d0765e96fdced1f7344817a1c8ed7e providers/common/der/der_ec_sig.c
03a5620654438c58a8f971398e68922a3f33a519e2c92edb141d13ef4cbc4651 providers/common/der/der_ecx_gen.c.in
f3b089fd3dcccc8e3ebfbbdbf87c47d58330f82bd0e2a1223da74977930cccf1 providers/common/der/der_ecx_key.c
5b3b0ae8da0fad1f7ba8b5fba2206210884728bf69a8aa00644036eb51953467 providers/common/der/der_rsa_gen.c.in
029aec80a45b477f7c8bd8d24d48e36de92f8056b421e9f128c336dc246dbc4e providers/common/der/der_rsa_key.c
7e8d579986f53eaf1875d677e5cf4adfd4ccf79db0275368f6cac580ab6007ca providers/common/der/der_rsa_sig.c
0b18bc007f296e16f6210956f5b6ab612b77d8a95170f12ae32764125901db6d providers/common/der/der_wrap_gen.c.in
d447cd774869da68a2cc0bbb19c547ee6ed4858c7aee1f3d5bba7796f97823a9 providers/common/digest_to_nid.c
440c8ce0a4ca9f63157202bbfa26e12fec25847215fbae3416274124604ada6e providers/common/include/prov/bio.h
18ce379903b078446945da9116026da8639b4b0d81d357f86f9674a2a5cb94ef providers/common/include/prov/der_digests.h.in
c0a020765feb7ededc7e6f20b2b140dca09f347cc72404a5c7971df82b2f9ad0 providers/common/include/prov/der_dsa.h.in
6024645ac9e165685b0a44a20feb342355eb06c07b7c7954508a125348570aea providers/common/include/prov/der_ec.h.in
5b6b7d8d12011c48195b7db8f65bc4bc4a48fb753763a3ce5006dc227b5139d7 providers/common/include/prov/der_ecx.h.in
ce605f32413b09d33ce5795de9498a08183895c3347f33344f9ae5d31c29ccac providers/common/include/prov/der_rsa.h.in
6c1fa3f229c6f049c3ac152c4c265f3eb056d94221b82df95a15400649690e93 providers/common/include/prov/der_wrap.h.in
76087f04f4de6414c240f88807659fb2a04af914108f0c5f2515a4cb5482f655 providers/common/include/prov/proverr.h
83a57505d88a6a9cc4f7781c9f7f4af07668e7923502dfd6c5960bb492c1d24e providers/common/include/prov/provider_ctx.h
03fcfea9ed6e23d1df7ffd230af15f0f9b91a6aa635f77b9cbe52d5112168d09 providers/common/include/prov/provider_util.h
e1ef8b2be828a54312d6561b37751a5b6e9d5ebdb6c3e63589728c3d8adca7dc providers/common/include/prov/providercommon.h
73d0e15963759fcb7c5c434bb214b50bc32f6066e90ac07fb53dad11c2fd1939 providers/common/include/prov/securitycheck.h
737cc1228106e555e9bab24e3c2438982e04e05b0d5b9ee6995d71df16c49143 providers/common/provider_ctx.c
a8b73b10ab0100942dd2bc45f2fc9c9238b70bec0e49708ba113bc7479c8b92a providers/common/provider_err.c
9eae3e2cac89c7b63d091fdca1b6d80c5c5d52aa79c8ba4ce0158c5437ad62f3 providers/common/provider_seeding.c
eec462d685dd3b4764b076a3c18ecd9dd254350a0b78ddc2f8a60587829e1ce3 providers/common/provider_util.c
5b94312727ca33e4f5c038f4caaae8417bf584cfde22df83d91f3c55c30c81ee providers/common/securitycheck.c
527eda471e26763a5fcf123b2d290234d5c836de7b8ef6eef2166ef439919d82 providers/common/securitycheck_fips.c
abd5997bc33b681a4ab275978b92aebca0806a4a3f0c2f41dacf11b3b6f4e101 providers/fips/fips_entry.c
4a5ed1059ea6c5ef8d4b2a074b3da332443468852f58c18555f67f5d6d98606a providers/fips/fipsprov.c
5d24ba30f9cc7ca48546fb85dc285bd68590f3a604a0bd471bcb0c2a61169591 providers/fips/self_test.c
f822a03138e8b83ccaa910b89d72f31691da6778bf6638181f993ec7ae1167e3 providers/fips/self_test.h
d3c95c9c6cc4e3b1a5e4b2bfb2ae735a4109d763bcda7b1e9b8f9eb253f79820 providers/fips/self_test_data.inc
629f619ad055723e42624230c08430a3ef53e17ab405dc0fd35499e9ca4e389c providers/fips/self_test_kats.c
99baeec10374301e90352ab637056104a8ea28a6880804f44c640d0c9ee16eba providers/implementations/asymciphers/rsa_enc.c
4db1826ecce8b60cb641bcd7a61430ec8cef73d2fe3cbc06aa33526afe1c954a providers/implementations/ciphers/cipher_aes.c
6ba7d817081cf0d87ba7bfb38cd9d70e41505480bb8bc796ef896f68d4514ea6 providers/implementations/ciphers/cipher_aes.h
aef500281e7cd5a25a806a9bd45ec00a5b73984673202527dac5896fbcc9fa9c providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c
7668e5c1cac474ad7b0f28aa78ca885edf44815fe4a606a6cd328b3c02fac25a providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h
26e0f28523b416ba4067e471061f5a11fd76f5dc8bfe57ce37a137cf5667630b providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c
6d2ab2e059ef38fad342d4c65eebd533c08a2092bb174ff3566c6604e175c5a4 providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c
f37c3cf9e2e6fcfcbed941f3670b790fe09990349db72eb065bef51705d46e96 providers/implementations/ciphers/cipher_aes_ccm.c
00f36bf48e522dbb5ec71df0ec13e387955fa3672e6ff90e8a412ae95c4a642f providers/implementations/ciphers/cipher_aes_ccm.h
6337b570e0dc4e98af07aa9704254d3ab958cf605584e250fbd76cd1d2a25ac7 providers/implementations/ciphers/cipher_aes_ccm_hw.c
302b3819ff9fdfed750185421616b248b0e1233d75b45a065490fe4762b42f55 providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc
a8eaca99a71521ff8ac4ffcf08315e59220f7e0b7f505ecddad04fadd021ec14 providers/implementations/ciphers/cipher_aes_cts.inc
7e886ecc088b5903aa082eac72a4c46f9064392bdf5723a592368ecebfeb71c0 providers/implementations/ciphers/cipher_aes_gcm.c
79f5a732820d2512a7f4fc2a99ece7e6e2523a51e62561eb67a4b70d5538b0c4 providers/implementations/ciphers/cipher_aes_gcm.h
ab298c5f89f3165fa11093fad8063b7bcbff0924b43fb3107148ae66d54adcb5 providers/implementations/ciphers/cipher_aes_gcm_hw.c
8ed4a100e4756c31c56147b4b0fab76a4c6e5292aa2f079045f37b5502fd41b9 providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc
4c6f3a2818754a5aa7b6db36dae53e248504f9e82cc5af2ed68c723903d4f9d5 providers/implementations/ciphers/cipher_aes_hw.c
89de794c090192459d99d95bc4a422e7782e62192cd0fdb3bdef4128cfedee68 providers/implementations/ciphers/cipher_aes_hw_aesni.inc
-fac3a1878dc9c0c363d0ecdd9f74926157df54ca4f40adf8c479927395082008 providers/implementations/ciphers/cipher_aes_ocb.c
+0d77239f0cc1a9e1ecdeb45b6fae12cac2637771d29842199be08699e59f87fc providers/implementations/ciphers/cipher_aes_ocb.c
88138a1aff9705e608c0557653be92eb4de65b152555a2b79ec8b2a8fae73e8f providers/implementations/ciphers/cipher_aes_ocb.h
855869ab5a8d7a61a11674cfe5d503dfa67f59e7e393730835d1d8cf0ab85c70 providers/implementations/ciphers/cipher_aes_ocb_hw.c
6a8782c728575d69c86b735c9f47acda5c0daa04e17f1e0faef2c963f23fab20 providers/implementations/ciphers/cipher_aes_wrp.c
527ff9277b92606517ee7af13225a9d5fcffbbc36eb18bce39f59d594cbe4931 providers/implementations/ciphers/cipher_aes_xts.c
c4a2499b214d7cf786dafaaee5c8c6963b3d5d1c27c144eec4b460f839074a3b providers/implementations/ciphers/cipher_aes_xts.h
281157d1da4d7285d878978e6d42d0d33b3a6bc16e3bc5b6879e39093a7d70da providers/implementations/ciphers/cipher_aes_xts_fips.c
f358c4121a8a223e2c6cf009fd28b8a195520279016462890214e8858880f632 providers/implementations/ciphers/cipher_aes_xts_hw.c
46ba8271917b53fd8fdf77aee19cc326a219c950b94e043d6d118dcac25ad7ad providers/implementations/ciphers/cipher_cts.c
74640ce402acc704af72e055fb7f27e6aa8efd417babc56f710478e571d8631c providers/implementations/ciphers/cipher_cts.h
fcc3bb0637864252402aaa9d543209909df9a39611127f777b168bc888498dc0 providers/implementations/ciphers/cipher_tdes.c
77709f7fc3f7c08986cd4f0ebf2ef6e44bacb975c1483ef444b3cf5e5071f9d6 providers/implementations/ciphers/cipher_tdes.h
f6b81faf6abf3baa926be7c054cda1ff2be109b0a2143b34b2f2d266b6cb2c52 providers/implementations/ciphers/cipher_tdes_common.c
50645122f08ef4891cd96cace833bd550be7f5278ab785515fd61fe8993c8c25 providers/implementations/ciphers/cipher_tdes_hw.c
1f44963b1ac450cb77d75df9fbf956b04742e38d236d316c7eb8021bdf0573a4 providers/implementations/ciphers/ciphercommon.c
dd72ea861edf70b94197821ceb00e07165d550934a2e851d62afa5034b79f468 providers/implementations/ciphers/ciphercommon_block.c
8af515e63a0c16ff35dcedcc43c7b4735a10943f1e937eeeb73eb1af3dc92782 providers/implementations/ciphers/ciphercommon_ccm.c
8b6828f188c2590c7d9c6cac13fa0eb6d38a522b0f2859e7c8a766580fa9b66e providers/implementations/ciphers/ciphercommon_ccm_hw.c
142785a128a0d694e2457e7d79da545791b73ae388dcf700b538763099f91f65 providers/implementations/ciphers/ciphercommon_gcm.c
bb67eaa7a98494ca938726f9218213870fc97dd87b56bda950626cc794baf20b providers/implementations/ciphers/ciphercommon_gcm_hw.c
23fd89e3239e596c325a8c5d23eb1fe157a8d23aa4d90ed2c574bf06dfabd693 providers/implementations/ciphers/ciphercommon_hw.c
c4b1cb143de15acc396ce2e03fdd165defd25ebc831de9cdfacf408ea883c666 providers/implementations/ciphers/ciphercommon_local.h
39b47b6ef9d71852964c26e07ef0e9b23f04c7493b1b16ba7c3dba7074b6b70d providers/implementations/digests/digestcommon.c
80551b53302d95faea257df3edbdbd02d48427ce42da2c4335f998456400d057 providers/implementations/digests/sha2_prov.c
de342d04be6af69037922d5c97bdc40c0c27f6740636e72786a765d0d8ad9173 providers/implementations/digests/sha3_prov.c
b5f94d597df72ca58486c59b2a70b4057d13f09528f861ed41a84b7125b54a82 providers/implementations/exchange/dh_exch.c
9c46dc0d859875fcc0bc3d61a7b610cd3520b1bf63718775c1124f54a1fe5f24 providers/implementations/exchange/ecdh_exch.c
9bf87b8429398a6465c7e9f749a33b84974303a458736b56f3359b30726d3969 providers/implementations/exchange/ecx_exch.c
4692ea3852bf5763db576359bd793fc1ec3bcd0ca42fc906991d7ec4cced7b2a providers/implementations/exchange/kdf_exch.c
996f1397f61b9eab1e31b5d06bccd9ac958dbd5982fd41fdb263ee889b84275c providers/implementations/include/prov/ciphercommon.h
a9f5de1623221f327245957ec1dfd66a1914bff25adf4bcb81213c7955d19382 providers/implementations/include/prov/ciphercommon_aead.h
dd07797d61988fd4124cfb920616df672938da80649fac5977bfd061c981edc5 providers/implementations/include/prov/ciphercommon_ccm.h
0c1e99d70155402a790e4de65923228c8df8ad970741caccfe8b513837457d7f providers/implementations/include/prov/ciphercommon_gcm.h
b9a61ce951c1904d8315b1bb26c0ab0aaadb47e71d4ead5df0a891608c728c4b providers/implementations/include/prov/digestcommon.h
3e2558c36298cdb4fdaebe5a0cfa1dbbc78e0f60a9012f3a34e711cafb09c7b5 providers/implementations/include/prov/implementations.h
5f09fc71874b00419d71646714f21ebbdcceda277463b6f77d3d3ea6946914e8 providers/implementations/include/prov/kdfexchange.h
c95ce5498e724b9b3d58e3c2f4723e7e3e4beb07f9bea9422e43182cbadb43af providers/implementations/include/prov/macsignature.h
29d1a112b799e1f45fdf8bcee8361c2ed67428c250c1cdf408a9fbb7ebf4cce1 providers/implementations/include/prov/names.h
2187713b446d8b6d24ee986748b941ac3e24292c71e07ff9fb53a33021decdda providers/implementations/include/prov/seeding.h
-d376c58489ae36fbece94bb88939845ced04a2a0bdd55d6a3562e45a56577ae1 providers/implementations/kdfs/hkdf.c
+6091dd22e716fbe6c7c94524cdee6ad4432a572f2d3c4d360dcafafa3902d692 providers/implementations/kdfs/hkdf.c
a62e3af09f5af84dcf36f951ba4ac90ca1694adaf3747126186020b155f94186 providers/implementations/kdfs/kbkdf.c
e0644e727aacfea4da3cf2c4d2602d7ef0626ebb760b6467432ffd54d5fbb24d providers/implementations/kdfs/pbkdf2.c
c0778565abff112c0c5257329a7750ec4605e62f26cc36851fa1fbee6e03c70c providers/implementations/kdfs/pbkdf2.h
abe2b0f3711eaa34846e155cffc9242e4051c45de896f747afd5ac9d87f637dc providers/implementations/kdfs/pbkdf2_fips.c
9cc42a4b0a8089e6d1be64637dbb9e41bd21ae5e3386022a27a8f29308ad25c9 providers/implementations/kdfs/sshkdf.c
8571556d77d10e8edc98212473a38f09632e3f19e9995dde89ee6c95f2e84ccf providers/implementations/kdfs/sskdf.c
589f6133799da80760e8bc3ab0191a341ab6d4d2706e92e6eb4a24b0250fefa6 providers/implementations/kdfs/tls1_prf.c
4d4a6d9a562d2dcfec941d3f113a544663b5ac2fbe4accd89ec70c1cc11751d0 providers/implementations/kdfs/x942kdf.c
-6b6c776b12664164f3cb54c21df61e1c4477c7855d89431a16fb338cdae58d43 providers/implementations/kem/rsa_kem.c
+58acb0ff36bf7e463ba714b347b714eccab9fda77c4ca6bacc3a55e6d2ce5ad9 providers/implementations/kem/rsa_kem.c
11a0d0fb88ed88e965f10b3a0ef6c880f60341df995128f57ad943053aaf15b2 providers/implementations/keymgmt/dh_kmgmt.c
-a329f57cb041cd03907e9d996fbc2f378ee116c7f8d7fbf1ea08b7a5df7e0304 providers/implementations/keymgmt/dsa_kmgmt.c
+9316fc619e8d8a1d841aa0936fc62c28eb2b4c60cc6c9b2d64b72f8641f28abb providers/implementations/keymgmt/dsa_kmgmt.c
9bc88451d3ae110c7a108ee73d3b3b6bda801ec3494d2dfb9c9970b85c2d34fe providers/implementations/keymgmt/ec_kmgmt.c
258ae17bb2dd87ed1511a8eb3fe99eed9b77f5c2f757215ff6b3d0e8791fc251 providers/implementations/keymgmt/ec_kmgmt_imexport.inc
-011c36aad6834729043f23eacab417732541ee23916d9afa5bb9164862be00bb providers/implementations/keymgmt/ecx_kmgmt.c
+d0c67b7fbddd51dcfebd96bf99794ca3bc437d50974ebcd56968fb8dd3627b0f providers/implementations/keymgmt/ecx_kmgmt.c
053a2be39a87f50b877ebdbbf799cf5faf8b2de33b04311d819d212ee1ea329b providers/implementations/keymgmt/kdf_legacy_kmgmt.c
-1646b477fa231dd0f6c22444c99098f9b447cab0d39ff69b811262469d4dbe09 providers/implementations/keymgmt/mac_legacy_kmgmt.c
+37e2f9f904eeabf94b1e4152b67ac236f872aa78dd7e47bf0de1b8f50ac19b6c providers/implementations/keymgmt/mac_legacy_kmgmt.c
19f22fc70a6321441e56d5bd4aab3d01d52d17069d4e4b5cefce0f411ecece75 providers/implementations/keymgmt/rsa_kmgmt.c
5eb96ea2df635cf79c5aeccae270fbe896b5e6384a5b3e4b187ce8c10fe8dfc7 providers/implementations/macs/cmac_prov.c
e69aa06f8f3c6f5a26702b9f44a844b8589b99dc0ee590953a29e8b9ef10acbe providers/implementations/macs/gmac_prov.c
895c8dc7235b9ad5ff893be0293cbc245a5455e8850195ac7d446646e4ea71d0 providers/implementations/macs/hmac_prov.c
8640b63fd8325aaf8f7128d6cc448d9af448a65bf51a8978075467d33a67944e providers/implementations/macs/kmac_prov.c
bf30274dd6b528ae913984775bd8f29c6c48c0ef06d464d0f738217727b7aa5c providers/implementations/rands/crngt.c
f9457255fc57ef5739aa2584e535195e38cc947e31fd044d28d64c28c8a946ce providers/implementations/rands/drbg.c
7e8fa6333845778474ed1313a66867512512372c9397f699a8f68fa6d5fc05fa providers/implementations/rands/drbg_ctr.c
8337994f4bc95e421d6d2833bb4481ad9d84deb3913d0faec6e1791ea372a793 providers/implementations/rands/drbg_hash.c
1f040090f596f88cb64d6eb89109a8b75e66caee113708fb59335ad2547027fc providers/implementations/rands/drbg_hmac.c
7a1b8516f891f25f3dc07ffe0455200f20d3a1f0345a917f00c7d9afe900bb0a providers/implementations/rands/drbg_local.h
04339b66c10017229ef368cb48077f58a252ebfda9ab12b9f919e4149b1036ed providers/implementations/rands/test_rng.c
cafb9e6f54ad15889fcebddac6df61336bff7d78936f7de3bb5aab8aee5728d2 providers/implementations/signature/dsa_sig.c
a30dc6308de0ca33406e7ce909f3bcf7580fb84d863b0976b275839f866258df providers/implementations/signature/ecdsa_sig.c
-02e833a767afbe98247d6f09dfb1eb5a5cf7304a93f2c5427a9f6af9c8a3b549 providers/implementations/signature/eddsa_sig.c
+09647b736980ac3c762f1e7c10cbfee78e2c6ab327ac62e5039968cea034ff3b providers/implementations/signature/eddsa_sig.c
3bb0f342b4cc1b4594ed0986adc47791c0a7b5c1ae7b1888c1fb5edb268a78d9 providers/implementations/signature/mac_legacy_sig.c
166d7e3a049b28ae2c6f94415070720d176a82e46af1613511c4b073ea705476 providers/implementations/signature/rsa_sig.c
a14e901b02fe095713624db4080b3aa3ca685d43f9ebec03041f992240973346 ssl/record/tls_pad.c
3f2e01a98d9e3fda6cc5cb4b44dd43f6cae4ec34994e8f734d11b1e643e58636 ssl/s3_cbc.c
diff --git a/crypto/openssl/providers/fips.checksum b/crypto/openssl/providers/fips.checksum
index cbd9c0951179..0904f6a1029e 100644
--- a/crypto/openssl/providers/fips.checksum
+++ b/crypto/openssl/providers/fips.checksum
@@ -1 +1 @@
-101807560af8f62c064ad796dfa1e4c269d45aaf5303b47ad0b25fdd6cc92466 providers/fips-sources.checksums
+01b31117f96429fe4c8efbf7f4f10ef32efa2b11c69851fd227e4194db116b6f providers/fips-sources.checksums
diff --git a/crypto/openssl/providers/implementations/ciphers/cipher_aes_ocb.c b/crypto/openssl/providers/implementations/ciphers/cipher_aes_ocb.c
index eab315453ef1..891e73f6726c 100644
--- a/crypto/openssl/providers/implementations/ciphers/cipher_aes_ocb.c
+++ b/crypto/openssl/providers/implementations/ciphers/cipher_aes_ocb.c
@@ -1,562 +1,570 @@
/*
* Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_aes_ocb.h"
#include "prov/providercommon.h"
#include "prov/ciphercommon_aead.h"
#include "prov/implementations.h"
#define AES_OCB_FLAGS AEAD_FLAGS
#define OCB_DEFAULT_TAG_LEN 16
#define OCB_DEFAULT_IV_LEN 12
#define OCB_MIN_IV_LEN 1
#define OCB_MAX_IV_LEN 15
PROV_CIPHER_FUNC(int, ocb_cipher, (PROV_AES_OCB_CTX *ctx,
const unsigned char *in, unsigned char *out,
size_t nextblock));
/* forward declarations */
static OSSL_FUNC_cipher_encrypt_init_fn aes_ocb_einit;
static OSSL_FUNC_cipher_decrypt_init_fn aes_ocb_dinit;
static OSSL_FUNC_cipher_update_fn aes_ocb_block_update;
static OSSL_FUNC_cipher_final_fn aes_ocb_block_final;
static OSSL_FUNC_cipher_cipher_fn aes_ocb_cipher;
static OSSL_FUNC_cipher_freectx_fn aes_ocb_freectx;
static OSSL_FUNC_cipher_dupctx_fn aes_ocb_dupctx;
static OSSL_FUNC_cipher_get_ctx_params_fn aes_ocb_get_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn aes_ocb_set_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn cipher_ocb_gettable_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn cipher_ocb_settable_ctx_params;
/*
* The following methods could be moved into PROV_AES_OCB_HW if
* multiple hardware implementations are ever needed.
*/
static ossl_inline int aes_generic_ocb_setiv(PROV_AES_OCB_CTX *ctx,
const unsigned char *iv,
size_t ivlen, size_t taglen)
{
return (CRYPTO_ocb128_setiv(&ctx->ocb, iv, ivlen, taglen) == 1);
}
static ossl_inline int aes_generic_ocb_setaad(PROV_AES_OCB_CTX *ctx,
const unsigned char *aad,
size_t alen)
{
return CRYPTO_ocb128_aad(&ctx->ocb, aad, alen) == 1;
}
static ossl_inline int aes_generic_ocb_gettag(PROV_AES_OCB_CTX *ctx,
unsigned char *tag, size_t tlen)
{
return CRYPTO_ocb128_tag(&ctx->ocb, tag, tlen) > 0;
}
static ossl_inline int aes_generic_ocb_final(PROV_AES_OCB_CTX *ctx)
{
return (CRYPTO_ocb128_finish(&ctx->ocb, ctx->tag, ctx->taglen) == 0);
}
static ossl_inline void aes_generic_ocb_cleanup(PROV_AES_OCB_CTX *ctx)
{
CRYPTO_ocb128_cleanup(&ctx->ocb);
}
static ossl_inline int aes_generic_ocb_cipher(PROV_AES_OCB_CTX *ctx,
const unsigned char *in,
unsigned char *out, size_t len)
{
if (ctx->base.enc) {
if (!CRYPTO_ocb128_encrypt(&ctx->ocb, in, out, len))
return 0;
} else {
if (!CRYPTO_ocb128_decrypt(&ctx->ocb, in, out, len))
return 0;
}
return 1;
}
static ossl_inline int aes_generic_ocb_copy_ctx(PROV_AES_OCB_CTX *dst,
PROV_AES_OCB_CTX *src)
{
return CRYPTO_ocb128_copy_ctx(&dst->ocb, &src->ocb,
&dst->ksenc.ks, &dst->ksdec.ks);
}
/*-
* Provider dispatch functions
*/
static int aes_ocb_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[], int enc)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
ctx->aad_buf_len = 0;
ctx->data_buf_len = 0;
ctx->base.enc = enc;
if (iv != NULL) {
if (ivlen != ctx->base.ivlen) {
/* IV len must be 1 to 15 */
if (ivlen < OCB_MIN_IV_LEN || ivlen > OCB_MAX_IV_LEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
ctx->base.ivlen = ivlen;
}
if (!ossl_cipher_generic_initiv(&ctx->base, iv, ivlen))
return 0;
ctx->iv_state = IV_STATE_BUFFERED;
}
if (key != NULL) {
if (keylen != ctx->base.keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
if (!ctx->base.hw->init(&ctx->base, key, keylen))
return 0;
}
return aes_ocb_set_ctx_params(ctx, params);
}
static int aes_ocb_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return aes_ocb_init(vctx, key, keylen, iv, ivlen, params, 1);
}
static int aes_ocb_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return aes_ocb_init(vctx, key, keylen, iv, ivlen, params, 0);
}
/*
* Because of the way OCB works, both the AAD and data are buffered in the
* same way. Only the last block can be a partial block.
*/
static int aes_ocb_block_update_internal(PROV_AES_OCB_CTX *ctx,
unsigned char *buf, size_t *bufsz,
unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl, OSSL_ocb_cipher_fn ciph)
{
size_t nextblocks;
size_t outlint = 0;
if (*bufsz != 0)
nextblocks = ossl_cipher_fillblock(buf, bufsz, AES_BLOCK_SIZE, &in, &inl);
else
nextblocks = inl & ~(AES_BLOCK_SIZE-1);
if (*bufsz == AES_BLOCK_SIZE) {
if (outsize < AES_BLOCK_SIZE) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ciph(ctx, buf, out, AES_BLOCK_SIZE)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
*bufsz = 0;
outlint = AES_BLOCK_SIZE;
if (out != NULL)
out += AES_BLOCK_SIZE;
}
if (nextblocks > 0) {
outlint += nextblocks;
if (outsize < outlint) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ciph(ctx, in, out, nextblocks)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
in += nextblocks;
inl -= nextblocks;
}
if (inl != 0
&& !ossl_cipher_trailingdata(buf, bufsz, AES_BLOCK_SIZE, &in, &inl)) {
/* PROVerr already called */
return 0;
}
*outl = outlint;
return inl == 0;
}
/* A wrapper function that has the same signature as cipher */
static int cipher_updateaad(PROV_AES_OCB_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
return aes_generic_ocb_setaad(ctx, in, len);
}
static int update_iv(PROV_AES_OCB_CTX *ctx)
{
if (ctx->iv_state == IV_STATE_FINISHED
|| ctx->iv_state == IV_STATE_UNINITIALISED)
return 0;
if (ctx->iv_state == IV_STATE_BUFFERED) {
if (!aes_generic_ocb_setiv(ctx, ctx->base.iv, ctx->base.ivlen,
ctx->taglen))
return 0;
ctx->iv_state = IV_STATE_COPIED;
}
return 1;
}
static int aes_ocb_block_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
unsigned char *buf;
size_t *buflen;
OSSL_ocb_cipher_fn fn;
if (!ctx->key_set || !update_iv(ctx))
return 0;
if (inl == 0) {
*outl = 0;
return 1;
}
/* Are we dealing with AAD or normal data here? */
if (out == NULL) {
buf = ctx->aad_buf;
buflen = &ctx->aad_buf_len;
fn = cipher_updateaad;
} else {
buf = ctx->data_buf;
buflen = &ctx->data_buf_len;
fn = aes_generic_ocb_cipher;
}
return aes_ocb_block_update_internal(ctx, buf, buflen, out, outl, outsize,
in, inl, fn);
}
static int aes_ocb_block_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
/* If no block_update has run then the iv still needs to be set */
if (!ctx->key_set || !update_iv(ctx))
return 0;
/*
* Empty the buffer of any partial block that we might have been provided,
* both for data and AAD
*/
*outl = 0;
if (ctx->data_buf_len > 0) {
if (!aes_generic_ocb_cipher(ctx, ctx->data_buf, out, ctx->data_buf_len))
return 0;
*outl = ctx->data_buf_len;
ctx->data_buf_len = 0;
}
if (ctx->aad_buf_len > 0) {
if (!aes_generic_ocb_setaad(ctx, ctx->aad_buf, ctx->aad_buf_len))
return 0;
ctx->aad_buf_len = 0;
}
if (ctx->base.enc) {
/* If encrypting then just get the tag */
if (!aes_generic_ocb_gettag(ctx, ctx->tag, ctx->taglen))
return 0;
} else {
/* If decrypting then verify */
if (ctx->taglen == 0)
return 0;
if (!aes_generic_ocb_final(ctx))
return 0;
}
/* Don't reuse the IV */
ctx->iv_state = IV_STATE_FINISHED;
return 1;
}
static void *aes_ocb_newctx(void *provctx, size_t kbits, size_t blkbits,
size_t ivbits, unsigned int mode, uint64_t flags)
{
PROV_AES_OCB_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL) {
ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
ossl_prov_cipher_hw_aes_ocb(kbits), NULL);
ctx->taglen = OCB_DEFAULT_TAG_LEN;
}
return ctx;
}
static void aes_ocb_freectx(void *vctx)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
if (ctx != NULL) {
aes_generic_ocb_cleanup(ctx);
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
static void *aes_ocb_dupctx(void *vctx)
{
PROV_AES_OCB_CTX *in = (PROV_AES_OCB_CTX *)vctx;
PROV_AES_OCB_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
if (!aes_generic_ocb_copy_ctx(ret, in)) {
OPENSSL_free(ret);
ret = NULL;
}
return ret;
}
static int aes_ocb_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
const OSSL_PARAM *p;
size_t sz;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (p->data == NULL) {
/* Tag len must be 0 to 16 */
- if (p->data_size > OCB_MAX_TAG_LEN)
+ if (p->data_size > OCB_MAX_TAG_LEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
return 0;
+ }
ctx->taglen = p->data_size;
} else {
- if (p->data_size != ctx->taglen || ctx->base.enc)
+ if (ctx->base.enc) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ if (p->data_size != ctx->taglen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
return 0;
+ }
memcpy(ctx->tag, p->data, p->data_size);
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
/* IV len must be 1 to 15 */
if (sz < OCB_MIN_IV_LEN || sz > OCB_MAX_IV_LEN)
return 0;
if (ctx->base.ivlen != sz) {
ctx->base.ivlen = sz;
ctx->iv_state = IV_STATE_UNINITIALISED;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
size_t keylen;
if (!OSSL_PARAM_get_size_t(p, &keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (ctx->base.keylen != keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
return 1;
}
static int aes_ocb_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
if (p != NULL) {
if (!OSSL_PARAM_set_size_t(p, ctx->taglen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
if (p != NULL) {
if (ctx->base.ivlen > p->data_size) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
if (!OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->base.oiv, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
if (p != NULL) {
if (ctx->base.ivlen > p->data_size) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
if (!OSSL_PARAM_set_octet_string(p, ctx->base.iv, ctx->base.ivlen)
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->base.iv, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (!ctx->base.enc || p->data_size != ctx->taglen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
return 0;
}
memcpy(p->data, ctx->tag, ctx->taglen);
}
return 1;
}
static const OSSL_PARAM cipher_ocb_known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *cipher_ocb_gettable_ctx_params(ossl_unused void *cctx,
ossl_unused void *p_ctx)
{
return cipher_ocb_known_gettable_ctx_params;
}
static const OSSL_PARAM cipher_ocb_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *cipher_ocb_settable_ctx_params(ossl_unused void *cctx,
ossl_unused void *p_ctx)
{
return cipher_ocb_known_settable_ctx_params;
}
static int aes_ocb_cipher(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!aes_generic_ocb_cipher(ctx, in, out, inl)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
*outl = inl;
return 1;
}
#define IMPLEMENT_cipher(mode, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##mode##_get_params; \
static int aes_##kbits##_##mode##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, kbits, blkbits, ivbits); \
} \
static OSSL_FUNC_cipher_newctx_fn aes_##kbits##_##mode##_newctx; \
static void *aes_##kbits##_##mode##_newctx(void *provctx) \
{ \
return aes_##mode##_newctx(provctx, kbits, blkbits, ivbits, \
EVP_CIPH_##UCMODE##_MODE, flags); \
} \
const OSSL_DISPATCH ossl_##aes##kbits##mode##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, \
(void (*)(void))aes_##kbits##_##mode##_newctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_block_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_block_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_ocb_cipher }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void))aes_##kbits##_##mode##_get_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))aes_##mode##_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))aes_##mode##_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_ocb_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_ocb_settable_ctx_params }, \
{ 0, NULL } \
}
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 256, 128, OCB_DEFAULT_IV_LEN * 8);
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 192, 128, OCB_DEFAULT_IV_LEN * 8);
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 128, 128, OCB_DEFAULT_IV_LEN * 8);
diff --git a/crypto/openssl/providers/implementations/encode_decode/encode_key2text.c b/crypto/openssl/providers/implementations/encode_decode/encode_key2text.c
index 3e75a9afb370..637fcf6a1214 100644
--- a/crypto/openssl/providers/implementations/encode_decode/encode_key2text.c
+++ b/crypto/openssl/providers/implementations/encode_decode/encode_key2text.c
@@ -1,876 +1,877 @@
/*
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* Low level APIs are deprecated for public use, but still ok for internal use.
*/
#include "internal/deprecated.h"
#include <ctype.h>
#include <openssl/core.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/safestack.h>
#include <openssl/proverr.h>
#include "internal/ffc.h"
#include "crypto/bn.h" /* bn_get_words() */
#include "crypto/dh.h" /* ossl_dh_get0_params() */
#include "crypto/dsa.h" /* ossl_dsa_get0_params() */
#include "crypto/ec.h" /* ossl_ec_key_get_libctx */
#include "crypto/ecx.h" /* ECX_KEY, etc... */
#include "crypto/rsa.h" /* RSA_PSS_PARAMS_30, etc... */
#include "prov/bio.h"
#include "prov/implementations.h"
#include "endecoder_local.h"
DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
# ifdef SIXTY_FOUR_BIT_LONG
# define BN_FMTu "%lu"
# define BN_FMTx "%lx"
# endif
# ifdef SIXTY_FOUR_BIT
# define BN_FMTu "%llu"
# define BN_FMTx "%llx"
# endif
# ifdef THIRTY_TWO_BIT
# define BN_FMTu "%u"
# define BN_FMTx "%x"
# endif
static int print_labeled_bignum(BIO *out, const char *label, const BIGNUM *bn)
{
int ret = 0, use_sep = 0;
char *hex_str = NULL, *p;
const char spaces[] = " ";
const char *post_label_spc = " ";
const char *neg = "";
int bytes;
if (bn == NULL)
return 0;
if (label == NULL) {
label = "";
post_label_spc = "";
}
if (BN_is_zero(bn))
return BIO_printf(out, "%s%s0\n", label, post_label_spc);
if (BN_num_bytes(bn) <= BN_BYTES) {
BN_ULONG *words = bn_get_words(bn);
if (BN_is_negative(bn))
neg = "-";
return BIO_printf(out, "%s%s%s" BN_FMTu " (%s0x" BN_FMTx ")\n",
label, post_label_spc, neg, words[0], neg, words[0]);
}
hex_str = BN_bn2hex(bn);
if (hex_str == NULL)
return 0;
p = hex_str;
if (*p == '-') {
++p;
neg = " (Negative)";
}
if (BIO_printf(out, "%s%s\n", label, neg) <= 0)
goto err;
/* Keep track of how many bytes we have printed out so far */
bytes = 0;
if (BIO_printf(out, "%s", spaces) <= 0)
goto err;
/* Add a leading 00 if the top bit is set */
if (*p >= '8') {
if (BIO_printf(out, "%02x", 0) <= 0)
goto err;
++bytes;
use_sep = 1;
}
while (*p != '\0') {
/* Do a newline after every 15 hex bytes + add the space indent */
if ((bytes % 15) == 0 && bytes > 0) {
if (BIO_printf(out, ":\n%s", spaces) <= 0)
goto err;
use_sep = 0; /* The first byte on the next line doesnt have a : */
}
if (BIO_printf(out, "%s%c%c", use_sep ? ":" : "",
- tolower(p[0]), tolower(p[1])) <= 0)
+ tolower((unsigned char)p[0]),
+ tolower((unsigned char)p[1])) <= 0)
goto err;
++bytes;
p += 2;
use_sep = 1;
}
if (BIO_printf(out, "\n") <= 0)
goto err;
ret = 1;
err:
OPENSSL_free(hex_str);
return ret;
}
/* Number of octets per line */
#define LABELED_BUF_PRINT_WIDTH 15
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
static int print_labeled_buf(BIO *out, const char *label,
const unsigned char *buf, size_t buflen)
{
size_t i;
if (BIO_printf(out, "%s\n", label) <= 0)
return 0;
for (i = 0; i < buflen; i++) {
if ((i % LABELED_BUF_PRINT_WIDTH) == 0) {
if (i > 0 && BIO_printf(out, "\n") <= 0)
return 0;
if (BIO_printf(out, " ") <= 0)
return 0;
}
if (BIO_printf(out, "%02x%s", buf[i],
(i == buflen - 1) ? "" : ":") <= 0)
return 0;
}
if (BIO_printf(out, "\n") <= 0)
return 0;
return 1;
}
#endif
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA)
static int ffc_params_to_text(BIO *out, const FFC_PARAMS *ffc)
{
if (ffc->nid != NID_undef) {
#ifndef OPENSSL_NO_DH
const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid);
const char *name = ossl_ffc_named_group_get_name(group);
if (name == NULL)
goto err;
if (BIO_printf(out, "GROUP: %s\n", name) <= 0)
goto err;
return 1;
#else
/* How could this be? We should not have a nid in a no-dh build. */
goto err;
#endif
}
if (!print_labeled_bignum(out, "P: ", ffc->p))
goto err;
if (ffc->q != NULL) {
if (!print_labeled_bignum(out, "Q: ", ffc->q))
goto err;
}
if (!print_labeled_bignum(out, "G: ", ffc->g))
goto err;
if (ffc->j != NULL) {
if (!print_labeled_bignum(out, "J: ", ffc->j))
goto err;
}
if (ffc->seed != NULL) {
if (!print_labeled_buf(out, "SEED:", ffc->seed, ffc->seedlen))
goto err;
}
if (ffc->gindex != -1) {
if (BIO_printf(out, "gindex: %d\n", ffc->gindex) <= 0)
goto err;
}
if (ffc->pcounter != -1) {
if (BIO_printf(out, "pcounter: %d\n", ffc->pcounter) <= 0)
goto err;
}
if (ffc->h != 0) {
if (BIO_printf(out, "h: %d\n", ffc->h) <= 0)
goto err;
}
return 1;
err:
return 0;
}
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_DH
static int dh_to_text(BIO *out, const void *key, int selection)
{
const DH *dh = key;
const char *type_label = NULL;
const BIGNUM *priv_key = NULL, *pub_key = NULL;
const FFC_PARAMS *params = NULL;
const BIGNUM *p = NULL;
long length;
if (out == NULL || dh == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
type_label = "DH Private-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
type_label = "DH Public-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
type_label = "DH Parameters";
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
priv_key = DH_get0_priv_key(dh);
if (priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
pub_key = DH_get0_pub_key(dh);
if (pub_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
params = ossl_dh_get0_params((DH *)dh);
if (params == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_PARAMETERS);
return 0;
}
}
p = DH_get0_p(dh);
if (p == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
if (BIO_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) <= 0)
return 0;
if (priv_key != NULL
&& !print_labeled_bignum(out, "private-key:", priv_key))
return 0;
if (pub_key != NULL
&& !print_labeled_bignum(out, "public-key:", pub_key))
return 0;
if (params != NULL
&& !ffc_params_to_text(out, params))
return 0;
length = DH_get_length(dh);
if (length > 0
&& BIO_printf(out, "recommended-private-length: %ld bits\n",
length) <= 0)
return 0;
return 1;
}
# define dh_input_type "DH"
# define dhx_input_type "DHX"
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_DSA
static int dsa_to_text(BIO *out, const void *key, int selection)
{
const DSA *dsa = key;
const char *type_label = NULL;
const BIGNUM *priv_key = NULL, *pub_key = NULL;
const FFC_PARAMS *params = NULL;
const BIGNUM *p = NULL;
if (out == NULL || dsa == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
type_label = "Private-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
type_label = "Public-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
type_label = "DSA-Parameters";
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
priv_key = DSA_get0_priv_key(dsa);
if (priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
pub_key = DSA_get0_pub_key(dsa);
if (pub_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
params = ossl_dsa_get0_params((DSA *)dsa);
if (params == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_PARAMETERS);
return 0;
}
}
p = DSA_get0_p(dsa);
if (p == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
if (BIO_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) <= 0)
return 0;
if (priv_key != NULL
&& !print_labeled_bignum(out, "priv:", priv_key))
return 0;
if (pub_key != NULL
&& !print_labeled_bignum(out, "pub: ", pub_key))
return 0;
if (params != NULL
&& !ffc_params_to_text(out, params))
return 0;
return 1;
}
# define dsa_input_type "DSA"
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_EC
static int ec_param_explicit_curve_to_text(BIO *out, const EC_GROUP *group,
BN_CTX *ctx)
{
const char *plabel = "Prime:";
BIGNUM *p = NULL, *a = NULL, *b = NULL;
p = BN_CTX_get(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
if (b == NULL
|| !EC_GROUP_get_curve(group, p, a, b, ctx))
return 0;
if (EC_GROUP_get_field_type(group) == NID_X9_62_characteristic_two_field) {
int basis_type = EC_GROUP_get_basis_type(group);
/* print the 'short name' of the base type OID */
if (basis_type == NID_undef
|| BIO_printf(out, "Basis Type: %s\n", OBJ_nid2sn(basis_type)) <= 0)
return 0;
plabel = "Polynomial:";
}
return print_labeled_bignum(out, plabel, p)
&& print_labeled_bignum(out, "A: ", a)
&& print_labeled_bignum(out, "B: ", b);
}
static int ec_param_explicit_gen_to_text(BIO *out, const EC_GROUP *group,
BN_CTX *ctx)
{
int ret;
size_t buflen;
point_conversion_form_t form;
const EC_POINT *point = NULL;
const char *glabel = NULL;
unsigned char *buf = NULL;
form = EC_GROUP_get_point_conversion_form(group);
point = EC_GROUP_get0_generator(group);
if (point == NULL)
return 0;
switch (form) {
case POINT_CONVERSION_COMPRESSED:
glabel = "Generator (compressed):";
break;
case POINT_CONVERSION_UNCOMPRESSED:
glabel = "Generator (uncompressed):";
break;
case POINT_CONVERSION_HYBRID:
glabel = "Generator (hybrid):";
break;
default:
return 0;
}
buflen = EC_POINT_point2buf(group, point, form, &buf, ctx);
if (buflen == 0)
return 0;
ret = print_labeled_buf(out, glabel, buf, buflen);
OPENSSL_clear_free(buf, buflen);
return ret;
}
/* Print explicit parameters */
static int ec_param_explicit_to_text(BIO *out, const EC_GROUP *group,
OSSL_LIB_CTX *libctx)
{
int ret = 0, tmp_nid;
BN_CTX *ctx = NULL;
const BIGNUM *order = NULL, *cofactor = NULL;
const unsigned char *seed;
size_t seed_len = 0;
ctx = BN_CTX_new_ex(libctx);
if (ctx == NULL)
return 0;
BN_CTX_start(ctx);
tmp_nid = EC_GROUP_get_field_type(group);
order = EC_GROUP_get0_order(group);
if (order == NULL)
goto err;
seed = EC_GROUP_get0_seed(group);
if (seed != NULL)
seed_len = EC_GROUP_get_seed_len(group);
cofactor = EC_GROUP_get0_cofactor(group);
/* print the 'short name' of the field type */
if (BIO_printf(out, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) <= 0
|| !ec_param_explicit_curve_to_text(out, group, ctx)
|| !ec_param_explicit_gen_to_text(out, group, ctx)
|| !print_labeled_bignum(out, "Order: ", order)
|| (cofactor != NULL
&& !print_labeled_bignum(out, "Cofactor: ", cofactor))
|| (seed != NULL
&& !print_labeled_buf(out, "Seed:", seed, seed_len)))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ret;
}
static int ec_param_to_text(BIO *out, const EC_GROUP *group,
OSSL_LIB_CTX *libctx)
{
if (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE) {
const char *curve_name;
int curve_nid = EC_GROUP_get_curve_name(group);
/* Explicit parameters */
if (curve_nid == NID_undef)
return 0;
if (BIO_printf(out, "%s: %s\n", "ASN1 OID", OBJ_nid2sn(curve_nid)) <= 0)
return 0;
curve_name = EC_curve_nid2nist(curve_nid);
return (curve_name == NULL
|| BIO_printf(out, "%s: %s\n", "NIST CURVE", curve_name) > 0);
} else {
return ec_param_explicit_to_text(out, group, libctx);
}
}
static int ec_to_text(BIO *out, const void *key, int selection)
{
const EC_KEY *ec = key;
const char *type_label = NULL;
unsigned char *priv = NULL, *pub = NULL;
size_t priv_len = 0, pub_len = 0;
const EC_GROUP *group;
int ret = 0;
if (out == NULL || ec == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((group = EC_KEY_get0_group(ec)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
type_label = "Private-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
type_label = "Public-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
type_label = "EC-Parameters";
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
const BIGNUM *priv_key = EC_KEY_get0_private_key(ec);
if (priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
goto err;
}
priv_len = EC_KEY_priv2buf(ec, &priv);
if (priv_len == 0)
goto err;
}
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
const EC_POINT *pub_pt = EC_KEY_get0_public_key(ec);
if (pub_pt == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
goto err;
}
pub_len = EC_KEY_key2buf(ec, EC_KEY_get_conv_form(ec), &pub, NULL);
if (pub_len == 0)
goto err;
}
if (BIO_printf(out, "%s: (%d bit)\n", type_label,
EC_GROUP_order_bits(group)) <= 0)
goto err;
if (priv != NULL
&& !print_labeled_buf(out, "priv:", priv, priv_len))
goto err;
if (pub != NULL
&& !print_labeled_buf(out, "pub:", pub, pub_len))
goto err;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ret = ec_param_to_text(out, group, ossl_ec_key_get_libctx(ec));
err:
OPENSSL_clear_free(priv, priv_len);
OPENSSL_free(pub);
return ret;
}
# define ec_input_type "EC"
# ifndef OPENSSL_NO_SM2
# define sm2_input_type "SM2"
# endif
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_EC
static int ecx_to_text(BIO *out, const void *key, int selection)
{
const ECX_KEY *ecx = key;
const char *type_label = NULL;
if (out == NULL || ecx == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
switch (ecx->type) {
case ECX_KEY_TYPE_X25519:
type_label = "X25519";
break;
case ECX_KEY_TYPE_X448:
type_label = "X448";
break;
case ECX_KEY_TYPE_ED25519:
type_label = "ED25519";
break;
case ECX_KEY_TYPE_ED448:
type_label = "ED448";
break;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if (ecx->privkey == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
if (BIO_printf(out, "%s Private-Key:\n", type_label) <= 0)
return 0;
if (!print_labeled_buf(out, "priv:", ecx->privkey, ecx->keylen))
return 0;
} else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
/* ecx->pubkey is an array, not a pointer... */
if (!ecx->haspubkey) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
if (BIO_printf(out, "%s Public-Key:\n", type_label) <= 0)
return 0;
}
if (!print_labeled_buf(out, "pub:", ecx->pubkey, ecx->keylen))
return 0;
return 1;
}
# define ed25519_input_type "ED25519"
# define ed448_input_type "ED448"
# define x25519_input_type "X25519"
# define x448_input_type "X448"
#endif
/* ---------------------------------------------------------------------- */
static int rsa_to_text(BIO *out, const void *key, int selection)
{
const RSA *rsa = key;
const char *type_label = "RSA key";
const char *modulus_label = NULL;
const char *exponent_label = NULL;
const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL;
STACK_OF(BIGNUM_const) *factors = NULL;
STACK_OF(BIGNUM_const) *exps = NULL;
STACK_OF(BIGNUM_const) *coeffs = NULL;
int primes;
const RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30((RSA *)rsa);
int ret = 0;
if (out == NULL || rsa == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
factors = sk_BIGNUM_const_new_null();
exps = sk_BIGNUM_const_new_null();
coeffs = sk_BIGNUM_const_new_null();
if (factors == NULL || exps == NULL || coeffs == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
type_label = "Private-Key";
modulus_label = "modulus:";
exponent_label = "publicExponent:";
} else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
type_label = "Public-Key";
modulus_label = "Modulus:";
exponent_label = "Exponent:";
}
RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
ossl_rsa_get0_all_params((RSA *)rsa, factors, exps, coeffs);
primes = sk_BIGNUM_const_num(factors);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if (BIO_printf(out, "%s: (%d bit, %d primes)\n",
type_label, BN_num_bits(rsa_n), primes) <= 0)
goto err;
} else {
if (BIO_printf(out, "%s: (%d bit)\n",
type_label, BN_num_bits(rsa_n)) <= 0)
goto err;
}
if (!print_labeled_bignum(out, modulus_label, rsa_n))
goto err;
if (!print_labeled_bignum(out, exponent_label, rsa_e))
goto err;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
int i;
if (!print_labeled_bignum(out, "privateExponent:", rsa_d))
goto err;
if (!print_labeled_bignum(out, "prime1:",
sk_BIGNUM_const_value(factors, 0)))
goto err;
if (!print_labeled_bignum(out, "prime2:",
sk_BIGNUM_const_value(factors, 1)))
goto err;
if (!print_labeled_bignum(out, "exponent1:",
sk_BIGNUM_const_value(exps, 0)))
goto err;
if (!print_labeled_bignum(out, "exponent2:",
sk_BIGNUM_const_value(exps, 1)))
goto err;
if (!print_labeled_bignum(out, "coefficient:",
sk_BIGNUM_const_value(coeffs, 0)))
goto err;
for (i = 2; i < sk_BIGNUM_const_num(factors); i++) {
if (BIO_printf(out, "prime%d:", i + 1) <= 0)
goto err;
if (!print_labeled_bignum(out, NULL,
sk_BIGNUM_const_value(factors, i)))
goto err;
if (BIO_printf(out, "exponent%d:", i + 1) <= 0)
goto err;
if (!print_labeled_bignum(out, NULL,
sk_BIGNUM_const_value(exps, i)))
goto err;
if (BIO_printf(out, "coefficient%d:", i + 1) <= 0)
goto err;
if (!print_labeled_bignum(out, NULL,
sk_BIGNUM_const_value(coeffs, i - 1)))
goto err;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) {
switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
case RSA_FLAG_TYPE_RSA:
if (!ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
if (BIO_printf(out, "(INVALID PSS PARAMETERS)\n") <= 0)
goto err;
}
break;
case RSA_FLAG_TYPE_RSASSAPSS:
if (ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
if (BIO_printf(out, "No PSS parameter restrictions\n") <= 0)
goto err;
} else {
int hashalg_nid = ossl_rsa_pss_params_30_hashalg(pss_params);
int maskgenalg_nid =
ossl_rsa_pss_params_30_maskgenalg(pss_params);
int maskgenhashalg_nid =
ossl_rsa_pss_params_30_maskgenhashalg(pss_params);
int saltlen = ossl_rsa_pss_params_30_saltlen(pss_params);
int trailerfield =
ossl_rsa_pss_params_30_trailerfield(pss_params);
if (BIO_printf(out, "PSS parameter restrictions:\n") <= 0)
goto err;
if (BIO_printf(out, " Hash Algorithm: %s%s\n",
ossl_rsa_oaeppss_nid2name(hashalg_nid),
(hashalg_nid == NID_sha1
? " (default)" : "")) <= 0)
goto err;
if (BIO_printf(out, " Mask Algorithm: %s with %s%s\n",
ossl_rsa_mgf_nid2name(maskgenalg_nid),
ossl_rsa_oaeppss_nid2name(maskgenhashalg_nid),
(maskgenalg_nid == NID_mgf1
&& maskgenhashalg_nid == NID_sha1
? " (default)" : "")) <= 0)
goto err;
if (BIO_printf(out, " Minimum Salt Length: %d%s\n",
saltlen,
(saltlen == 20 ? " (default)" : "")) <= 0)
goto err;
if (BIO_printf(out, " Trailer Field: 0x%x%s\n",
trailerfield,
(trailerfield == 1 ? " (default)" : "")) <= 0)
goto err;
}
break;
}
}
ret = 1;
err:
sk_BIGNUM_const_free(factors);
sk_BIGNUM_const_free(exps);
sk_BIGNUM_const_free(coeffs);
return ret;
}
#define rsa_input_type "RSA"
#define rsapss_input_type "RSA-PSS"
/* ---------------------------------------------------------------------- */
static void *key2text_newctx(void *provctx)
{
return provctx;
}
static void key2text_freectx(ossl_unused void *vctx)
{
}
static int key2text_encode(void *vctx, const void *key, int selection,
OSSL_CORE_BIO *cout,
int (*key2text)(BIO *out, const void *key,
int selection),
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
{
BIO *out = ossl_bio_new_from_core_bio(vctx, cout);
int ret;
if (out == NULL)
return 0;
ret = key2text(out, key, selection);
BIO_free(out);
return ret;
}
#define MAKE_TEXT_ENCODER(impl, type) \
static OSSL_FUNC_encoder_import_object_fn \
impl##2text_import_object; \
static OSSL_FUNC_encoder_free_object_fn \
impl##2text_free_object; \
static OSSL_FUNC_encoder_encode_fn impl##2text_encode; \
\
static void *impl##2text_import_object(void *ctx, int selection, \
const OSSL_PARAM params[]) \
{ \
return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
ctx, selection, params); \
} \
static void impl##2text_free_object(void *key) \
{ \
ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
} \
static int impl##2text_encode(void *vctx, OSSL_CORE_BIO *cout, \
const void *key, \
const OSSL_PARAM key_abstract[], \
int selection, \
OSSL_PASSPHRASE_CALLBACK *cb, \
void *cbarg) \
{ \
/* We don't deal with abstract objects */ \
if (key_abstract != NULL) { \
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
return 0; \
} \
return key2text_encode(vctx, key, selection, cout, \
type##_to_text, cb, cbarg); \
} \
const OSSL_DISPATCH ossl_##impl##_to_text_encoder_functions[] = { \
{ OSSL_FUNC_ENCODER_NEWCTX, \
(void (*)(void))key2text_newctx }, \
{ OSSL_FUNC_ENCODER_FREECTX, \
(void (*)(void))key2text_freectx }, \
{ OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
(void (*)(void))impl##2text_import_object }, \
{ OSSL_FUNC_ENCODER_FREE_OBJECT, \
(void (*)(void))impl##2text_free_object }, \
{ OSSL_FUNC_ENCODER_ENCODE, \
(void (*)(void))impl##2text_encode }, \
{ 0, NULL } \
}
#ifndef OPENSSL_NO_DH
MAKE_TEXT_ENCODER(dh, dh);
MAKE_TEXT_ENCODER(dhx, dh);
#endif
#ifndef OPENSSL_NO_DSA
MAKE_TEXT_ENCODER(dsa, dsa);
#endif
#ifndef OPENSSL_NO_EC
MAKE_TEXT_ENCODER(ec, ec);
# ifndef OPENSSL_NO_SM2
MAKE_TEXT_ENCODER(sm2, ec);
# endif
MAKE_TEXT_ENCODER(ed25519, ecx);
MAKE_TEXT_ENCODER(ed448, ecx);
MAKE_TEXT_ENCODER(x25519, ecx);
MAKE_TEXT_ENCODER(x448, ecx);
#endif
MAKE_TEXT_ENCODER(rsa, rsa);
MAKE_TEXT_ENCODER(rsapss, rsa);
diff --git a/crypto/openssl/providers/implementations/kdfs/hkdf.c b/crypto/openssl/providers/implementations/kdfs/hkdf.c
index 3db8b43891a0..69ef565d04fc 100644
--- a/crypto/openssl/providers/implementations/kdfs/hkdf.c
+++ b/crypto/openssl/providers/implementations/kdfs/hkdf.c
@@ -1,791 +1,791 @@
/*
* Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* HMAC low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/core_names.h>
#include <openssl/proverr.h>
#include "internal/cryptlib.h"
#include "internal/numbers.h"
#include "internal/packet.h"
#include "crypto/evp.h"
#include "prov/provider_ctx.h"
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_util.h"
#include "e_os.h"
#define HKDF_MAXBUF 2048
#define HKDF_MAXINFO (32*1024)
static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_new;
static OSSL_FUNC_kdf_freectx_fn kdf_hkdf_free;
static OSSL_FUNC_kdf_reset_fn kdf_hkdf_reset;
static OSSL_FUNC_kdf_derive_fn kdf_hkdf_derive;
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params;
static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params;
static OSSL_FUNC_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params;
static OSSL_FUNC_kdf_derive_fn kdf_tls1_3_derive;
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params;
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params;
static int HKDF(OSSL_LIB_CTX *libctx, 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 int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *ikm, size_t ikm_len,
unsigned char *prk, size_t prk_len);
static int 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);
/* Settable context parameters that are common across HKDF and the TLS KDF */
#define HKDF_COMMON_SETTABLES \
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), \
OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL), \
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), \
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0)
typedef struct {
void *provctx;
int mode;
PROV_DIGEST digest;
unsigned char *salt;
size_t salt_len;
unsigned char *key;
size_t key_len;
unsigned char *prefix;
size_t prefix_len;
unsigned char *label;
size_t label_len;
unsigned char *data;
size_t data_len;
unsigned char *info;
size_t info_len;
} KDF_HKDF;
static void *kdf_hkdf_new(void *provctx)
{
KDF_HKDF *ctx;
if (!ossl_prov_is_running())
return NULL;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
else
ctx->provctx = provctx;
return ctx;
}
static void kdf_hkdf_free(void *vctx)
{
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
if (ctx != NULL) {
kdf_hkdf_reset(ctx);
OPENSSL_free(ctx);
}
}
static void kdf_hkdf_reset(void *vctx)
{
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
void *provctx = ctx->provctx;
ossl_prov_digest_reset(&ctx->digest);
OPENSSL_free(ctx->salt);
OPENSSL_free(ctx->prefix);
OPENSSL_free(ctx->label);
OPENSSL_clear_free(ctx->data, ctx->data_len);
OPENSSL_clear_free(ctx->key, ctx->key_len);
OPENSSL_clear_free(ctx->info, ctx->info_len);
memset(ctx, 0, sizeof(*ctx));
ctx->provctx = provctx;
}
static size_t kdf_hkdf_size(KDF_HKDF *ctx)
{
int sz;
const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
return SIZE_MAX;
if (md == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
return 0;
}
sz = EVP_MD_get_size(md);
if (sz < 0)
return 0;
return sz;
}
static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen,
const OSSL_PARAM params[])
{
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
const EVP_MD *md;
if (!ossl_prov_is_running() || !kdf_hkdf_set_ctx_params(ctx, params))
return 0;
md = ossl_prov_digest_md(&ctx->digest);
if (md == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
return 0;
}
if (ctx->key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
return 0;
}
if (keylen == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
switch (ctx->mode) {
case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
default:
return HKDF(libctx, md, ctx->salt, ctx->salt_len,
ctx->key, ctx->key_len, ctx->info, ctx->info_len, key, keylen);
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
return HKDF_Extract(libctx, md, ctx->salt, ctx->salt_len,
ctx->key, ctx->key_len, key, keylen);
case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info,
ctx->info_len, key, keylen);
}
}
static int hkdf_common_set_ctx_params(KDF_HKDF *ctx, const OSSL_PARAM params[])
{
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
const OSSL_PARAM *p;
int n;
if (params == NULL)
return 1;
if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) {
if (p->data_type == OSSL_PARAM_UTF8_STRING) {
if (OPENSSL_strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) {
ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
} else if (OPENSSL_strcasecmp(p->data, "EXTRACT_ONLY") == 0) {
ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
} else if (OPENSSL_strcasecmp(p->data, "EXPAND_ONLY") == 0) {
ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
} else {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
return 0;
}
} else if (OSSL_PARAM_get_int(p, &n)) {
if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
&& n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY
&& n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
return 0;
}
ctx->mode = n;
} else {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
return 0;
}
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) {
OPENSSL_clear_free(ctx->key, ctx->key_len);
ctx->key = NULL;
if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0,
&ctx->key_len))
return 0;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) {
if (p->data_size != 0 && p->data != NULL) {
OPENSSL_free(ctx->salt);
ctx->salt = NULL;
if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0,
&ctx->salt_len))
return 0;
}
}
return 1;
}
/*
* Use WPACKET to concat one or more OSSL_KDF_PARAM_INFO fields into a fixed
* out buffer of size *outlen.
* If out is NULL then outlen is used to return the required buffer size.
*/
static int setinfo_fromparams(const OSSL_PARAM *p, unsigned char *out, size_t *outlen)
{
int ret = 0;
WPACKET pkt;
if (out == NULL) {
if (!WPACKET_init_null(&pkt, 0))
return 0;
} else {
if (!WPACKET_init_static_len(&pkt, out, *outlen, 0))
return 0;
}
for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_INFO)) {
if (p->data_type != OSSL_PARAM_OCTET_STRING)
goto err;
if (p->data != NULL
&& p->data_size != 0
&& !WPACKET_memcpy(&pkt, p->data, p->data_size))
goto err;
}
if (!WPACKET_get_total_written(&pkt, outlen)
|| !WPACKET_finish(&pkt))
goto err;
ret = 1;
err:
WPACKET_cleanup(&pkt);
return ret;
}
static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
KDF_HKDF *ctx = vctx;
if (params == NULL)
return 1;
if (!hkdf_common_set_ctx_params(ctx, params))
return 0;
/* The info fields concatenate, so process them all */
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) {
size_t sz = 0;
/* calculate the total size */
if (!setinfo_fromparams(p, NULL, &sz))
return 0;
if (sz > HKDF_MAXINFO)
return 0;
OPENSSL_clear_free(ctx->info, ctx->info_len);
ctx->info = NULL;
if (sz == 0)
return 1;
/* Alloc the buffer */
ctx->info = OPENSSL_malloc(sz);
if (ctx->info == NULL)
return 0;
ctx->info_len = sz;
/* Concat one or more OSSL_KDF_PARAM_INFO fields */
if (!setinfo_fromparams(p, ctx->info, &sz))
return 0;
}
return 1;
}
static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(ossl_unused void *ctx,
ossl_unused void *provctx)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
HKDF_COMMON_SETTABLES,
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
OSSL_PARAM_END
};
return known_settable_ctx_params;
}
static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
size_t sz = kdf_hkdf_size(ctx);
if (sz == 0)
return 0;
return OSSL_PARAM_set_size_t(p, sz);
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_INFO)) != NULL) {
if (ctx->info == NULL || ctx->info_len == 0) {
p->return_size = 0;
return 1;
}
return OSSL_PARAM_set_octet_string(p, ctx->info, ctx->info_len);
}
return -2;
}
static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx,
ossl_unused void *provctx)
{
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
OSSL_PARAM_END
};
return known_gettable_ctx_params;
}
const OSSL_DISPATCH ossl_kdf_hkdf_functions[] = {
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive },
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
(void(*)(void))kdf_hkdf_settable_ctx_params },
{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params },
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
(void(*)(void))kdf_hkdf_gettable_ctx_params },
{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
{ 0, NULL }
};
/*
* Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
* Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and
* "Cryptographic Extraction and Key Derivation: The HKDF Scheme"
* Section 4.2 (https://eprint.iacr.org/2010/264.pdf).
*
* From the paper:
* The scheme HKDF is specified as:
* HKDF(XTS, SKM, CTXinfo, L) = K(1) | K(2) | ... | K(t)
*
* where:
* SKM is source key material
* XTS is extractor salt (which may be null or constant)
* CTXinfo is context information (may be null)
* L is the number of key bits to be produced by KDF
* k is the output length in bits of the hash function used with HMAC
* t = ceil(L/k)
* the value K(t) is truncated to its first d = L mod k bits.
*
* From RFC 5869:
* 2.2. Step 1: Extract
* HKDF-Extract(salt, IKM) -> PRK
* 2.3. Step 2: Expand
* HKDF-Expand(PRK, info, L) -> OKM
*/
static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *ikm, size_t ikm_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
{
unsigned char prk[EVP_MAX_MD_SIZE];
int ret, sz;
size_t prk_len;
sz = EVP_MD_get_size(evp_md);
if (sz < 0)
return 0;
prk_len = (size_t)sz;
/* Step 1: HKDF-Extract(salt, IKM) -> PRK */
if (!HKDF_Extract(libctx, evp_md,
salt, salt_len, ikm, ikm_len, prk, prk_len))
return 0;
/* Step 2: HKDF-Expand(PRK, info, L) -> OKM */
ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
OPENSSL_cleanse(prk, sizeof(prk));
return ret;
}
/*
* Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
* Section 2.2 (https://tools.ietf.org/html/rfc5869#section-2.2).
*
* 2.2. Step 1: Extract
*
* HKDF-Extract(salt, IKM) -> PRK
*
* Options:
* Hash a hash function; HashLen denotes the length of the
* hash function output in octets
*
* Inputs:
* salt optional salt value (a non-secret random value);
* if not provided, it is set to a string of HashLen zeros.
* IKM input keying material
*
* Output:
* PRK a pseudorandom key (of HashLen octets)
*
* The output PRK is calculated as follows:
*
* PRK = HMAC-Hash(salt, IKM)
*/
static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *ikm, size_t ikm_len,
unsigned char *prk, size_t prk_len)
{
int sz = EVP_MD_get_size(evp_md);
if (sz < 0)
return 0;
if (prk_len != (size_t)sz) {
ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE);
return 0;
}
/* calc: PRK = HMAC-Hash(salt, IKM) */
return
EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt,
salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL)
!= NULL;
}
/*
* Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
* Section 2.3 (https://tools.ietf.org/html/rfc5869#section-2.3).
*
* 2.3. Step 2: Expand
*
* HKDF-Expand(PRK, info, L) -> OKM
*
* Options:
* Hash a hash function; HashLen denotes the length of the
* hash function output in octets
*
* Inputs:
* PRK a pseudorandom key of at least HashLen octets
* (usually, the output from the extract step)
* info optional context and application specific information
* (can be a zero-length string)
* L length of output keying material in octets
* (<= 255*HashLen)
*
* Output:
* OKM output keying material (of L octets)
*
* The output OKM is calculated as follows:
*
* N = ceil(L/HashLen)
* T = T(1) | T(2) | T(3) | ... | T(N)
* OKM = first L octets of T
*
* where:
* T(0) = empty string (zero length)
* T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
* T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
* T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
* ...
*
* (where the constant concatenated to the end of each T(n) is a
* single octet.)
*/
static int 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;
int ret = 0, sz;
unsigned int i;
unsigned char prev[EVP_MAX_MD_SIZE];
size_t done_len = 0, dig_len, n;
sz = EVP_MD_get_size(evp_md);
if (sz <= 0)
return 0;
dig_len = (size_t)sz;
/* calc: N = ceil(L/HashLen) */
n = okm_len / dig_len;
if (okm_len % dig_len)
n++;
if (n > 255 || okm == NULL)
return 0;
if ((hmac = HMAC_CTX_new()) == NULL)
return 0;
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;
/* calc: T(i) = HMAC-Hash(PRK, T(i - 1) | info | 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 = (dig_len > okm_len - done_len) ?
okm_len - done_len :
dig_len;
memcpy(okm + done_len, prev, copy_len);
done_len += copy_len;
}
ret = 1;
err:
OPENSSL_cleanse(prev, sizeof(prev));
HMAC_CTX_free(hmac);
return ret;
}
/*
* TLS uses slight variations of the above and for FIPS validation purposes,
* they need to be present here.
* Refer to RFC 8446 section 7 for specific details.
*/
/*
* 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 and 0 on failure.
*/
static int prov_tls13_hkdf_expand(const EVP_MD *md,
const unsigned char *key, size_t keylen,
const unsigned char *prefix, size_t prefixlen,
const unsigned char *label, size_t labellen,
const unsigned char *data, size_t datalen,
unsigned char *out, size_t outlen)
{
size_t hkdflabellen;
unsigned char hkdflabel[HKDF_MAXBUF];
WPACKET pkt;
/*
* 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. We've got the maximum the KDF can handle
* which should always be sufficient.
*/
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, prefix, prefixlen)
|| !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)) {
WPACKET_cleanup(&pkt);
return 0;
}
return HKDF_Expand(md, key, keylen, hkdflabel, hkdflabellen,
out, outlen);
}
static int prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX *libctx,
const EVP_MD *md,
const unsigned char *prevsecret,
size_t prevsecretlen,
const unsigned char *insecret,
size_t insecretlen,
const unsigned char *prefix,
size_t prefixlen,
const unsigned char *label,
size_t labellen,
unsigned char *out, size_t outlen)
{
size_t mdlen;
int ret;
unsigned char preextractsec[EVP_MAX_MD_SIZE];
/* Always filled with zeros */
static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
ret = EVP_MD_get_size(md);
/* Ensure cast to size_t is safe */
if (ret <= 0)
return 0;
mdlen = (size_t)ret;
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) {
EVP_MD_CTX_free(mctx);
return 0;
}
EVP_MD_CTX_free(mctx);
/* Generate the pre-extract secret */
- if (!prov_tls13_hkdf_expand(md, prevsecret, mdlen,
+ if (!prov_tls13_hkdf_expand(md, prevsecret, prevsecretlen,
prefix, prefixlen, label, labellen,
hash, mdlen, preextractsec, mdlen))
return 0;
prevsecret = preextractsec;
prevsecretlen = mdlen;
}
ret = HKDF_Extract(libctx, md, prevsecret, prevsecretlen,
insecret, insecretlen, out, outlen);
if (prevsecret == preextractsec)
OPENSSL_cleanse(preextractsec, mdlen);
return ret;
}
static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen,
const OSSL_PARAM params[])
{
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
const EVP_MD *md;
if (!ossl_prov_is_running() || !kdf_tls1_3_set_ctx_params(ctx, params))
return 0;
md = ossl_prov_digest_md(&ctx->digest);
if (md == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
return 0;
}
switch (ctx->mode) {
default:
return 0;
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
return prov_tls13_hkdf_generate_secret(PROV_LIBCTX_OF(ctx->provctx),
md,
ctx->salt, ctx->salt_len,
ctx->key, ctx->key_len,
ctx->prefix, ctx->prefix_len,
ctx->label, ctx->label_len,
key, keylen);
case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
return prov_tls13_hkdf_expand(md, ctx->key, ctx->key_len,
ctx->prefix, ctx->prefix_len,
ctx->label, ctx->label_len,
ctx->data, ctx->data_len,
key, keylen);
}
}
static int kdf_tls1_3_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
KDF_HKDF *ctx = vctx;
if (params == NULL)
return 1;
if (!hkdf_common_set_ctx_params(ctx, params))
return 0;
if (ctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
return 0;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PREFIX)) != NULL) {
OPENSSL_free(ctx->prefix);
ctx->prefix = NULL;
if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->prefix, 0,
&ctx->prefix_len))
return 0;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_LABEL)) != NULL) {
OPENSSL_free(ctx->label);
ctx->label = NULL;
if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->label, 0,
&ctx->label_len))
return 0;
}
OPENSSL_clear_free(ctx->data, ctx->data_len);
ctx->data = NULL;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DATA)) != NULL
&& !OSSL_PARAM_get_octet_string(p, (void **)&ctx->data, 0,
&ctx->data_len))
return 0;
return 1;
}
static const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx,
ossl_unused void *provctx)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
HKDF_COMMON_SETTABLES,
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PREFIX, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_LABEL, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_DATA, NULL, 0),
OSSL_PARAM_END
};
return known_settable_ctx_params;
}
const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = {
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_3_derive },
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
(void(*)(void))kdf_tls1_3_settable_ctx_params },
{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_tls1_3_set_ctx_params },
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
(void(*)(void))kdf_hkdf_gettable_ctx_params },
{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
{ 0, NULL }
};
diff --git a/crypto/openssl/providers/implementations/kdfs/scrypt.c b/crypto/openssl/providers/implementations/kdfs/scrypt.c
index a7072f785f08..6fa4192600fd 100644
--- a/crypto/openssl/providers/implementations/kdfs/scrypt.c
+++ b/crypto/openssl/providers/implementations/kdfs/scrypt.c
@@ -1,517 +1,518 @@
/*
- * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <stdarg.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/err.h>
#include <openssl/core_names.h>
#include <openssl/proverr.h>
#include "crypto/evp.h"
#include "internal/numbers.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "prov/providercommon.h"
#include "prov/implementations.h"
#ifndef OPENSSL_NO_SCRYPT
static OSSL_FUNC_kdf_newctx_fn kdf_scrypt_new;
static OSSL_FUNC_kdf_freectx_fn kdf_scrypt_free;
static OSSL_FUNC_kdf_reset_fn kdf_scrypt_reset;
static OSSL_FUNC_kdf_derive_fn kdf_scrypt_derive;
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_scrypt_settable_ctx_params;
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_scrypt_set_ctx_params;
static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_scrypt_gettable_ctx_params;
static OSSL_FUNC_kdf_get_ctx_params_fn kdf_scrypt_get_ctx_params;
static int scrypt_alg(const char *pass, size_t passlen,
const unsigned char *salt, size_t saltlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen, EVP_MD *sha256,
OSSL_LIB_CTX *libctx, const char *propq);
typedef struct {
OSSL_LIB_CTX *libctx;
char *propq;
unsigned char *pass;
size_t pass_len;
unsigned char *salt;
size_t salt_len;
uint64_t N;
uint64_t r, p;
uint64_t maxmem_bytes;
EVP_MD *sha256;
} KDF_SCRYPT;
static void kdf_scrypt_init(KDF_SCRYPT *ctx);
static void *kdf_scrypt_new(void *provctx)
{
KDF_SCRYPT *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
ctx->libctx = PROV_LIBCTX_OF(provctx);
kdf_scrypt_init(ctx);
return ctx;
}
static void kdf_scrypt_free(void *vctx)
{
KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
if (ctx != NULL) {
OPENSSL_free(ctx->propq);
EVP_MD_free(ctx->sha256);
kdf_scrypt_reset(ctx);
OPENSSL_free(ctx);
}
}
static void kdf_scrypt_reset(void *vctx)
{
KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
OPENSSL_free(ctx->salt);
+ ctx->salt = NULL;
OPENSSL_clear_free(ctx->pass, ctx->pass_len);
+ ctx->pass = NULL;
kdf_scrypt_init(ctx);
}
static void kdf_scrypt_init(KDF_SCRYPT *ctx)
{
/* Default values are the most conservative recommendation given in the
* original paper of C. Percival. Derivation uses roughly 1 GiB of memory
* for this parameter choice (approx. 128 * r * N * p bytes).
*/
ctx->N = 1 << 20;
ctx->r = 8;
ctx->p = 1;
ctx->maxmem_bytes = 1025 * 1024 * 1024;
}
static int scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
const OSSL_PARAM *p)
{
OPENSSL_clear_free(*buffer, *buflen);
*buffer = NULL;
*buflen = 0;
if (p->data_size == 0) {
if ((*buffer = OPENSSL_malloc(1)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
} else if (p->data != NULL) {
if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
return 0;
}
return 1;
}
static int set_digest(KDF_SCRYPT *ctx)
{
EVP_MD_free(ctx->sha256);
ctx->sha256 = EVP_MD_fetch(ctx->libctx, "sha256", ctx->propq);
if (ctx->sha256 == NULL) {
- OPENSSL_free(ctx);
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA256);
return 0;
}
return 1;
}
static int set_property_query(KDF_SCRYPT *ctx, const char *propq)
{
OPENSSL_free(ctx->propq);
ctx->propq = NULL;
if (propq != NULL) {
ctx->propq = OPENSSL_strdup(propq);
if (ctx->propq == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
}
return 1;
}
static int kdf_scrypt_derive(void *vctx, unsigned char *key, size_t keylen,
const OSSL_PARAM params[])
{
KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
if (!ossl_prov_is_running() || !kdf_scrypt_set_ctx_params(ctx, params))
return 0;
if (ctx->pass == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
return 0;
}
if (ctx->salt == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
return 0;
}
if (ctx->sha256 == NULL && !set_digest(ctx))
return 0;
return scrypt_alg((char *)ctx->pass, ctx->pass_len, ctx->salt,
ctx->salt_len, ctx->N, ctx->r, ctx->p,
ctx->maxmem_bytes, key, keylen, ctx->sha256,
ctx->libctx, ctx->propq);
}
static int is_power_of_two(uint64_t value)
{
return (value != 0) && ((value & (value - 1)) == 0);
}
static int kdf_scrypt_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
KDF_SCRYPT *ctx = vctx;
uint64_t u64_value;
if (params == NULL)
return 1;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
if (!scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p))
return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
if (!scrypt_set_membuf(&ctx->salt, &ctx->salt_len, p))
return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_N))
!= NULL) {
if (!OSSL_PARAM_get_uint64(p, &u64_value)
|| u64_value <= 1
|| !is_power_of_two(u64_value))
return 0;
ctx->N = u64_value;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_R))
!= NULL) {
if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
return 0;
ctx->r = u64_value;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_P))
!= NULL) {
if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
return 0;
ctx->p = u64_value;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_MAXMEM))
!= NULL) {
if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
return 0;
ctx->maxmem_bytes = u64_value;
}
p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING
|| !set_property_query(ctx, p->data)
|| !set_digest(ctx))
return 0;
}
return 1;
}
static const OSSL_PARAM *kdf_scrypt_settable_ctx_params(ossl_unused void *ctx,
ossl_unused void *p_ctx)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_N, NULL),
OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_R, NULL),
OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_P, NULL),
OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, NULL),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_END
};
return known_settable_ctx_params;
}
static int kdf_scrypt_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
return OSSL_PARAM_set_size_t(p, SIZE_MAX);
return -2;
}
static const OSSL_PARAM *kdf_scrypt_gettable_ctx_params(ossl_unused void *ctx,
ossl_unused void *p_ctx)
{
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
OSSL_PARAM_END
};
return known_gettable_ctx_params;
}
const OSSL_DISPATCH ossl_kdf_scrypt_functions[] = {
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_scrypt_new },
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_scrypt_free },
{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_scrypt_reset },
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_scrypt_derive },
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
(void(*)(void))kdf_scrypt_settable_ctx_params },
{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_scrypt_set_ctx_params },
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
(void(*)(void))kdf_scrypt_gettable_ctx_params },
{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_scrypt_get_ctx_params },
{ 0, NULL }
};
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
static void salsa208_word_specification(uint32_t inout[16])
{
int i;
uint32_t x[16];
memcpy(x, inout, sizeof(x));
for (i = 8; i > 0; i -= 2) {
x[4] ^= R(x[0] + x[12], 7);
x[8] ^= R(x[4] + x[0], 9);
x[12] ^= R(x[8] + x[4], 13);
x[0] ^= R(x[12] + x[8], 18);
x[9] ^= R(x[5] + x[1], 7);
x[13] ^= R(x[9] + x[5], 9);
x[1] ^= R(x[13] + x[9], 13);
x[5] ^= R(x[1] + x[13], 18);
x[14] ^= R(x[10] + x[6], 7);
x[2] ^= R(x[14] + x[10], 9);
x[6] ^= R(x[2] + x[14], 13);
x[10] ^= R(x[6] + x[2], 18);
x[3] ^= R(x[15] + x[11], 7);
x[7] ^= R(x[3] + x[15], 9);
x[11] ^= R(x[7] + x[3], 13);
x[15] ^= R(x[11] + x[7], 18);
x[1] ^= R(x[0] + x[3], 7);
x[2] ^= R(x[1] + x[0], 9);
x[3] ^= R(x[2] + x[1], 13);
x[0] ^= R(x[3] + x[2], 18);
x[6] ^= R(x[5] + x[4], 7);
x[7] ^= R(x[6] + x[5], 9);
x[4] ^= R(x[7] + x[6], 13);
x[5] ^= R(x[4] + x[7], 18);
x[11] ^= R(x[10] + x[9], 7);
x[8] ^= R(x[11] + x[10], 9);
x[9] ^= R(x[8] + x[11], 13);
x[10] ^= R(x[9] + x[8], 18);
x[12] ^= R(x[15] + x[14], 7);
x[13] ^= R(x[12] + x[15], 9);
x[14] ^= R(x[13] + x[12], 13);
x[15] ^= R(x[14] + x[13], 18);
}
for (i = 0; i < 16; ++i)
inout[i] += x[i];
OPENSSL_cleanse(x, sizeof(x));
}
static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
{
uint64_t i, j;
uint32_t X[16], *pB;
memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
pB = B;
for (i = 0; i < r * 2; i++) {
for (j = 0; j < 16; j++)
X[j] ^= *pB++;
salsa208_word_specification(X);
memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
}
OPENSSL_cleanse(X, sizeof(X));
}
static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
uint32_t *X, uint32_t *T, uint32_t *V)
{
unsigned char *pB;
uint32_t *pV;
uint64_t i, k;
/* Convert from little endian input */
for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
*pV = *pB++;
*pV |= *pB++ << 8;
*pV |= *pB++ << 16;
*pV |= (uint32_t)*pB++ << 24;
}
for (i = 1; i < N; i++, pV += 32 * r)
scryptBlockMix(pV, pV - 32 * r, r);
scryptBlockMix(X, V + (N - 1) * 32 * r, r);
for (i = 0; i < N; i++) {
uint32_t j;
j = X[16 * (2 * r - 1)] % N;
pV = V + 32 * r * j;
for (k = 0; k < 32 * r; k++)
T[k] = X[k] ^ *pV++;
scryptBlockMix(X, T, r);
}
/* Convert output to little endian */
for (i = 0, pB = B; i < 32 * r; i++) {
uint32_t xtmp = X[i];
*pB++ = xtmp & 0xff;
*pB++ = (xtmp >> 8) & 0xff;
*pB++ = (xtmp >> 16) & 0xff;
*pB++ = (xtmp >> 24) & 0xff;
}
}
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
#endif
/*
* Maximum power of two that will fit in uint64_t: this should work on
* most (all?) platforms.
*/
#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1)
/*
* Maximum value of p * r:
* p <= ((2^32-1) * hLen) / MFLen =>
* p <= ((2^32-1) * 32) / (128 * r) =>
* p * r <= (2^30-1)
*/
#define SCRYPT_PR_MAX ((1 << 30) - 1)
static int scrypt_alg(const char *pass, size_t passlen,
const unsigned char *salt, size_t saltlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen, EVP_MD *sha256,
OSSL_LIB_CTX *libctx, const char *propq)
{
int rv = 0;
unsigned char *B;
uint32_t *X, *V, *T;
uint64_t i, Blen, Vlen;
/* Sanity check parameters */
/* initial check, r,p must be non zero, N >= 2 and a power of 2 */
if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
return 0;
/* Check p * r < SCRYPT_PR_MAX avoiding overflow */
if (p > SCRYPT_PR_MAX / r) {
ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/*
* Need to check N: if 2^(128 * r / 8) overflows limit this is
* automatically satisfied since N <= UINT64_MAX.
*/
if (16 * r <= LOG2_UINT64_MAX) {
if (N >= (((uint64_t)1) << (16 * r))) {
ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
}
/* Memory checks: check total allocated buffer size fits in uint64_t */
/*
* B size in section 5 step 1.S
* Note: we know p * 128 * r < UINT64_MAX because we already checked
* p * r < SCRYPT_PR_MAX
*/
Blen = p * 128 * r;
/*
* Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
* have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
*/
if (Blen > INT_MAX) {
ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/*
* Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
* This is combined size V, X and T (section 4)
*/
i = UINT64_MAX / (32 * sizeof(uint32_t));
if (N + 2 > i / r) {
ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
/* check total allocated size fits in uint64_t */
if (Blen > UINT64_MAX - Vlen) {
ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/* Check that the maximum memory doesn't exceed a size_t limits */
if (maxmem > SIZE_MAX)
maxmem = SIZE_MAX;
if (Blen + Vlen > maxmem) {
ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/* If no key return to indicate parameters are OK */
if (key == NULL)
return 1;
B = OPENSSL_malloc((size_t)(Blen + Vlen));
if (B == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
X = (uint32_t *)(B + Blen);
T = X + 32 * r;
V = T + 32 * r;
if (ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, salt, saltlen, 1, sha256,
(int)Blen, B, libctx, propq) == 0)
goto err;
for (i = 0; i < p; i++)
scryptROMix(B + 128 * r * i, r, N, X, T, V);
if (ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, B, (int)Blen, 1, sha256,
keylen, key, libctx, propq) == 0)
goto err;
rv = 1;
err:
if (rv == 0)
ERR_raise(ERR_LIB_EVP, EVP_R_PBKDF2_ERROR);
OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
return rv;
}
#endif
diff --git a/crypto/openssl/providers/implementations/kem/rsa_kem.c b/crypto/openssl/providers/implementations/kem/rsa_kem.c
index 882cf161258a..94c5bceea597 100644
--- a/crypto/openssl/providers/implementations/kem/rsa_kem.c
+++ b/crypto/openssl/providers/implementations/kem/rsa_kem.c
@@ -1,364 +1,410 @@
/*
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* RSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "internal/nelem.h"
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/rsa.h>
#include <openssl/params.h>
#include <openssl/err.h>
#include "crypto/rsa.h"
#include <openssl/proverr.h>
#include "prov/provider_ctx.h"
#include "prov/implementations.h"
#include "prov/securitycheck.h"
static OSSL_FUNC_kem_newctx_fn rsakem_newctx;
static OSSL_FUNC_kem_encapsulate_init_fn rsakem_encapsulate_init;
static OSSL_FUNC_kem_encapsulate_fn rsakem_generate;
static OSSL_FUNC_kem_decapsulate_init_fn rsakem_decapsulate_init;
static OSSL_FUNC_kem_decapsulate_fn rsakem_recover;
static OSSL_FUNC_kem_freectx_fn rsakem_freectx;
static OSSL_FUNC_kem_dupctx_fn rsakem_dupctx;
static OSSL_FUNC_kem_get_ctx_params_fn rsakem_get_ctx_params;
static OSSL_FUNC_kem_gettable_ctx_params_fn rsakem_gettable_ctx_params;
static OSSL_FUNC_kem_set_ctx_params_fn rsakem_set_ctx_params;
static OSSL_FUNC_kem_settable_ctx_params_fn rsakem_settable_ctx_params;
/*
* Only the KEM for RSASVE as defined in SP800-56b r2 is implemented
* currently.
*/
#define KEM_OP_UNDEFINED -1
#define KEM_OP_RSASVE 0
/*
* What's passed as an actual key is defined by the KEYMGMT interface.
* We happen to know that our KEYMGMT simply passes RSA structures, so
* we use that here too.
*/
typedef struct {
OSSL_LIB_CTX *libctx;
RSA *rsa;
int op;
} PROV_RSA_CTX;
static const OSSL_ITEM rsakem_opname_id_map[] = {
{ KEM_OP_RSASVE, OSSL_KEM_PARAM_OPERATION_RSASVE },
};
static int name2id(const char *name, const OSSL_ITEM *map, size_t sz)
{
size_t i;
if (name == NULL)
return -1;
for (i = 0; i < sz; ++i) {
if (OPENSSL_strcasecmp(map[i].ptr, name) == 0)
return map[i].id;
}
return -1;
}
static int rsakem_opname2id(const char *name)
{
return name2id(name, rsakem_opname_id_map, OSSL_NELEM(rsakem_opname_id_map));
}
static void *rsakem_newctx(void *provctx)
{
PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX));
if (prsactx == NULL)
return NULL;
prsactx->libctx = PROV_LIBCTX_OF(provctx);
prsactx->op = KEM_OP_UNDEFINED;
return prsactx;
}
static void rsakem_freectx(void *vprsactx)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
RSA_free(prsactx->rsa);
OPENSSL_free(prsactx);
}
static void *rsakem_dupctx(void *vprsactx)
{
PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
PROV_RSA_CTX *dstctx;
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
if (dstctx == NULL)
return NULL;
*dstctx = *srcctx;
if (dstctx->rsa != NULL && !RSA_up_ref(dstctx->rsa)) {
OPENSSL_free(dstctx);
return NULL;
}
return dstctx;
}
static int rsakem_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[], int operation)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx == NULL || vrsa == NULL)
return 0;
if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation))
return 0;
if (!RSA_up_ref(vrsa))
return 0;
RSA_free(prsactx->rsa);
prsactx->rsa = vrsa;
return rsakem_set_ctx_params(prsactx, params);
}
static int rsakem_encapsulate_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[])
{
return rsakem_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCAPSULATE);
}
static int rsakem_decapsulate_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[])
{
return rsakem_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECAPSULATE);
}
static int rsakem_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
{
PROV_RSA_CTX *ctx = (PROV_RSA_CTX *)vprsactx;
return ctx != NULL;
}
static const OSSL_PARAM known_gettable_rsakem_ctx_params[] = {
OSSL_PARAM_END
};
static const OSSL_PARAM *rsakem_gettable_ctx_params(ossl_unused void *vprsactx,
ossl_unused void *provctx)
{
return known_gettable_rsakem_ctx_params;
}
static int rsakem_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
const OSSL_PARAM *p;
int op;
if (prsactx == NULL)
return 0;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_KEM_PARAM_OPERATION);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
op = rsakem_opname2id(p->data);
if (op < 0)
return 0;
prsactx->op = op;
}
return 1;
}
static const OSSL_PARAM known_settable_rsakem_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_KEM_PARAM_OPERATION, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *rsakem_settable_ctx_params(ossl_unused void *vprsactx,
ossl_unused void *provctx)
{
return known_settable_rsakem_ctx_params;
}
/*
* NIST.SP.800-56Br2
* 7.2.1.2 RSASVE Generate Operation (RSASVE.GENERATE).
*
* Generate a random in the range 1 < z < (n – 1)
*/
static int rsasve_gen_rand_bytes(RSA *rsa_pub,
unsigned char *out, int outlen)
{
int ret = 0;
BN_CTX *bnctx;
BIGNUM *z, *nminus3;
bnctx = BN_CTX_secure_new_ex(ossl_rsa_get0_libctx(rsa_pub));
if (bnctx == NULL)
return 0;
/*
* Generate a random in the range 1 < z < (n – 1).
* Since BN_priv_rand_range_ex() returns a value in range 0 <= r < max
* We can achieve this by adding 2.. but then we need to subtract 3 from
* the upper bound i.e: 2 + (0 <= r < (n - 3))
*/
BN_CTX_start(bnctx);
nminus3 = BN_CTX_get(bnctx);
z = BN_CTX_get(bnctx);
ret = (z != NULL
&& (BN_copy(nminus3, RSA_get0_n(rsa_pub)) != NULL)
&& BN_sub_word(nminus3, 3)
&& BN_priv_rand_range_ex(z, nminus3, 0, bnctx)
&& BN_add_word(z, 2)
&& (BN_bn2binpad(z, out, outlen) == outlen));
BN_CTX_end(bnctx);
BN_CTX_free(bnctx);
return ret;
}
/*
* NIST.SP.800-56Br2
* 7.2.1.2 RSASVE Generate Operation (RSASVE.GENERATE).
*/
static int rsasve_generate(PROV_RSA_CTX *prsactx,
unsigned char *out, size_t *outlen,
unsigned char *secret, size_t *secretlen)
{
int ret;
size_t nlen;
/* Step (1): nlen = Ceil(len(n)/8) */
nlen = RSA_size(prsactx->rsa);
if (out == NULL) {
if (nlen == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
if (outlen == NULL && secretlen == NULL)
return 0;
if (outlen != NULL)
*outlen = nlen;
if (secretlen != NULL)
*secretlen = nlen;
return 1;
}
+
+ /*
+ * If outlen is specified, then it must report the length
+ * of the out buffer on input so that we can confirm
+ * its size is sufficent for encapsulation
+ */
+ if (outlen != NULL && *outlen < nlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH);
+ return 0;
+ }
+
/*
* Step (2): Generate a random byte string z of nlen bytes where
* 1 < z < n - 1
*/
if (!rsasve_gen_rand_bytes(prsactx->rsa, secret, nlen))
return 0;
/* Step(3): out = RSAEP((n,e), z) */
ret = RSA_public_encrypt(nlen, secret, out, prsactx->rsa, RSA_NO_PADDING);
if (ret) {
ret = 1;
if (outlen != NULL)
*outlen = nlen;
if (secretlen != NULL)
*secretlen = nlen;
} else {
OPENSSL_cleanse(secret, nlen);
}
return ret;
}
-/*
- * NIST.SP.800-56Br2
+/**
+ * rsasve_recover - Recovers a secret value from ciphertext using an RSA
+ * private key. Once, recovered, the secret value is considered to be a
+ * shared secret. Algorithm is preformed as per
+ * NIST SP 800-56B Rev 2
* 7.2.1.3 RSASVE Recovery Operation (RSASVE.RECOVER).
+ *
+ * This function performs RSA decryption using the private key from the
+ * provided RSA context (`prsactx`). It takes the input ciphertext, decrypts
+ * it, and writes the decrypted message to the output buffer.
+ *
+ * @prsactx: The RSA context containing the private key.
+ * @out: The output buffer to store the decrypted message.
+ * @outlen: On input, the size of the output buffer. On successful
+ * completion, the actual length of the decrypted message.
+ * @in: The input buffer containing the ciphertext to be decrypted.
+ * @inlen: The length of the input ciphertext in bytes.
+ *
+ * Returns 1 on success, or 0 on error. In case of error, appropriate
+ * error messages are raised using the ERR_raise function.
*/
static int rsasve_recover(PROV_RSA_CTX *prsactx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen)
{
size_t nlen;
+ int ret;
/* Step (1): get the byte length of n */
nlen = RSA_size(prsactx->rsa);
if (out == NULL) {
if (nlen == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
*outlen = nlen;
return 1;
}
- /* Step (2): check the input ciphertext 'inlen' matches the nlen */
+ /*
+ * Step (2): check the input ciphertext 'inlen' matches the nlen
+ * and that outlen is at least nlen bytes
+ */
if (inlen != nlen) {
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
return 0;
}
+
+ /*
+ * If outlen is specified, then it must report the length
+ * of the out buffer, so that we can confirm that it is of
+ * sufficient size to hold the output of decapsulation
+ */
+ if (outlen != NULL && *outlen < nlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH);
+ return 0;
+ }
+
/* Step (3): out = RSADP((n,d), in) */
- return (RSA_private_decrypt(inlen, in, out, prsactx->rsa, RSA_NO_PADDING) > 0);
+ ret = RSA_private_decrypt(inlen, in, out, prsactx->rsa, RSA_NO_PADDING);
+ if (ret > 0 && outlen != NULL)
+ *outlen = ret;
+ return ret > 0;
}
static int rsakem_generate(void *vprsactx, unsigned char *out, size_t *outlen,
unsigned char *secret, size_t *secretlen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
switch (prsactx->op) {
case KEM_OP_RSASVE:
return rsasve_generate(prsactx, out, outlen, secret, secretlen);
default:
return -2;
}
}
static int rsakem_recover(void *vprsactx, unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
switch (prsactx->op) {
case KEM_OP_RSASVE:
return rsasve_recover(prsactx, out, outlen, in, inlen);
default:
return -2;
}
}
const OSSL_DISPATCH ossl_rsa_asym_kem_functions[] = {
{ OSSL_FUNC_KEM_NEWCTX, (void (*)(void))rsakem_newctx },
{ OSSL_FUNC_KEM_ENCAPSULATE_INIT,
(void (*)(void))rsakem_encapsulate_init },
{ OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))rsakem_generate },
{ OSSL_FUNC_KEM_DECAPSULATE_INIT,
(void (*)(void))rsakem_decapsulate_init },
{ OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))rsakem_recover },
{ OSSL_FUNC_KEM_FREECTX, (void (*)(void))rsakem_freectx },
{ OSSL_FUNC_KEM_DUPCTX, (void (*)(void))rsakem_dupctx },
{ OSSL_FUNC_KEM_GET_CTX_PARAMS,
(void (*)(void))rsakem_get_ctx_params },
{ OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS,
(void (*)(void))rsakem_gettable_ctx_params },
{ OSSL_FUNC_KEM_SET_CTX_PARAMS,
(void (*)(void))rsakem_set_ctx_params },
{ OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS,
(void (*)(void))rsakem_settable_ctx_params },
{ 0, NULL }
};
diff --git a/crypto/openssl/providers/implementations/keymgmt/dsa_kmgmt.c b/crypto/openssl/providers/implementations/keymgmt/dsa_kmgmt.c
index 2f5742cfcc07..e3c3fd6916ed 100644
--- a/crypto/openssl/providers/implementations/keymgmt/dsa_kmgmt.c
+++ b/crypto/openssl/providers/implementations/keymgmt/dsa_kmgmt.c
@@ -1,680 +1,680 @@
/*
* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* DSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "crypto/dsa.h"
#include "internal/sizes.h"
#include "internal/nelem.h"
#include "internal/param_build_set.h"
static OSSL_FUNC_keymgmt_new_fn dsa_newdata;
static OSSL_FUNC_keymgmt_free_fn dsa_freedata;
static OSSL_FUNC_keymgmt_gen_init_fn dsa_gen_init;
static OSSL_FUNC_keymgmt_gen_set_template_fn dsa_gen_set_template;
static OSSL_FUNC_keymgmt_gen_set_params_fn dsa_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn dsa_gen_settable_params;
static OSSL_FUNC_keymgmt_gen_fn dsa_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn dsa_gen_cleanup;
static OSSL_FUNC_keymgmt_load_fn dsa_load;
static OSSL_FUNC_keymgmt_get_params_fn dsa_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn dsa_gettable_params;
static OSSL_FUNC_keymgmt_has_fn dsa_has;
static OSSL_FUNC_keymgmt_match_fn dsa_match;
static OSSL_FUNC_keymgmt_validate_fn dsa_validate;
static OSSL_FUNC_keymgmt_import_fn dsa_import;
static OSSL_FUNC_keymgmt_import_types_fn dsa_import_types;
static OSSL_FUNC_keymgmt_export_fn dsa_export;
static OSSL_FUNC_keymgmt_export_types_fn dsa_export_types;
static OSSL_FUNC_keymgmt_dup_fn dsa_dup;
#define DSA_DEFAULT_MD "SHA256"
#define DSA_POSSIBLE_SELECTIONS \
(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
struct dsa_gen_ctx {
OSSL_LIB_CTX *libctx;
FFC_PARAMS *ffc_params;
int selection;
/* All these parameters are used for parameter generation only */
size_t pbits;
size_t qbits;
unsigned char *seed; /* optional FIPS186-4 param for testing */
size_t seedlen;
int gindex; /* optional FIPS186-4 generator index (ignored if -1) */
int gen_type; /* DSA_PARAMGEN_TYPE_FIPS_186_2 or DSA_PARAMGEN_TYPE_FIPS_186_4 */
int pcounter;
int hindex;
char *mdname;
char *mdprops;
OSSL_CALLBACK *cb;
void *cbarg;
};
typedef struct dh_name2id_st{
const char *name;
int id;
} DSA_GENTYPE_NAME2ID;
static const DSA_GENTYPE_NAME2ID dsatype2id[]=
{
#ifdef FIPS_MODULE
{ "default", DSA_PARAMGEN_TYPE_FIPS_186_4 },
#else
{ "default", DSA_PARAMGEN_TYPE_FIPS_DEFAULT },
#endif
{ "fips186_4", DSA_PARAMGEN_TYPE_FIPS_186_4 },
{ "fips186_2", DSA_PARAMGEN_TYPE_FIPS_186_2 },
};
static int dsa_gen_type_name2id(const char *name)
{
size_t i;
for (i = 0; i < OSSL_NELEM(dsatype2id); ++i) {
if (OPENSSL_strcasecmp(dsatype2id[i].name, name) == 0)
return dsatype2id[i].id;
}
return -1;
}
static int dsa_key_todata(DSA *dsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],
int include_private)
{
const BIGNUM *priv = NULL, *pub = NULL;
if (dsa == NULL)
return 0;
DSA_get0_key(dsa, &pub, &priv);
if (include_private
&& priv != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv))
return 0;
if (pub != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub))
return 0;
return 1;
}
static void *dsa_newdata(void *provctx)
{
if (!ossl_prov_is_running())
return NULL;
return ossl_dsa_new(PROV_LIBCTX_OF(provctx));
}
static void dsa_freedata(void *keydata)
{
DSA_free(keydata);
}
static int dsa_has(const void *keydata, int selection)
{
const DSA *dsa = keydata;
int ok = 1;
if (!ossl_prov_is_running() || dsa == NULL)
return 0;
if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
return 1; /* the selection is not missing */
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && (DSA_get0_pub_key(dsa) != NULL);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && (DSA_get0_priv_key(dsa) != NULL);
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && (DSA_get0_p(dsa) != NULL && DSA_get0_g(dsa) != NULL);
return ok;
}
static int dsa_match(const void *keydata1, const void *keydata2, int selection)
{
const DSA *dsa1 = keydata1;
const DSA *dsa2 = keydata2;
int ok = 1;
if (!ossl_prov_is_running())
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int key_checked = 0;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
const BIGNUM *pa = DSA_get0_pub_key(dsa1);
const BIGNUM *pb = DSA_get0_pub_key(dsa2);
if (pa != NULL && pb != NULL) {
ok = ok && BN_cmp(pa, pb) == 0;
key_checked = 1;
}
}
if (!key_checked
&& (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
const BIGNUM *pa = DSA_get0_priv_key(dsa1);
const BIGNUM *pb = DSA_get0_priv_key(dsa2);
if (pa != NULL && pb != NULL) {
ok = ok && BN_cmp(pa, pb) == 0;
key_checked = 1;
}
}
ok = ok && key_checked;
}
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
FFC_PARAMS *dsaparams1 = ossl_dsa_get0_params((DSA *)dsa1);
FFC_PARAMS *dsaparams2 = ossl_dsa_get0_params((DSA *)dsa2);
ok = ok && ossl_ffc_params_cmp(dsaparams1, dsaparams2, 1);
}
return ok;
}
static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
{
DSA *dsa = keydata;
int ok = 1;
if (!ossl_prov_is_running() || dsa == NULL)
return 0;
if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
return 0;
/* a key without parameters is meaningless */
ok = ok && ossl_dsa_ffc_params_fromdata(dsa, params);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private =
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && ossl_dsa_key_fromdata(dsa, params, include_private);
}
return ok;
}
static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
void *cbarg)
{
DSA *dsa = keydata;
OSSL_PARAM_BLD *tmpl;
OSSL_PARAM *params = NULL;
int ok = 1;
if (!ossl_prov_is_running() || dsa == NULL)
return 0;
if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
return 0;
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
ok = ok && ossl_ffc_params_todata(ossl_dsa_get0_params(dsa), tmpl, NULL);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private =
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && dsa_key_todata(dsa, tmpl, NULL, include_private);
}
if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
ok = 0;
goto err;
}
ok = param_cb(params, cbarg);
OSSL_PARAM_free(params);
err:
OSSL_PARAM_BLD_free(tmpl);
return ok;
}
/* IMEXPORT = IMPORT + EXPORT */
# define DSA_IMEXPORTABLE_PARAMETERS \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0)
# define DSA_IMEXPORTABLE_PUBLIC_KEY \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
# define DSA_IMEXPORTABLE_PRIVATE_KEY \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
static const OSSL_PARAM dsa_all_types[] = {
DSA_IMEXPORTABLE_PARAMETERS,
DSA_IMEXPORTABLE_PUBLIC_KEY,
DSA_IMEXPORTABLE_PRIVATE_KEY,
OSSL_PARAM_END
};
static const OSSL_PARAM dsa_parameter_types[] = {
DSA_IMEXPORTABLE_PARAMETERS,
OSSL_PARAM_END
};
static const OSSL_PARAM dsa_key_types[] = {
DSA_IMEXPORTABLE_PUBLIC_KEY,
DSA_IMEXPORTABLE_PRIVATE_KEY,
OSSL_PARAM_END
};
static const OSSL_PARAM *dsa_types[] = {
NULL, /* Index 0 = none of them */
dsa_parameter_types, /* Index 1 = parameter types */
dsa_key_types, /* Index 2 = key types */
dsa_all_types /* Index 3 = 1 + 2 */
};
static const OSSL_PARAM *dsa_imexport_types(int selection)
{
int type_select = 0;
if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
type_select += 1;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
type_select += 2;
return dsa_types[type_select];
}
static const OSSL_PARAM *dsa_import_types(int selection)
{
return dsa_imexport_types(selection);
}
static const OSSL_PARAM *dsa_export_types(int selection)
{
return dsa_imexport_types(selection);
}
static ossl_inline int dsa_get_params(void *key, OSSL_PARAM params[])
{
DSA *dsa = key;
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, DSA_bits(dsa)))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, DSA_security_bits(dsa)))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
&& !OSSL_PARAM_set_int(p, DSA_size(dsa)))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
&& !OSSL_PARAM_set_utf8_string(p, DSA_DEFAULT_MD))
return 0;
return ossl_ffc_params_todata(ossl_dsa_get0_params(dsa), NULL, params)
&& dsa_key_todata(dsa, NULL, params, 1);
}
static const OSSL_PARAM dsa_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
DSA_IMEXPORTABLE_PARAMETERS,
DSA_IMEXPORTABLE_PUBLIC_KEY,
DSA_IMEXPORTABLE_PRIVATE_KEY,
OSSL_PARAM_END
};
static const OSSL_PARAM *dsa_gettable_params(void *provctx)
{
return dsa_params;
}
static int dsa_validate_domparams(const DSA *dsa, int checktype)
{
int status = 0;
return ossl_dsa_check_params(dsa, checktype, &status);
}
static int dsa_validate_public(const DSA *dsa)
{
int status = 0;
const BIGNUM *pub_key = NULL;
DSA_get0_key(dsa, &pub_key, NULL);
if (pub_key == NULL)
return 0;
return ossl_dsa_check_pub_key(dsa, pub_key, &status);
}
static int dsa_validate_private(const DSA *dsa)
{
int status = 0;
const BIGNUM *priv_key = NULL;
DSA_get0_key(dsa, NULL, &priv_key);
if (priv_key == NULL)
return 0;
return ossl_dsa_check_priv_key(dsa, priv_key, &status);
}
static int dsa_validate(const void *keydata, int selection, int checktype)
{
const DSA *dsa = keydata;
int ok = 1;
if (!ossl_prov_is_running())
return 0;
if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
return 1; /* nothing to validate */
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && dsa_validate_domparams(dsa, checktype);
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && dsa_validate_public(dsa);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && dsa_validate_private(dsa);
/* If the whole key is selected, we do a pairwise validation */
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
== OSSL_KEYMGMT_SELECT_KEYPAIR)
ok = ok && ossl_dsa_check_pairwise(dsa);
return ok;
}
static void *dsa_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
struct dsa_gen_ctx *gctx = NULL;
if (!ossl_prov_is_running() || (selection & DSA_POSSIBLE_SELECTIONS) == 0)
return NULL;
if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
gctx->selection = selection;
gctx->libctx = libctx;
gctx->pbits = 2048;
gctx->qbits = 224;
#ifdef FIPS_MODULE
gctx->gen_type = DSA_PARAMGEN_TYPE_FIPS_186_4;
#else
gctx->gen_type = DSA_PARAMGEN_TYPE_FIPS_DEFAULT;
#endif
gctx->gindex = -1;
gctx->pcounter = -1;
gctx->hindex = 0;
}
if (!dsa_gen_set_params(gctx, params)) {
- OPENSSL_free(gctx);
+ dsa_gen_cleanup(gctx);
gctx = NULL;
}
return gctx;
}
static int dsa_gen_set_template(void *genctx, void *templ)
{
struct dsa_gen_ctx *gctx = genctx;
DSA *dsa = templ;
if (!ossl_prov_is_running() || gctx == NULL || dsa == NULL)
return 0;
gctx->ffc_params = ossl_dsa_get0_params(dsa);
return 1;
}
static int dsa_set_gen_seed(struct dsa_gen_ctx *gctx, unsigned char *seed,
size_t seedlen)
{
OPENSSL_clear_free(gctx->seed, gctx->seedlen);
gctx->seed = NULL;
gctx->seedlen = 0;
if (seed != NULL && seedlen > 0) {
gctx->seed = OPENSSL_memdup(seed, seedlen);
if (gctx->seed == NULL)
return 0;
gctx->seedlen = seedlen;
}
return 1;
}
static int dsa_gen_set_params(void *genctx, const OSSL_PARAM params[])
{
struct dsa_gen_ctx *gctx = genctx;
const OSSL_PARAM *p;
if (gctx == NULL)
return 0;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING
|| ((gctx->gen_type = dsa_gen_type_name2id(p->data)) == -1)) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
if (p != NULL
&& !OSSL_PARAM_get_int(p, &gctx->gindex))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
if (p != NULL
&& !OSSL_PARAM_get_int(p, &gctx->pcounter))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
if (p != NULL
&& !OSSL_PARAM_get_int(p, &gctx->hindex))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
if (p != NULL
&& (p->data_type != OSSL_PARAM_OCTET_STRING
|| !dsa_set_gen_seed(gctx, p->data, p->data_size)))
return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL
&& !OSSL_PARAM_get_size_t(p, &gctx->pbits))
return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL
&& !OSSL_PARAM_get_size_t(p, &gctx->qbits))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
OPENSSL_free(gctx->mdname);
gctx->mdname = OPENSSL_strdup(p->data);
if (gctx->mdname == NULL)
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
OPENSSL_free(gctx->mdprops);
gctx->mdprops = OPENSSL_strdup(p->data);
if (gctx->mdprops == NULL)
return 0;
}
return 1;
}
static const OSSL_PARAM *dsa_gen_settable_params(ossl_unused void *genctx,
ossl_unused void *provctx)
{
static OSSL_PARAM settable[] = {
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0),
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),
OSSL_PARAM_END
};
return settable;
}
static int dsa_gencb(int p, int n, BN_GENCB *cb)
{
struct dsa_gen_ctx *gctx = BN_GENCB_get_arg(cb);
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
return gctx->cb(params, gctx->cbarg);
}
static void *dsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct dsa_gen_ctx *gctx = genctx;
DSA *dsa = NULL;
BN_GENCB *gencb = NULL;
int ret = 0;
FFC_PARAMS *ffc;
if (!ossl_prov_is_running() || gctx == NULL)
return NULL;
dsa = ossl_dsa_new(gctx->libctx);
if (dsa == NULL)
return NULL;
if (gctx->gen_type == DSA_PARAMGEN_TYPE_FIPS_DEFAULT)
gctx->gen_type = (gctx->pbits >= 2048 ? DSA_PARAMGEN_TYPE_FIPS_186_4 :
DSA_PARAMGEN_TYPE_FIPS_186_2);
gctx->cb = osslcb;
gctx->cbarg = cbarg;
gencb = BN_GENCB_new();
if (gencb != NULL)
BN_GENCB_set(gencb, dsa_gencb, genctx);
ffc = ossl_dsa_get0_params(dsa);
/* Copy the template value if one was passed */
if (gctx->ffc_params != NULL
&& !ossl_ffc_params_copy(ffc, gctx->ffc_params))
goto end;
if (gctx->seed != NULL
&& !ossl_ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))
goto end;
if (gctx->gindex != -1) {
ossl_ffc_params_set_gindex(ffc, gctx->gindex);
if (gctx->pcounter != -1)
ossl_ffc_params_set_pcounter(ffc, gctx->pcounter);
} else if (gctx->hindex != 0) {
ossl_ffc_params_set_h(ffc, gctx->hindex);
}
if (gctx->mdname != NULL) {
if (!ossl_ffc_set_digest(ffc, gctx->mdname, gctx->mdprops))
goto end;
}
if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
if (ossl_dsa_generate_ffc_parameters(dsa, gctx->gen_type,
gctx->pbits, gctx->qbits,
gencb) <= 0)
goto end;
}
ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY,
gctx->gen_type == DSA_PARAMGEN_TYPE_FIPS_186_2);
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
if (ffc->p == NULL
|| ffc->q == NULL
|| ffc->g == NULL)
goto end;
if (DSA_generate_key(dsa) <= 0)
goto end;
}
ret = 1;
end:
if (ret <= 0) {
DSA_free(dsa);
dsa = NULL;
}
BN_GENCB_free(gencb);
return dsa;
}
static void dsa_gen_cleanup(void *genctx)
{
struct dsa_gen_ctx *gctx = genctx;
if (gctx == NULL)
return;
OPENSSL_free(gctx->mdname);
OPENSSL_free(gctx->mdprops);
OPENSSL_clear_free(gctx->seed, gctx->seedlen);
OPENSSL_free(gctx);
}
static void *dsa_load(const void *reference, size_t reference_sz)
{
DSA *dsa = NULL;
if (ossl_prov_is_running() && reference_sz == sizeof(dsa)) {
/* The contents of the reference is the address to our object */
dsa = *(DSA **)reference;
/* We grabbed, so we detach it */
*(DSA **)reference = NULL;
return dsa;
}
return NULL;
}
static void *dsa_dup(const void *keydata_from, int selection)
{
if (ossl_prov_is_running())
return ossl_dsa_dup(keydata_from, selection);
return NULL;
}
const OSSL_DISPATCH ossl_dsa_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dsa_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dsa_gen_init },
{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dsa_gen_set_template },
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dsa_gen_set_params },
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
(void (*)(void))dsa_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dsa_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dsa_gen_cleanup },
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dsa_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dsa_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dsa_gettable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dsa_has },
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dsa_match },
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dsa_validate },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dsa_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dsa_export_types },
{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dsa_dup },
{ 0, NULL }
};
diff --git a/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c b/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
index 987d38456fba..94e62f755c20 100644
--- a/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -1,1059 +1,1059 @@
/*
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <assert.h>
#include <string.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include <openssl/err.h>
#include <openssl/proverr.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include "internal/param_build_set.h"
#include <openssl/param_build.h>
#include "crypto/ecx.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/provider_ctx.h"
#ifdef S390X_EC_ASM
# include "s390x_arch.h"
# include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
#endif
static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
static OSSL_FUNC_keymgmt_new_fn x448_new_key;
static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
static OSSL_FUNC_keymgmt_gen_fn x448_gen;
static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
static OSSL_FUNC_keymgmt_load_fn ecx_load;
static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
static OSSL_FUNC_keymgmt_has_fn ecx_has;
static OSSL_FUNC_keymgmt_match_fn ecx_match;
static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
static OSSL_FUNC_keymgmt_validate_fn x448_validate;
static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
static OSSL_FUNC_keymgmt_import_fn ecx_import;
static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
static OSSL_FUNC_keymgmt_export_fn ecx_export;
static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
struct ecx_gen_ctx {
OSSL_LIB_CTX *libctx;
char *propq;
ECX_KEY_TYPE type;
int selection;
};
#ifdef S390X_EC_ASM
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
#endif
static void *x25519_new_key(void *provctx)
{
if (!ossl_prov_is_running())
return 0;
return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
NULL);
}
static void *x448_new_key(void *provctx)
{
if (!ossl_prov_is_running())
return 0;
return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
NULL);
}
static void *ed25519_new_key(void *provctx)
{
if (!ossl_prov_is_running())
return 0;
return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
NULL);
}
static void *ed448_new_key(void *provctx)
{
if (!ossl_prov_is_running())
return 0;
return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
NULL);
}
static int ecx_has(const void *keydata, int selection)
{
const ECX_KEY *key = keydata;
int ok = 0;
if (ossl_prov_is_running() && key != NULL) {
/*
* ECX keys always have all the parameters they need (i.e. none).
* Therefore we always return with 1, if asked about parameters.
*/
ok = 1;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && key->haspubkey;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && key->privkey != NULL;
}
return ok;
}
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
{
const ECX_KEY *key1 = keydata1;
const ECX_KEY *key2 = keydata2;
int ok = 1;
if (!ossl_prov_is_running())
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && key1->type == key2->type;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int key_checked = 0;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
size_t pal = key1->keylen;
size_t pbl = key2->keylen;
if (pa != NULL && pb != NULL) {
ok = ok
&& key1->type == key2->type
&& pal == pbl
&& CRYPTO_memcmp(pa, pb, pal) == 0;
key_checked = 1;
}
}
if (!key_checked
&& (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
const unsigned char *pa = key1->privkey;
const unsigned char *pb = key2->privkey;
size_t pal = key1->keylen;
size_t pbl = key2->keylen;
if (pa != NULL && pb != NULL) {
ok = ok
&& key1->type == key2->type
&& pal == pbl
&& CRYPTO_memcmp(pa, pb, pal) == 0;
key_checked = 1;
}
}
ok = ok && key_checked;
}
return ok;
}
static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
{
ECX_KEY *key = keydata;
int ok = 1;
int include_private;
if (!ossl_prov_is_running() || key == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return 0;
include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
return ok;
}
static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
OSSL_PARAM params[], int include_private)
{
if (key == NULL)
return 0;
if (!ossl_param_build_set_octet_string(tmpl, params,
OSSL_PKEY_PARAM_PUB_KEY,
key->pubkey, key->keylen))
return 0;
if (include_private
&& key->privkey != NULL
&& !ossl_param_build_set_octet_string(tmpl, params,
OSSL_PKEY_PARAM_PRIV_KEY,
key->privkey, key->keylen))
return 0;
return 1;
}
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
void *cbarg)
{
ECX_KEY *key = keydata;
OSSL_PARAM_BLD *tmpl;
OSSL_PARAM *params = NULL;
int ret = 0;
if (!ossl_prov_is_running() || key == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return 0;
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
if (!key_to_params(key, tmpl, NULL, include_private))
goto err;
}
params = OSSL_PARAM_BLD_to_param(tmpl);
if (params == NULL)
goto err;
ret = param_cb(params, cbarg);
OSSL_PARAM_free(params);
err:
OSSL_PARAM_BLD_free(tmpl);
return ret;
}
#define ECX_KEY_TYPES() \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
static const OSSL_PARAM ecx_key_types[] = {
ECX_KEY_TYPES(),
OSSL_PARAM_END
};
static const OSSL_PARAM *ecx_imexport_types(int selection)
{
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
return ecx_key_types;
return NULL;
}
static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
int size)
{
ECX_KEY *ecx = key;
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, bits))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, secbits))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
&& !OSSL_PARAM_set_int(p, size))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
&& (ecx->type == ECX_KEY_TYPE_X25519
|| ecx->type == ECX_KEY_TYPE_X448)) {
if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
return 0;
}
return key_to_params(ecx, NULL, params, 1);
}
static int ed_get_params(void *key, OSSL_PARAM params[])
{
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params,
OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
&& !OSSL_PARAM_set_utf8_string(p, ""))
return 0;
return 1;
}
static int x25519_get_params(void *key, OSSL_PARAM params[])
{
return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
X25519_KEYLEN);
}
static int x448_get_params(void *key, OSSL_PARAM params[])
{
return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
X448_KEYLEN);
}
static int ed25519_get_params(void *key, OSSL_PARAM params[])
{
return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
ED25519_SIGSIZE)
&& ed_get_params(key, params);
}
static int ed448_get_params(void *key, OSSL_PARAM params[])
{
return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
ED448_SIGSIZE)
&& ed_get_params(key, params);
}
static const OSSL_PARAM ecx_gettable_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
ECX_KEY_TYPES(),
OSSL_PARAM_END
};
static const OSSL_PARAM ed_gettable_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
ECX_KEY_TYPES(),
OSSL_PARAM_END
};
static const OSSL_PARAM *x25519_gettable_params(void *provctx)
{
return ecx_gettable_params;
}
static const OSSL_PARAM *x448_gettable_params(void *provctx)
{
return ecx_gettable_params;
}
static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
{
return ed_gettable_params;
}
static const OSSL_PARAM *ed448_gettable_params(void *provctx)
{
return ed_gettable_params;
}
static int set_property_query(ECX_KEY *ecxkey, const char *propq)
{
OPENSSL_free(ecxkey->propq);
ecxkey->propq = NULL;
if (propq != NULL) {
ecxkey->propq = OPENSSL_strdup(propq);
if (ecxkey->propq == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
}
return 1;
}
static int ecx_set_params(void *key, const OSSL_PARAM params[])
{
ECX_KEY *ecxkey = key;
const OSSL_PARAM *p;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
if (p != NULL) {
void *buf = ecxkey->pubkey;
if (p->data_size != ecxkey->keylen
|| !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
NULL))
return 0;
OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
ecxkey->privkey = NULL;
ecxkey->haspubkey = 1;
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING
|| !set_property_query(ecxkey, p->data))
return 0;
}
return 1;
}
static int x25519_set_params(void *key, const OSSL_PARAM params[])
{
return ecx_set_params(key, params);
}
static int x448_set_params(void *key, const OSSL_PARAM params[])
{
return ecx_set_params(key, params);
}
static int ed25519_set_params(void *key, const OSSL_PARAM params[])
{
return 1;
}
static int ed448_set_params(void *key, const OSSL_PARAM params[])
{
return 1;
}
static const OSSL_PARAM ecx_settable_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM ed_settable_params[] = {
OSSL_PARAM_END
};
static const OSSL_PARAM *x25519_settable_params(void *provctx)
{
return ecx_settable_params;
}
static const OSSL_PARAM *x448_settable_params(void *provctx)
{
return ecx_settable_params;
}
static const OSSL_PARAM *ed25519_settable_params(void *provctx)
{
return ed_settable_params;
}
static const OSSL_PARAM *ed448_settable_params(void *provctx)
{
return ed_settable_params;
}
static void *ecx_gen_init(void *provctx, int selection,
const OSSL_PARAM params[], ECX_KEY_TYPE type)
{
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
struct ecx_gen_ctx *gctx = NULL;
if (!ossl_prov_is_running())
return NULL;
if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
gctx->libctx = libctx;
gctx->type = type;
gctx->selection = selection;
}
if (!ecx_gen_set_params(gctx, params)) {
- OPENSSL_free(gctx);
+ ecx_gen_cleanup(gctx);
gctx = NULL;
}
return gctx;
}
static void *x25519_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
}
static void *x448_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
}
static void *ed25519_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519);
}
static void *ed448_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448);
}
static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
{
struct ecx_gen_ctx *gctx = genctx;
const OSSL_PARAM *p;
if (gctx == NULL)
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
if (p != NULL) {
const char *groupname = NULL;
/*
* We optionally allow setting a group name - but each algorithm only
* support one such name, so all we do is verify that it is the one we
* expected.
*/
switch (gctx->type) {
case ECX_KEY_TYPE_X25519:
groupname = "x25519";
break;
case ECX_KEY_TYPE_X448:
groupname = "x448";
break;
default:
/* We only support this for key exchange at the moment */
break;
}
if (p->data_type != OSSL_PARAM_UTF8_STRING
|| groupname == NULL
|| OPENSSL_strcasecmp(p->data, groupname) != 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
OPENSSL_free(gctx->propq);
gctx->propq = OPENSSL_strdup(p->data);
if (gctx->propq == NULL)
return 0;
}
return 1;
}
static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
ossl_unused void *provctx)
{
static OSSL_PARAM settable[] = {
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_END
};
return settable;
}
static void *ecx_gen(struct ecx_gen_ctx *gctx)
{
ECX_KEY *key;
unsigned char *privkey;
if (gctx == NULL)
return NULL;
if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
gctx->propq)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
/* If we're doing parameter generation then we just return a blank key */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return key;
if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
goto err;
switch (gctx->type) {
case ECX_KEY_TYPE_X25519:
privkey[0] &= 248;
privkey[X25519_KEYLEN - 1] &= 127;
privkey[X25519_KEYLEN - 1] |= 64;
ossl_x25519_public_from_private(key->pubkey, privkey);
break;
case ECX_KEY_TYPE_X448:
privkey[0] &= 252;
privkey[X448_KEYLEN - 1] |= 128;
ossl_x448_public_from_private(key->pubkey, privkey);
break;
case ECX_KEY_TYPE_ED25519:
if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
gctx->propq))
goto err;
break;
case ECX_KEY_TYPE_ED448:
if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
gctx->propq))
goto err;
break;
}
key->haspubkey = 1;
return key;
err:
ossl_ecx_key_free(key);
return NULL;
}
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct ecx_gen_ctx *gctx = genctx;
if (!ossl_prov_is_running())
return 0;
#ifdef S390X_EC_ASM
if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
return s390x_ecx_keygen25519(gctx);
#endif
return ecx_gen(gctx);
}
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct ecx_gen_ctx *gctx = genctx;
if (!ossl_prov_is_running())
return 0;
#ifdef S390X_EC_ASM
if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
return s390x_ecx_keygen448(gctx);
#endif
return ecx_gen(gctx);
}
static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct ecx_gen_ctx *gctx = genctx;
if (!ossl_prov_is_running())
return 0;
#ifdef S390X_EC_ASM
if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
&& OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
&& OPENSSL_s390xcap_P.kdsa[0]
& S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
return s390x_ecd_keygen25519(gctx);
#endif
return ecx_gen(gctx);
}
static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct ecx_gen_ctx *gctx = genctx;
if (!ossl_prov_is_running())
return 0;
#ifdef S390X_EC_ASM
if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
&& OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
&& OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
return s390x_ecd_keygen448(gctx);
#endif
return ecx_gen(gctx);
}
static void ecx_gen_cleanup(void *genctx)
{
struct ecx_gen_ctx *gctx = genctx;
OPENSSL_free(gctx->propq);
OPENSSL_free(gctx);
}
void *ecx_load(const void *reference, size_t reference_sz)
{
ECX_KEY *key = NULL;
if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
/* The contents of the reference is the address to our object */
key = *(ECX_KEY **)reference;
/* We grabbed, so we detach it */
*(ECX_KEY **)reference = NULL;
return key;
}
return NULL;
}
static void *ecx_dup(const void *keydata_from, int selection)
{
if (ossl_prov_is_running())
return ossl_ecx_key_dup(keydata_from, selection);
return NULL;
}
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
{
uint8_t pub[64];
switch (type) {
case ECX_KEY_TYPE_X25519:
ossl_x25519_public_from_private(pub, ecx->privkey);
break;
case ECX_KEY_TYPE_X448:
ossl_x448_public_from_private(pub, ecx->privkey);
break;
case ECX_KEY_TYPE_ED25519:
if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
ecx->propq))
return 0;
break;
case ECX_KEY_TYPE_ED448:
if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
ecx->propq))
return 0;
break;
default:
return 0;
}
return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
}
static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
{
const ECX_KEY *ecx = keydata;
int ok = keylen == ecx->keylen;
if (!ossl_prov_is_running())
return 0;
if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
return 1; /* nothing to validate */
if (!ok) {
ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
return 0;
}
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && ecx->haspubkey;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && ecx->privkey != NULL;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
ok = ok && ecx_key_pairwise_check(ecx, type);
return ok;
}
static int x25519_validate(const void *keydata, int selection, int checktype)
{
return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
}
static int x448_validate(const void *keydata, int selection, int checktype)
{
return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
}
static int ed25519_validate(const void *keydata, int selection, int checktype)
{
return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
}
static int ed448_validate(const void *keydata, int selection, int checktype)
{
return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
}
#define MAKE_KEYMGMT_FUNCTIONS(alg) \
const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
(void (*)(void))ecx_gen_settable_params }, \
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
{ 0, NULL } \
};
MAKE_KEYMGMT_FUNCTIONS(x25519)
MAKE_KEYMGMT_FUNCTIONS(x448)
MAKE_KEYMGMT_FUNCTIONS(ed25519)
MAKE_KEYMGMT_FUNCTIONS(ed448)
#ifdef S390X_EC_ASM
# include "s390x_arch.h"
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
{
static const unsigned char generator[] = {
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
gctx->propq);
unsigned char *privkey = NULL, *pubkey;
if (key == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
/* If we're doing parameter generation then we just return a blank key */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return key;
pubkey = key->pubkey;
privkey = ossl_ecx_key_allocate_privkey(key);
if (privkey == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
goto err;
privkey[0] &= 248;
privkey[31] &= 127;
privkey[31] |= 64;
if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
goto err;
key->haspubkey = 1;
return key;
err:
ossl_ecx_key_free(key);
return NULL;
}
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
{
static const unsigned char generator[] = {
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
gctx->propq);
unsigned char *privkey = NULL, *pubkey;
if (key == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
/* If we're doing parameter generation then we just return a blank key */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return key;
pubkey = key->pubkey;
privkey = ossl_ecx_key_allocate_privkey(key);
if (privkey == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
goto err;
privkey[0] &= 252;
privkey[55] |= 128;
if (s390x_x448_mul(pubkey, generator, privkey) != 1)
goto err;
key->haspubkey = 1;
return key;
err:
ossl_ecx_key_free(key);
return NULL;
}
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
{
static const unsigned char generator_x[] = {
0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
};
static const unsigned char generator_y[] = {
0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
};
unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
gctx->propq);
unsigned char *privkey = NULL, *pubkey;
unsigned int sz;
EVP_MD *sha = NULL;
int j;
if (key == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
/* If we're doing parameter generation then we just return a blank key */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return key;
pubkey = key->pubkey;
privkey = ossl_ecx_key_allocate_privkey(key);
if (privkey == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
goto err;
sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
if (sha == NULL)
goto err;
j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
EVP_MD_free(sha);
if (!j)
goto err;
buff[0] &= 248;
buff[31] &= 63;
buff[31] |= 64;
if (s390x_ed25519_mul(x_dst, pubkey,
generator_x, generator_y, buff) != 1)
goto err;
pubkey[31] |= ((x_dst[0] & 0x01) << 7);
key->haspubkey = 1;
return key;
err:
ossl_ecx_key_free(key);
return NULL;
}
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
{
static const unsigned char generator_x[] = {
0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
};
static const unsigned char generator_y[] = {
0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
};
unsigned char x_dst[57], buff[114];
ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
gctx->propq);
unsigned char *privkey = NULL, *pubkey;
EVP_MD_CTX *hashctx = NULL;
EVP_MD *shake = NULL;
if (key == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
/* If we're doing parameter generation then we just return a blank key */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return key;
pubkey = key->pubkey;
privkey = ossl_ecx_key_allocate_privkey(key);
if (privkey == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
if (shake == NULL)
goto err;
if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
goto err;
hashctx = EVP_MD_CTX_new();
if (hashctx == NULL)
goto err;
if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
goto err;
if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
goto err;
if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
goto err;
buff[0] &= -4;
buff[55] |= 0x80;
buff[56] = 0;
if (s390x_ed448_mul(x_dst, pubkey,
generator_x, generator_y, buff) != 1)
goto err;
pubkey[56] |= ((x_dst[0] & 0x01) << 7);
EVP_MD_CTX_free(hashctx);
EVP_MD_free(shake);
key->haspubkey = 1;
return key;
err:
ossl_ecx_key_free(key);
EVP_MD_CTX_free(hashctx);
EVP_MD_free(shake);
return NULL;
}
#endif
diff --git a/crypto/openssl/providers/implementations/keymgmt/mac_legacy_kmgmt.c b/crypto/openssl/providers/implementations/keymgmt/mac_legacy_kmgmt.c
index 1fae4407fca6..b02a0a91c6f6 100644
--- a/crypto/openssl/providers/implementations/keymgmt/mac_legacy_kmgmt.c
+++ b/crypto/openssl/providers/implementations/keymgmt/mac_legacy_kmgmt.c
@@ -1,578 +1,578 @@
/*
- * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* We need to use some engine deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
#include <string.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/proverr.h>
#include <openssl/param_build.h>
#ifndef FIPS_MODULE
# include <openssl/engine.h>
#endif
#include "internal/param_build_set.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/provider_ctx.h"
#include "prov/macsignature.h"
static OSSL_FUNC_keymgmt_new_fn mac_new;
static OSSL_FUNC_keymgmt_free_fn mac_free;
static OSSL_FUNC_keymgmt_gen_init_fn mac_gen_init;
static OSSL_FUNC_keymgmt_gen_fn mac_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn mac_gen_cleanup;
static OSSL_FUNC_keymgmt_gen_set_params_fn mac_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn mac_gen_settable_params;
static OSSL_FUNC_keymgmt_get_params_fn mac_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn mac_gettable_params;
static OSSL_FUNC_keymgmt_set_params_fn mac_set_params;
static OSSL_FUNC_keymgmt_settable_params_fn mac_settable_params;
static OSSL_FUNC_keymgmt_has_fn mac_has;
static OSSL_FUNC_keymgmt_match_fn mac_match;
static OSSL_FUNC_keymgmt_import_fn mac_import;
static OSSL_FUNC_keymgmt_import_types_fn mac_imexport_types;
static OSSL_FUNC_keymgmt_export_fn mac_export;
static OSSL_FUNC_keymgmt_export_types_fn mac_imexport_types;
static OSSL_FUNC_keymgmt_new_fn mac_new_cmac;
static OSSL_FUNC_keymgmt_gettable_params_fn cmac_gettable_params;
static OSSL_FUNC_keymgmt_import_types_fn cmac_imexport_types;
static OSSL_FUNC_keymgmt_export_types_fn cmac_imexport_types;
static OSSL_FUNC_keymgmt_gen_init_fn cmac_gen_init;
static OSSL_FUNC_keymgmt_gen_set_params_fn cmac_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn cmac_gen_settable_params;
struct mac_gen_ctx {
OSSL_LIB_CTX *libctx;
int selection;
unsigned char *priv_key;
size_t priv_key_len;
PROV_CIPHER cipher;
};
MAC_KEY *ossl_mac_key_new(OSSL_LIB_CTX *libctx, int cmac)
{
MAC_KEY *mackey;
if (!ossl_prov_is_running())
return NULL;
mackey = OPENSSL_zalloc(sizeof(*mackey));
if (mackey == NULL)
return NULL;
mackey->lock = CRYPTO_THREAD_lock_new();
if (mackey->lock == NULL) {
OPENSSL_free(mackey);
return NULL;
}
mackey->libctx = libctx;
mackey->refcnt = 1;
mackey->cmac = cmac;
return mackey;
}
void ossl_mac_key_free(MAC_KEY *mackey)
{
int ref = 0;
if (mackey == NULL)
return;
CRYPTO_DOWN_REF(&mackey->refcnt, &ref, mackey->lock);
if (ref > 0)
return;
OPENSSL_secure_clear_free(mackey->priv_key, mackey->priv_key_len);
OPENSSL_free(mackey->properties);
ossl_prov_cipher_reset(&mackey->cipher);
CRYPTO_THREAD_lock_free(mackey->lock);
OPENSSL_free(mackey);
}
int ossl_mac_key_up_ref(MAC_KEY *mackey)
{
int ref = 0;
/* This is effectively doing a new operation on the MAC_KEY and should be
* adequately guarded again modules' error states. However, both current
* calls here are guarded propery in signature/mac_legacy.c. Thus, it
* could be removed here. The concern is that something in the future
* might call this function without adequate guards. It's a cheap call,
* it seems best to leave it even though it is currently redundant.
*/
if (!ossl_prov_is_running())
return 0;
CRYPTO_UP_REF(&mackey->refcnt, &ref, mackey->lock);
return 1;
}
static void *mac_new(void *provctx)
{
return ossl_mac_key_new(PROV_LIBCTX_OF(provctx), 0);
}
static void *mac_new_cmac(void *provctx)
{
return ossl_mac_key_new(PROV_LIBCTX_OF(provctx), 1);
}
static void mac_free(void *mackey)
{
ossl_mac_key_free(mackey);
}
static int mac_has(const void *keydata, int selection)
{
const MAC_KEY *key = keydata;
int ok = 0;
if (ossl_prov_is_running() && key != NULL) {
/*
* MAC keys always have all the parameters they need (i.e. none).
* Therefore we always return with 1, if asked about parameters.
* Similarly for public keys.
*/
ok = 1;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = key->priv_key != NULL;
}
return ok;
}
static int mac_match(const void *keydata1, const void *keydata2, int selection)
{
const MAC_KEY *key1 = keydata1;
const MAC_KEY *key2 = keydata2;
int ok = 1;
if (!ossl_prov_is_running())
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if ((key1->priv_key == NULL && key2->priv_key != NULL)
|| (key1->priv_key != NULL && key2->priv_key == NULL)
|| key1->priv_key_len != key2->priv_key_len
|| (key1->cipher.cipher == NULL && key2->cipher.cipher != NULL)
|| (key1->cipher.cipher != NULL && key2->cipher.cipher == NULL))
ok = 0;
else
ok = ok && (key1->priv_key == NULL /* implies key2->privkey == NULL */
|| CRYPTO_memcmp(key1->priv_key, key2->priv_key,
key1->priv_key_len) == 0);
if (key1->cipher.cipher != NULL)
ok = ok && EVP_CIPHER_is_a(key1->cipher.cipher,
EVP_CIPHER_get0_name(key2->cipher.cipher));
}
return ok;
}
static int mac_key_fromdata(MAC_KEY *key, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
OPENSSL_secure_clear_free(key->priv_key, key->priv_key_len);
/* allocate at least one byte to distinguish empty key from no key set */
key->priv_key = OPENSSL_secure_malloc(p->data_size > 0 ? p->data_size : 1);
if (key->priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(key->priv_key, p->data, p->data_size);
key->priv_key_len = p->data_size;
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
OPENSSL_free(key->properties);
key->properties = OPENSSL_strdup(p->data);
if (key->properties == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (key->cmac && !ossl_prov_cipher_load_from_params(&key->cipher, params,
key->libctx)) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
if (key->priv_key != NULL)
return 1;
return 0;
}
static int mac_import(void *keydata, int selection, const OSSL_PARAM params[])
{
MAC_KEY *key = keydata;
if (!ossl_prov_is_running() || key == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0)
return 0;
return mac_key_fromdata(key, params);
}
static int key_to_params(MAC_KEY *key, OSSL_PARAM_BLD *tmpl,
OSSL_PARAM params[])
{
if (key == NULL)
return 0;
if (key->priv_key != NULL
&& !ossl_param_build_set_octet_string(tmpl, params,
OSSL_PKEY_PARAM_PRIV_KEY,
key->priv_key, key->priv_key_len))
return 0;
if (key->cipher.cipher != NULL
&& !ossl_param_build_set_utf8_string(tmpl, params,
OSSL_PKEY_PARAM_CIPHER,
EVP_CIPHER_get0_name(key->cipher.cipher)))
return 0;
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
if (key->cipher.engine != NULL
&& !ossl_param_build_set_utf8_string(tmpl, params,
OSSL_PKEY_PARAM_ENGINE,
ENGINE_get_id(key->cipher.engine)))
return 0;
#endif
return 1;
}
static int mac_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
void *cbarg)
{
MAC_KEY *key = keydata;
OSSL_PARAM_BLD *tmpl;
OSSL_PARAM *params = NULL;
int ret = 0;
if (!ossl_prov_is_running() || key == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0)
return 0;
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
&& !key_to_params(key, tmpl, NULL))
goto err;
params = OSSL_PARAM_BLD_to_param(tmpl);
if (params == NULL)
goto err;
ret = param_cb(params, cbarg);
OSSL_PARAM_free(params);
err:
OSSL_PARAM_BLD_free(tmpl);
return ret;
}
static const OSSL_PARAM mac_key_types[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *mac_imexport_types(int selection)
{
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
return mac_key_types;
return NULL;
}
static const OSSL_PARAM cmac_key_types[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_CIPHER, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_ENGINE, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *cmac_imexport_types(int selection)
{
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
return cmac_key_types;
return NULL;
}
static int mac_get_params(void *key, OSSL_PARAM params[])
{
return key_to_params(key, NULL, params);
}
static const OSSL_PARAM *mac_gettable_params(void *provctx)
{
static const OSSL_PARAM gettable_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
OSSL_PARAM_END
};
return gettable_params;
}
static const OSSL_PARAM *cmac_gettable_params(void *provctx)
{
static const OSSL_PARAM gettable_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_CIPHER, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_ENGINE, NULL, 0),
OSSL_PARAM_END
};
return gettable_params;
}
static int mac_set_params(void *keydata, const OSSL_PARAM params[])
{
MAC_KEY *key = keydata;
const OSSL_PARAM *p;
if (key == NULL)
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
if (p != NULL)
return mac_key_fromdata(key, params);
return 1;
}
static const OSSL_PARAM *mac_settable_params(void *provctx)
{
static const OSSL_PARAM settable_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
OSSL_PARAM_END
};
return settable_params;
}
static void *mac_gen_init_common(void *provctx, int selection)
{
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
struct mac_gen_ctx *gctx = NULL;
if (!ossl_prov_is_running())
return NULL;
if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
gctx->libctx = libctx;
gctx->selection = selection;
}
return gctx;
}
static void *mac_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
struct mac_gen_ctx *gctx = mac_gen_init_common(provctx, selection);
if (gctx != NULL && !mac_gen_set_params(gctx, params)) {
- OPENSSL_free(gctx);
+ mac_gen_cleanup(gctx);
gctx = NULL;
}
return gctx;
}
static void *cmac_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
struct mac_gen_ctx *gctx = mac_gen_init_common(provctx, selection);
if (gctx != NULL && !cmac_gen_set_params(gctx, params)) {
- OPENSSL_free(gctx);
+ mac_gen_cleanup(gctx);
gctx = NULL;
}
return gctx;
}
static int mac_gen_set_params(void *genctx, const OSSL_PARAM params[])
{
struct mac_gen_ctx *gctx = genctx;
const OSSL_PARAM *p;
if (gctx == NULL)
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
gctx->priv_key = OPENSSL_secure_malloc(p->data_size);
if (gctx->priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(gctx->priv_key, p->data, p->data_size);
gctx->priv_key_len = p->data_size;
}
return 1;
}
static int cmac_gen_set_params(void *genctx, const OSSL_PARAM params[])
{
struct mac_gen_ctx *gctx = genctx;
if (!mac_gen_set_params(genctx, params))
return 0;
if (!ossl_prov_cipher_load_from_params(&gctx->cipher, params,
gctx->libctx)) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
return 1;
}
static const OSSL_PARAM *mac_gen_settable_params(ossl_unused void *genctx,
ossl_unused void *provctx)
{
static OSSL_PARAM settable[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
OSSL_PARAM_END
};
return settable;
}
static const OSSL_PARAM *cmac_gen_settable_params(ossl_unused void *genctx,
ossl_unused void *provctx)
{
static OSSL_PARAM settable[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_CIPHER, NULL, 0),
OSSL_PARAM_END
};
return settable;
}
static void *mac_gen(void *genctx, OSSL_CALLBACK *cb, void *cbarg)
{
struct mac_gen_ctx *gctx = genctx;
MAC_KEY *key;
if (!ossl_prov_is_running() || gctx == NULL)
return NULL;
if ((key = ossl_mac_key_new(gctx->libctx, 0)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
/* If we're doing parameter generation then we just return a blank key */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return key;
if (gctx->priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
ossl_mac_key_free(key);
return NULL;
}
/*
* This is horrible but required for backwards compatibility. We don't
* actually do real key generation at all. We simply copy the key that was
* previously set in the gctx. Hopefully at some point in the future all
* of this can be removed and we will only support the EVP_KDF APIs.
*/
if (!ossl_prov_cipher_copy(&key->cipher, &gctx->cipher)) {
ossl_mac_key_free(key);
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return NULL;
}
ossl_prov_cipher_reset(&gctx->cipher);
key->priv_key = gctx->priv_key;
key->priv_key_len = gctx->priv_key_len;
gctx->priv_key_len = 0;
gctx->priv_key = NULL;
return key;
}
static void mac_gen_cleanup(void *genctx)
{
struct mac_gen_ctx *gctx = genctx;
OPENSSL_secure_clear_free(gctx->priv_key, gctx->priv_key_len);
ossl_prov_cipher_reset(&gctx->cipher);
OPENSSL_free(gctx);
}
const OSSL_DISPATCH ossl_mac_legacy_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))mac_new },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))mac_free },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))mac_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))mac_gettable_params },
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))mac_set_params },
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))mac_settable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))mac_has },
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))mac_match },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))mac_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))mac_imexport_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))mac_export },
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))mac_imexport_types },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))mac_gen_init },
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))mac_gen_set_params },
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
(void (*)(void))mac_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))mac_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))mac_gen_cleanup },
{ 0, NULL }
};
const OSSL_DISPATCH ossl_cmac_legacy_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))mac_new_cmac },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))mac_free },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))mac_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))cmac_gettable_params },
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))mac_set_params },
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))mac_settable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))mac_has },
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))mac_match },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))mac_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))cmac_imexport_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))mac_export },
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))cmac_imexport_types },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))cmac_gen_init },
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))cmac_gen_set_params },
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
(void (*)(void))cmac_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))mac_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))mac_gen_cleanup },
{ 0, NULL }
};
diff --git a/crypto/openssl/providers/implementations/signature/eddsa_sig.c b/crypto/openssl/providers/implementations/signature/eddsa_sig.c
index c78f1fbb5fa6..9ec910af2527 100644
--- a/crypto/openssl/providers/implementations/signature/eddsa_sig.c
+++ b/crypto/openssl/providers/implementations/signature/eddsa_sig.c
@@ -1,468 +1,469 @@
/*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/crypto.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/params.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/proverr.h>
#include "internal/nelem.h"
#include "internal/sizes.h"
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "prov/der_ecx.h"
#include "crypto/ecx.h"
#ifdef S390X_EC_ASM
# include "s390x_arch.h"
# define S390X_CAN_SIGN(edtype) \
((OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_##edtype)) \
&& (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_##edtype)) \
&& (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_##edtype)))
static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
const unsigned char *tbs, size_t tbslen);
static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
const unsigned char *tbs, size_t tbslen);
static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
const unsigned char *sig,
const unsigned char *tbs, size_t tbslen);
static int s390x_ed448_digestverify(const ECX_KEY *edkey,
const unsigned char *sig,
const unsigned char *tbs, size_t tbslen);
#endif /* S390X_EC_ASM */
static OSSL_FUNC_signature_newctx_fn eddsa_newctx;
static OSSL_FUNC_signature_digest_sign_init_fn eddsa_digest_signverify_init;
static OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign;
static OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign;
static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify;
static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify;
static OSSL_FUNC_signature_freectx_fn eddsa_freectx;
static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx;
static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params;
static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params;
typedef struct {
OSSL_LIB_CTX *libctx;
ECX_KEY *key;
/* The Algorithm Identifier of the signature algorithm */
unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
unsigned char *aid;
size_t aid_len;
} PROV_EDDSA_CTX;
static void *eddsa_newctx(void *provctx, const char *propq_unused)
{
PROV_EDDSA_CTX *peddsactx;
if (!ossl_prov_is_running())
return NULL;
peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));
if (peddsactx == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
peddsactx->libctx = PROV_LIBCTX_OF(provctx);
return peddsactx;
}
static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname,
void *vedkey,
ossl_unused const OSSL_PARAM params[])
{
PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
ECX_KEY *edkey = (ECX_KEY *)vedkey;
WPACKET pkt;
int ret;
if (!ossl_prov_is_running())
return 0;
if (mdname != NULL && mdname[0] != '\0') {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
return 0;
}
if (edkey == NULL) {
if (peddsactx->key != NULL)
/* there is nothing to do on reinit */
return 1;
ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
return 0;
}
if (!ossl_ecx_key_up_ref(edkey)) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* We do not care about DER writing errors.
* All it really means is that for some reason, there's no
* AlgorithmIdentifier to be had, but the operation itself is
* still valid, just as long as it's not used to construct
* anything that needs an AlgorithmIdentifier.
*/
peddsactx->aid_len = 0;
ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
switch (edkey->type) {
case ECX_KEY_TYPE_ED25519:
ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
break;
case ECX_KEY_TYPE_ED448:
ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
break;
default:
/* Should never happen */
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
ossl_ecx_key_free(edkey);
+ WPACKET_cleanup(&pkt);
return 0;
}
if (ret && WPACKET_finish(&pkt)) {
WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
peddsactx->aid = WPACKET_get_curr(&pkt);
}
WPACKET_cleanup(&pkt);
peddsactx->key = edkey;
return 1;
}
int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
size_t *siglen, size_t sigsize,
const unsigned char *tbs, size_t tbslen)
{
PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
const ECX_KEY *edkey = peddsactx->key;
if (!ossl_prov_is_running())
return 0;
if (sigret == NULL) {
*siglen = ED25519_SIGSIZE;
return 1;
}
if (sigsize < ED25519_SIGSIZE) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (edkey->privkey == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
#ifdef S390X_EC_ASM
if (S390X_CAN_SIGN(ED25519)) {
if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
return 0;
}
*siglen = ED25519_SIGSIZE;
return 1;
}
#endif /* S390X_EC_ASM */
if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
peddsactx->libctx, NULL) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
return 0;
}
*siglen = ED25519_SIGSIZE;
return 1;
}
int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
size_t *siglen, size_t sigsize,
const unsigned char *tbs, size_t tbslen)
{
PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
const ECX_KEY *edkey = peddsactx->key;
if (!ossl_prov_is_running())
return 0;
if (sigret == NULL) {
*siglen = ED448_SIGSIZE;
return 1;
}
if (sigsize < ED448_SIGSIZE) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (edkey->privkey == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
#ifdef S390X_EC_ASM
if (S390X_CAN_SIGN(ED448)) {
if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
return 0;
}
*siglen = ED448_SIGSIZE;
return 1;
}
#endif /* S390X_EC_ASM */
if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen, edkey->pubkey,
edkey->privkey, NULL, 0, edkey->propq) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
return 0;
}
*siglen = ED448_SIGSIZE;
return 1;
}
int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen)
{
PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
const ECX_KEY *edkey = peddsactx->key;
if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
return 0;
#ifdef S390X_EC_ASM
if (S390X_CAN_SIGN(ED25519))
return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);
#endif /* S390X_EC_ASM */
return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
peddsactx->libctx, edkey->propq);
}
int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen)
{
PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
const ECX_KEY *edkey = peddsactx->key;
if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
return 0;
#ifdef S390X_EC_ASM
if (S390X_CAN_SIGN(ED448))
return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);
#endif /* S390X_EC_ASM */
return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
NULL, 0, edkey->propq);
}
static void eddsa_freectx(void *vpeddsactx)
{
PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
ossl_ecx_key_free(peddsactx->key);
OPENSSL_free(peddsactx);
}
static void *eddsa_dupctx(void *vpeddsactx)
{
PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
PROV_EDDSA_CTX *dstctx;
if (!ossl_prov_is_running())
return NULL;
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
if (dstctx == NULL)
return NULL;
*dstctx = *srcctx;
dstctx->key = NULL;
if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
goto err;
}
dstctx->key = srcctx->key;
return dstctx;
err:
eddsa_freectx(dstctx);
return NULL;
}
static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
{
PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
OSSL_PARAM *p;
if (peddsactx == NULL)
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid,
peddsactx->aid_len))
return 0;
return 1;
}
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,
ossl_unused void *provctx)
{
return known_gettable_ctx_params;
}
const OSSL_DISPATCH ossl_ed25519_signature_functions[] = {
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
(void (*)(void))eddsa_digest_signverify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
(void (*)(void))ed25519_digest_sign },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
(void (*)(void))eddsa_digest_signverify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
(void (*)(void))ed25519_digest_verify },
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
(void (*)(void))eddsa_gettable_ctx_params },
{ 0, NULL }
};
const OSSL_DISPATCH ossl_ed448_signature_functions[] = {
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
(void (*)(void))eddsa_digest_signverify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
(void (*)(void))ed448_digest_sign },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
(void (*)(void))eddsa_digest_signverify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
(void (*)(void))ed448_digest_verify },
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
(void (*)(void))eddsa_gettable_ctx_params },
{ 0, NULL }
};
#ifdef S390X_EC_ASM
static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
const unsigned char *tbs, size_t tbslen)
{
int rc;
union {
struct {
unsigned char sig[64];
unsigned char priv[32];
} ed25519;
unsigned long long buff[512];
} param;
memset(&param, 0, sizeof(param));
memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
if (rc != 0)
return 0;
s390x_flip_endian32(sig, param.ed25519.sig);
s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
return 1;
}
static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
const unsigned char *tbs, size_t tbslen)
{
int rc;
union {
struct {
unsigned char sig[128];
unsigned char priv[64];
} ed448;
unsigned long long buff[512];
} param;
memset(&param, 0, sizeof(param));
memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
if (rc != 0)
return 0;
s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
memcpy(sig, param.ed448.sig, 57);
memcpy(sig + 57, param.ed448.sig + 64, 57);
return 1;
}
static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
const unsigned char *sig,
const unsigned char *tbs, size_t tbslen)
{
union {
struct {
unsigned char sig[64];
unsigned char pub[32];
} ed25519;
unsigned long long buff[512];
} param;
memset(&param, 0, sizeof(param));
s390x_flip_endian32(param.ed25519.sig, sig);
s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
&param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
}
static int s390x_ed448_digestverify(const ECX_KEY *edkey,
const unsigned char *sig,
const unsigned char *tbs,
size_t tbslen)
{
union {
struct {
unsigned char sig[128];
unsigned char pub[64];
} ed448;
unsigned long long buff[512];
} param;
memset(&param, 0, sizeof(param));
memcpy(param.ed448.sig, sig, 57);
s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
memcpy(param.ed448.sig + 64, sig + 57, 57);
s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
memcpy(param.ed448.pub, edkey->pubkey, 57);
s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
&param.ed448, tbs, tbslen) == 0 ? 1 : 0;
}
#endif /* S390X_EC_ASM */
diff --git a/crypto/openssl/providers/implementations/storemgmt/file_store.c b/crypto/openssl/providers/implementations/storemgmt/file_store.c
index bb8b2ab8625a..3049a9c81133 100644
--- a/crypto/openssl/providers/implementations/storemgmt/file_store.c
+++ b/crypto/openssl/providers/implementations/storemgmt/file_store.c
@@ -1,790 +1,790 @@
/*
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 has quite some overlap with engines/e_loader_attic.c */
#include <string.h>
#include <sys/stat.h>
#include <ctype.h> /* isdigit */
#include <assert.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/core_object.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/params.h>
#include <openssl/decoder.h>
#include <openssl/proverr.h>
#include <openssl/store.h> /* The OSSL_STORE_INFO type numbers */
#include "internal/cryptlib.h"
#include "internal/o_dir.h"
#include "crypto/decoder.h"
#include "crypto/ctype.h" /* ossl_isdigit() */
#include "prov/implementations.h"
#include "prov/bio.h"
#include "file_store_local.h"
DEFINE_STACK_OF(OSSL_STORE_INFO)
#ifdef _WIN32
# define stat _stat
#endif
#ifndef S_ISDIR
# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
#endif
static OSSL_FUNC_store_open_fn file_open;
static OSSL_FUNC_store_attach_fn file_attach;
static OSSL_FUNC_store_settable_ctx_params_fn file_settable_ctx_params;
static OSSL_FUNC_store_set_ctx_params_fn file_set_ctx_params;
static OSSL_FUNC_store_load_fn file_load;
static OSSL_FUNC_store_eof_fn file_eof;
static OSSL_FUNC_store_close_fn file_close;
/*
* This implementation makes full use of OSSL_DECODER, and then some.
* It uses its own internal decoder implementation that reads DER and
* passes that on to the data callback; this decoder is created with
* internal OpenSSL functions, thereby bypassing the need for a surrounding
* provider. This is ok, since this is a local decoder, not meant for
* public consumption. It also uses the libcrypto internal decoder
* setup function ossl_decoder_ctx_setup_for_pkey(), to allow the
* last resort decoder to be added first (and thereby be executed last).
* Finally, it sets up its own construct and cleanup functions.
*
* Essentially, that makes this implementation a kind of glorified decoder.
*/
struct file_ctx_st {
void *provctx;
char *uri; /* The URI we currently try to load */
enum {
IS_FILE = 0, /* Read file and pass results */
IS_DIR /* Pass directory entry names */
} type;
union {
/* Used with |IS_FILE| */
struct {
BIO *file;
OSSL_DECODER_CTX *decoderctx;
char *input_type;
char *propq; /* The properties we got as a parameter */
} file;
/* Used with |IS_DIR| */
struct {
OPENSSL_DIR_CTX *ctx;
int end_reached;
/*
* When a search expression is given, these are filled in.
* |search_name| contains the file basename to look for.
* The string is exactly 8 characters long.
*/
char search_name[9];
/*
* The directory reading utility we have combines opening with
* reading the first name. To make sure we can detect the end
* at the right time, we read early and cache the name.
*/
const char *last_entry;
int last_errno;
} dir;
} _;
/* Expected object type. May be unspecified */
int expected_type;
};
static void free_file_ctx(struct file_ctx_st *ctx)
{
if (ctx == NULL)
return;
OPENSSL_free(ctx->uri);
if (ctx->type != IS_DIR) {
OSSL_DECODER_CTX_free(ctx->_.file.decoderctx);
OPENSSL_free(ctx->_.file.propq);
OPENSSL_free(ctx->_.file.input_type);
}
OPENSSL_free(ctx);
}
static struct file_ctx_st *new_file_ctx(int type, const char *uri,
void *provctx)
{
struct file_ctx_st *ctx = NULL;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL
&& (uri == NULL || (ctx->uri = OPENSSL_strdup(uri)) != NULL)) {
ctx->type = type;
ctx->provctx = provctx;
return ctx;
}
free_file_ctx(ctx);
return NULL;
}
static OSSL_DECODER_CONSTRUCT file_load_construct;
static OSSL_DECODER_CLEANUP file_load_cleanup;
/*-
* Opening / attaching streams and directories
* -------------------------------------------
*/
/*
* Function to service both file_open() and file_attach()
*
*
*/
static struct file_ctx_st *file_open_stream(BIO *source, const char *uri,
void *provctx)
{
struct file_ctx_st *ctx;
if ((ctx = new_file_ctx(IS_FILE, uri, provctx)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
ctx->_.file.file = source;
return ctx;
err:
free_file_ctx(ctx);
return NULL;
}
static void *file_open_dir(const char *path, const char *uri, void *provctx)
{
struct file_ctx_st *ctx;
if ((ctx = new_file_ctx(IS_DIR, uri, provctx)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path);
ctx->_.dir.last_errno = errno;
if (ctx->_.dir.last_entry == NULL) {
if (ctx->_.dir.last_errno != 0) {
ERR_raise_data(ERR_LIB_SYS, ctx->_.dir.last_errno,
"Calling OPENSSL_DIR_read(\"%s\")", path);
goto err;
}
ctx->_.dir.end_reached = 1;
}
return ctx;
err:
file_close(ctx);
return NULL;
}
static void *file_open(void *provctx, const char *uri)
{
struct file_ctx_st *ctx = NULL;
struct stat st;
struct {
const char *path;
unsigned int check_absolute:1;
} path_data[2];
size_t path_data_n = 0, i;
const char *path;
BIO *bio;
ERR_set_mark();
/*
* First step, just take the URI as is.
*/
path_data[path_data_n].check_absolute = 0;
path_data[path_data_n++].path = uri;
/*
* Second step, if the URI appears to start with the 'file' scheme,
* extract the path and make that the second path to check.
* There's a special case if the URI also contains an authority, then
* the full URI shouldn't be used as a path anywhere.
*/
if (OPENSSL_strncasecmp(uri, "file:", 5) == 0) {
const char *p = &uri[5];
if (strncmp(&uri[5], "//", 2) == 0) {
path_data_n--; /* Invalidate using the full URI */
if (OPENSSL_strncasecmp(&uri[7], "localhost/", 10) == 0) {
p = &uri[16];
} else if (uri[7] == '/') {
p = &uri[7];
} else {
ERR_clear_last_mark();
ERR_raise(ERR_LIB_PROV, PROV_R_URI_AUTHORITY_UNSUPPORTED);
return NULL;
}
}
path_data[path_data_n].check_absolute = 1;
#ifdef _WIN32
/* Windows file: URIs with a drive letter start with a / */
if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
- char c = tolower(p[1]);
+ char c = tolower((unsigned char)p[1]);
if (c >= 'a' && c <= 'z') {
p++;
/* We know it's absolute, so no need to check */
path_data[path_data_n].check_absolute = 0;
}
}
#endif
path_data[path_data_n++].path = p;
}
for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) {
/*
* If the scheme "file" was an explicit part of the URI, the path must
* be absolute. So says RFC 8089
*/
if (path_data[i].check_absolute && path_data[i].path[0] != '/') {
ERR_clear_last_mark();
ERR_raise_data(ERR_LIB_PROV, PROV_R_PATH_MUST_BE_ABSOLUTE,
"Given path=%s", path_data[i].path);
return NULL;
}
if (stat(path_data[i].path, &st) < 0) {
ERR_raise_data(ERR_LIB_SYS, errno,
"calling stat(%s)",
path_data[i].path);
} else {
path = path_data[i].path;
}
}
if (path == NULL) {
ERR_clear_last_mark();
return NULL;
}
/* Successfully found a working path, clear possible collected errors */
ERR_pop_to_mark();
if (S_ISDIR(st.st_mode))
ctx = file_open_dir(path, uri, provctx);
else if ((bio = BIO_new_file(path, "rb")) == NULL
|| (ctx = file_open_stream(bio, uri, provctx)) == NULL)
BIO_free_all(bio);
return ctx;
}
void *file_attach(void *provctx, OSSL_CORE_BIO *cin)
{
struct file_ctx_st *ctx;
BIO *new_bio = ossl_bio_new_from_core_bio(provctx, cin);
if (new_bio == NULL)
return NULL;
ctx = file_open_stream(new_bio, NULL, provctx);
if (ctx == NULL)
BIO_free(new_bio);
return ctx;
}
/*-
* Setting parameters
* ------------------
*/
static const OSSL_PARAM *file_settable_ctx_params(void *provctx)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_int(OSSL_STORE_PARAM_EXPECT, NULL),
OSSL_PARAM_octet_string(OSSL_STORE_PARAM_SUBJECT, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_INPUT_TYPE, NULL, 0),
OSSL_PARAM_END
};
return known_settable_ctx_params;
}
static int file_set_ctx_params(void *loaderctx, const OSSL_PARAM params[])
{
struct file_ctx_st *ctx = loaderctx;
const OSSL_PARAM *p;
if (params == NULL)
return 1;
if (ctx->type != IS_DIR) {
/* these parameters are ignored for directories */
p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_PROPERTIES);
if (p != NULL) {
OPENSSL_free(ctx->_.file.propq);
ctx->_.file.propq = NULL;
if (!OSSL_PARAM_get_utf8_string(p, &ctx->_.file.propq, 0))
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_INPUT_TYPE);
if (p != NULL) {
OPENSSL_free(ctx->_.file.input_type);
ctx->_.file.input_type = NULL;
if (!OSSL_PARAM_get_utf8_string(p, &ctx->_.file.input_type, 0))
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_EXPECT);
if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->expected_type))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT);
if (p != NULL) {
const unsigned char *der = NULL;
size_t der_len = 0;
X509_NAME *x509_name;
unsigned long hash;
int ok;
if (ctx->type != IS_DIR) {
ERR_raise(ERR_LIB_PROV,
PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
return 0;
}
if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&der, &der_len)
|| (x509_name = d2i_X509_NAME(NULL, &der, der_len)) == NULL)
return 0;
hash = X509_NAME_hash_ex(x509_name,
ossl_prov_ctx_get0_libctx(ctx->provctx), NULL,
&ok);
BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name),
"%08lx", hash);
X509_NAME_free(x509_name);
if (ok == 0)
return 0;
}
return 1;
}
/*-
* Loading an object from a stream
* -------------------------------
*/
struct file_load_data_st {
OSSL_CALLBACK *object_cb;
void *object_cbarg;
};
static int file_load_construct(OSSL_DECODER_INSTANCE *decoder_inst,
const OSSL_PARAM *params, void *construct_data)
{
struct file_load_data_st *data = construct_data;
/*
* At some point, we may find it justifiable to recognise PKCS#12 and
* handle it specially here, making |file_load()| return pass its
* contents one piece at ta time, like |e_loader_attic.c| does.
*
* However, that currently means parsing them out, which converts the
* DER encoded PKCS#12 into a bunch of EVP_PKEYs and X509s, just to
* have to re-encode them into DER to create an object abstraction for
* each of them.
* It's much simpler (less churn) to pass on the object abstraction we
* get to the load_result callback and leave it to that one to do the
* work. If that's libcrypto code, we know that it has much better
* possibilities to handle the EVP_PKEYs and X509s without the extra
* churn.
*/
return data->object_cb(params, data->object_cbarg);
}
void file_load_cleanup(void *construct_data)
{
/* Nothing to do */
}
static int file_setup_decoders(struct file_ctx_st *ctx)
{
OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(ctx->provctx);
const OSSL_ALGORITHM *to_algo = NULL;
int ok = 0;
/* Setup for this session, so only if not already done */
if (ctx->_.file.decoderctx == NULL) {
if ((ctx->_.file.decoderctx = OSSL_DECODER_CTX_new()) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Make sure the input type is set */
if (!OSSL_DECODER_CTX_set_input_type(ctx->_.file.decoderctx,
ctx->_.file.input_type)) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
/*
* Where applicable, set the outermost structure name.
* The goal is to avoid the STORE object types that are
* potentially password protected but aren't interesting
* for this load.
*/
switch (ctx->expected_type) {
case OSSL_STORE_INFO_CERT:
if (!OSSL_DECODER_CTX_set_input_structure(ctx->_.file.decoderctx,
"Certificate")) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
break;
case OSSL_STORE_INFO_CRL:
if (!OSSL_DECODER_CTX_set_input_structure(ctx->_.file.decoderctx,
"CertificateList")) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
break;
default:
break;
}
for (to_algo = ossl_any_to_obj_algorithm;
to_algo->algorithm_names != NULL;
to_algo++) {
OSSL_DECODER *to_obj = NULL;
OSSL_DECODER_INSTANCE *to_obj_inst = NULL;
/*
* Create the internal last resort decoder implementation
* together with a "decoder instance".
* The decoder doesn't need any identification or to be
* attached to any provider, since it's only used locally.
*/
to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL);
if (to_obj != NULL)
to_obj_inst = ossl_decoder_instance_new(to_obj, ctx->provctx);
OSSL_DECODER_free(to_obj);
if (to_obj_inst == NULL)
goto err;
if (!ossl_decoder_ctx_add_decoder_inst(ctx->_.file.decoderctx,
to_obj_inst)) {
ossl_decoder_instance_free(to_obj_inst);
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
}
/* Add on the usual extra decoders */
if (!OSSL_DECODER_CTX_add_extra(ctx->_.file.decoderctx,
libctx, ctx->_.file.propq)) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
/*
* Then install our constructor hooks, which just passes decoded
* data to the load callback
*/
if (!OSSL_DECODER_CTX_set_construct(ctx->_.file.decoderctx,
file_load_construct)
|| !OSSL_DECODER_CTX_set_cleanup(ctx->_.file.decoderctx,
file_load_cleanup)) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
}
ok = 1;
err:
return ok;
}
static int file_load_file(struct file_ctx_st *ctx,
OSSL_CALLBACK *object_cb, void *object_cbarg,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
struct file_load_data_st data;
int ret, err;
/* Setup the decoders (one time shot per session */
if (!file_setup_decoders(ctx))
return 0;
/* Setup for this object */
data.object_cb = object_cb;
data.object_cbarg = object_cbarg;
OSSL_DECODER_CTX_set_construct_data(ctx->_.file.decoderctx, &data);
OSSL_DECODER_CTX_set_passphrase_cb(ctx->_.file.decoderctx, pw_cb, pw_cbarg);
/* Launch */
ERR_set_mark();
ret = OSSL_DECODER_from_bio(ctx->_.file.decoderctx, ctx->_.file.file);
if (BIO_eof(ctx->_.file.file)
&& ((err = ERR_peek_last_error()) != 0)
&& ERR_GET_LIB(err) == ERR_LIB_OSSL_DECODER
&& ERR_GET_REASON(err) == ERR_R_UNSUPPORTED)
ERR_pop_to_mark();
else
ERR_clear_last_mark();
return ret;
}
/*-
* Loading a name object from a directory
* --------------------------------------
*/
static char *file_name_to_uri(struct file_ctx_st *ctx, const char *name)
{
char *data = NULL;
assert(name != NULL);
{
const char *pathsep = ossl_ends_with_dirsep(ctx->uri) ? "" : "/";
long calculated_length = strlen(ctx->uri) + strlen(pathsep)
+ strlen(name) + 1 /* \0 */;
data = OPENSSL_zalloc(calculated_length);
if (data == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_strlcat(data, ctx->uri, calculated_length);
OPENSSL_strlcat(data, pathsep, calculated_length);
OPENSSL_strlcat(data, name, calculated_length);
}
return data;
}
static int file_name_check(struct file_ctx_st *ctx, const char *name)
{
const char *p = NULL;
size_t len = strlen(ctx->_.dir.search_name);
/* If there are no search criteria, all names are accepted */
if (ctx->_.dir.search_name[0] == '\0')
return 1;
/* If the expected type isn't supported, no name is accepted */
if (ctx->expected_type != 0
&& ctx->expected_type != OSSL_STORE_INFO_CERT
&& ctx->expected_type != OSSL_STORE_INFO_CRL)
return 0;
/*
* First, check the basename
*/
if (OPENSSL_strncasecmp(name, ctx->_.dir.search_name, len) != 0
|| name[len] != '.')
return 0;
p = &name[len + 1];
/*
* Then, if the expected type is a CRL, check that the extension starts
* with 'r'
*/
if (*p == 'r') {
p++;
if (ctx->expected_type != 0
&& ctx->expected_type != OSSL_STORE_INFO_CRL)
return 0;
} else if (ctx->expected_type == OSSL_STORE_INFO_CRL) {
return 0;
}
/*
* Last, check that the rest of the extension is a decimal number, at
* least one digit long.
*/
if (!isdigit((unsigned char)*p))
return 0;
while (isdigit((unsigned char)*p))
p++;
#ifdef __VMS
/*
* One extra step here, check for a possible generation number.
*/
if (*p == ';')
for (p++; *p != '\0'; p++)
if (!ossl_isdigit((unsigned char)*p))
break;
#endif
/*
* If we've reached the end of the string at this point, we've successfully
* found a fitting file name.
*/
return *p == '\0';
}
static int file_load_dir_entry(struct file_ctx_st *ctx,
OSSL_CALLBACK *object_cb, void *object_cbarg,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
/* Prepare as much as possible in advance */
static const int object_type = OSSL_OBJECT_NAME;
OSSL_PARAM object[] = {
OSSL_PARAM_int(OSSL_OBJECT_PARAM_TYPE, (int *)&object_type),
OSSL_PARAM_utf8_string(OSSL_OBJECT_PARAM_DATA, NULL, 0),
OSSL_PARAM_END
};
char *newname = NULL;
int ok;
/* Loop until we get an error or until we have a suitable name */
do {
if (ctx->_.dir.last_entry == NULL) {
if (!ctx->_.dir.end_reached) {
assert(ctx->_.dir.last_errno != 0);
ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
}
/* file_eof() will tell if EOF was reached */
return 0;
}
/* flag acceptable names */
if (ctx->_.dir.last_entry[0] != '.'
&& file_name_check(ctx, ctx->_.dir.last_entry)) {
/* If we can't allocate the new name, we fail */
if ((newname =
file_name_to_uri(ctx, ctx->_.dir.last_entry)) == NULL)
return 0;
}
/*
* On the first call (with a NULL context), OPENSSL_DIR_read()
* cares about the second argument. On the following calls, it
* only cares that it isn't NULL. Therefore, we can safely give
* it our URI here.
*/
ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, ctx->uri);
ctx->_.dir.last_errno = errno;
if (ctx->_.dir.last_entry == NULL && ctx->_.dir.last_errno == 0)
ctx->_.dir.end_reached = 1;
} while (newname == NULL);
object[1].data = newname;
object[1].data_size = strlen(newname);
ok = object_cb(object, object_cbarg);
OPENSSL_free(newname);
return ok;
}
/*-
* Loading, local dispatcher
* -------------------------
*/
static int file_load(void *loaderctx,
OSSL_CALLBACK *object_cb, void *object_cbarg,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
struct file_ctx_st *ctx = loaderctx;
switch (ctx->type) {
case IS_FILE:
return file_load_file(ctx, object_cb, object_cbarg, pw_cb, pw_cbarg);
case IS_DIR:
return
file_load_dir_entry(ctx, object_cb, object_cbarg, pw_cb, pw_cbarg);
default:
break;
}
/* ctx->type has an unexpected value */
assert(0);
return 0;
}
/*-
* Eof detection and closing
* -------------------------
*/
static int file_eof(void *loaderctx)
{
struct file_ctx_st *ctx = loaderctx;
switch (ctx->type) {
case IS_DIR:
return ctx->_.dir.end_reached;
case IS_FILE:
/*
* BIO_pending() checks any filter BIO.
* BIO_eof() checks the source BIO.
*/
return !BIO_pending(ctx->_.file.file)
&& BIO_eof(ctx->_.file.file);
}
/* ctx->type has an unexpected value */
assert(0);
return 1;
}
static int file_close_dir(struct file_ctx_st *ctx)
{
if (ctx->_.dir.ctx != NULL)
OPENSSL_DIR_end(&ctx->_.dir.ctx);
free_file_ctx(ctx);
return 1;
}
static int file_close_stream(struct file_ctx_st *ctx)
{
/*
* This frees either the provider BIO filter (for file_attach()) OR
* the allocated file BIO (for file_open()).
*/
BIO_free(ctx->_.file.file);
ctx->_.file.file = NULL;
free_file_ctx(ctx);
return 1;
}
static int file_close(void *loaderctx)
{
struct file_ctx_st *ctx = loaderctx;
switch (ctx->type) {
case IS_DIR:
return file_close_dir(ctx);
case IS_FILE:
return file_close_stream(ctx);
}
/* ctx->type has an unexpected value */
assert(0);
return 1;
}
const OSSL_DISPATCH ossl_file_store_functions[] = {
{ OSSL_FUNC_STORE_OPEN, (void (*)(void))file_open },
{ OSSL_FUNC_STORE_ATTACH, (void (*)(void))file_attach },
{ OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS,
(void (*)(void))file_settable_ctx_params },
{ OSSL_FUNC_STORE_SET_CTX_PARAMS, (void (*)(void))file_set_ctx_params },
{ OSSL_FUNC_STORE_LOAD, (void (*)(void))file_load },
{ OSSL_FUNC_STORE_EOF, (void (*)(void))file_eof },
{ OSSL_FUNC_STORE_CLOSE, (void (*)(void))file_close },
{ 0, NULL },
};
diff --git a/crypto/openssl/ssl/statem/extensions_srvr.c b/crypto/openssl/ssl/statem/extensions_srvr.c
index 91ff14ce98f2..72c00574be68 100644
--- a/crypto/openssl/ssl/statem/extensions_srvr.c
+++ b/crypto/openssl/ssl/statem/extensions_srvr.c
@@ -1,1922 +1,1922 @@
/*
* Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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_local.h"
#include "statem_local.h"
#include "internal/cryptlib.h"
#define COOKIE_STATE_FORMAT_VERSION 1
/*
* 2 bytes for packet length, 2 bytes for format version, 2 bytes for
* protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for
* key_share present flag, 8 bytes for timestamp, 2 bytes for the hashlen,
* EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie
* length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing.
*/
#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 8 + 2 + EVP_MAX_MD_SIZE + 1 \
+ SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH)
/*
* Message header + 2 bytes for protocol version + number of random bytes +
* + 1 byte for legacy session id length + number of bytes in legacy session id
* + 2 bytes for ciphersuite + 1 byte for legacy compression
* + 2 bytes for extension block length + 6 bytes for key_share extension
* + 4 bytes for cookie extension header + the number of bytes in the cookie
*/
#define MAX_HRR_SIZE (SSL3_HM_HEADER_LENGTH + 2 + SSL3_RANDOM_SIZE + 1 \
+ SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \
+ MAX_COOKIE_SIZE)
/*
* Parse the client's renegotiation binding and abort if it's not right
*/
int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int ilen;
const unsigned char *data;
/* Parse the length byte */
if (!PACKET_get_1(pkt, &ilen)
|| !PACKET_get_bytes(pkt, &data, ilen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RENEGOTIATION_ENCODING_ERR);
return 0;
}
/* Check that the extension matches */
if (ilen != s->s3.previous_client_finished_len) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
if (memcmp(data, s->s3.previous_client_finished,
s->s3.previous_client_finished_len)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
s->s3.send_connection_binding = 1;
return 1;
}
/*-
* The servername extension is treated as follows:
*
* - Only the hostname type is supported with a maximum length of 255.
* - The servername is rejected if too long or if it contains zeros,
* in which case an fatal alert is generated.
* - The servername field is maintained together with the session cache.
* - When a session is resumed, the servername call back invoked in order
* to allow the application to position itself to the right context.
* - The servername is acknowledged if it is new for a session or when
* it is identical to a previously used for the same session.
* Applications can control the behaviour. They can at any time
* set a 'desirable' servername for a new SSL object. This can be the
* case for example with HTTPS when a Host: header field is received and
* a renegotiation is requested. In this case, a possible servername
* presented in the new client hello is only acknowledged if it matches
* the value of the Host: field.
* - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
* if they provide for changing an explicit servername context for the
* session, i.e. when the session has been established with a servername
* extension.
* - On session reconnect, the servername extension may be absent.
*/
int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int servname_type;
PACKET sni, hostname;
if (!PACKET_as_length_prefixed_2(pkt, &sni)
/* ServerNameList must be at least 1 byte long. */
|| PACKET_remaining(&sni) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
/*
* Although the intent was for server_name to be extensible, RFC 4366
* was not clear about it; and so OpenSSL among other implementations,
* always and only allows a 'host_name' name types.
* RFC 6066 corrected the mistake but adding new name types
* is nevertheless no longer feasible, so act as if no other
* SNI types can exist, to simplify parsing.
*
* Also note that the RFC permits only one SNI value per type,
* i.e., we can only have a single hostname.
*/
if (!PACKET_get_1(&sni, &servname_type)
|| servname_type != TLSEXT_NAMETYPE_host_name
|| !PACKET_as_length_prefixed_2(&sni, &hostname)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
/*
* In TLSv1.2 and below the SNI is associated with the session. In TLSv1.3
* we always use the SNI value from the handshake.
*/
if (!s->hit || SSL_IS_TLS13(s)) {
if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME, SSL_R_BAD_EXTENSION);
return 0;
}
if (PACKET_contains_zero_byte(&hostname)) {
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME, SSL_R_BAD_EXTENSION);
return 0;
}
/*
* Store the requested SNI in the SSL as temporary storage.
* If we accept it, it will get stored in the SSL_SESSION as well.
*/
OPENSSL_free(s->ext.hostname);
s->ext.hostname = NULL;
if (!PACKET_strndup(&hostname, &s->ext.hostname)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
s->servername_done = 1;
} else {
/*
* In TLSv1.2 and below we should check if the SNI is consistent between
* the initial handshake and the resumption. In TLSv1.3 SNI is not
* associated with the session.
*/
s->servername_done = (s->session->ext.hostname != NULL)
&& PACKET_equal(&hostname, s->session->ext.hostname,
strlen(s->session->ext.hostname));
}
return 1;
}
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
/* Received |value| should be a valid max-fragment-length code. */
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
/*
* When doing a full handshake or a renegotiation max_fragment_len_mode will
* be TLSEXT_max_fragment_length_UNSPECIFIED
*
* In case of a resumption max_fragment_len_mode will be one of
* TLSEXT_max_fragment_length_DISABLED, TLSEXT_max_fragment_length_512,
* TLSEXT_max_fragment_length_1024, TLSEXT_max_fragment_length_2048.
* TLSEXT_max_fragment_length_4096
*
* RFC 6066: The negotiated length applies for the duration of the session
* including session resumptions.
*
* So we only set the value in case it is unspecified.
*/
if (s->session->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_UNSPECIFIED)
/*
* Store it in session, so it'll become binding for us
* and we'll include it in a next Server Hello.
*/
s->session->ext.max_fragment_len_mode = value;
return 1;
}
#ifndef OPENSSL_NO_SRP
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET srp_I;
if (!PACKET_as_length_prefixed_1(pkt, &srp_I)
|| PACKET_contains_zero_byte(&srp_I)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
#endif
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
PACKET ec_point_format_list;
if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list)
|| PACKET_remaining(&ec_point_format_list) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit) {
if (!PACKET_memdup(&ec_point_format_list,
&s->ext.peer_ecpointformats,
&s->ext.peer_ecpointformats_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->ext.session_ticket_cb &&
!s->ext.session_ticket_cb(s, PACKET_data(pkt),
PACKET_remaining(pkt),
s->ext.session_ticket_cb_arg)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt,
ossl_unused unsigned int context,
ossl_unused X509 *x,
ossl_unused size_t chainidx)
{
PACKET supported_sig_algs;
if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
|| PACKET_remaining(&supported_sig_algs) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
return 1;
}
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET supported_sig_algs;
if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
|| PACKET_remaining(&supported_sig_algs) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_OCSP
int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
PACKET responder_id_list, exts;
/* We ignore this in a resumption handshake */
if (s->hit)
return 1;
/* Not defined if we get one of these in a client Certificate */
if (x != NULL)
return 1;
if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
/*
* We don't know what to do with any other type so ignore it.
*/
s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
return 1;
}
if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
/*
* We remove any OCSP_RESPIDs from a previous handshake
* to prevent unbounded memory growth - CVE-2016-6304
*/
sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free);
if (PACKET_remaining(&responder_id_list) > 0) {
s->ext.ocsp.ids = sk_OCSP_RESPID_new_null();
if (s->ext.ocsp.ids == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
s->ext.ocsp.ids = NULL;
}
while (PACKET_remaining(&responder_id_list) > 0) {
OCSP_RESPID *id;
PACKET responder_id;
const unsigned char *id_data;
if (!PACKET_get_length_prefixed_2(&responder_id_list, &responder_id)
|| PACKET_remaining(&responder_id) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
id_data = PACKET_data(&responder_id);
id = d2i_OCSP_RESPID(NULL, &id_data,
(int)PACKET_remaining(&responder_id));
if (id == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (id_data != PACKET_end(&responder_id)) {
OCSP_RESPID_free(id);
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) {
OCSP_RESPID_free(id);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
/* Read in request_extensions */
if (!PACKET_as_length_prefixed_2(pkt, &exts)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (PACKET_remaining(&exts) > 0) {
const unsigned char *ext_data = PACKET_data(&exts);
sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts,
X509_EXTENSION_free);
s->ext.ocsp.exts =
d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts));
if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
}
return 1;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
/*
* We shouldn't accept this extension on a
* renegotiation.
*/
if (SSL_IS_FIRST_HANDSHAKE(s))
s->s3.npn_seen = 1;
return 1;
}
#endif
/*
* Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN
* extension, not including type and length. Returns: 1 on success, 0 on error.
*/
int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET protocol_list, save_protocol_list, protocol;
if (!SSL_IS_FIRST_HANDSHAKE(s))
return 1;
if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
|| PACKET_remaining(&protocol_list) < 2) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
save_protocol_list = protocol_list;
do {
/* Protocol names can't be empty. */
if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol)
|| PACKET_remaining(&protocol) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
} while (PACKET_remaining(&protocol_list) != 0);
OPENSSL_free(s->s3.alpn_proposed);
s->s3.alpn_proposed = NULL;
s->s3.alpn_proposed_len = 0;
if (!PACKET_memdup(&save_protocol_list,
&s->s3.alpn_proposed, &s->s3.alpn_proposed_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_SRTP
int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
unsigned int ct, mki_len, id;
int i, srtp_pref;
PACKET subpkt;
/* Ignore this if we have no SRTP profiles */
if (SSL_get_srtp_profiles(s) == NULL)
return 1;
/* Pull off the length of the cipher suite list and check it is even */
if (!PACKET_get_net_2(pkt, &ct) || (ct & 1) != 0
|| !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
srvr = SSL_get_srtp_profiles(s);
s->srtp_profile = NULL;
/* Search all profiles for a match initially */
srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
while (PACKET_remaining(&subpkt)) {
if (!PACKET_get_net_2(&subpkt, &id)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
/*
* Only look for match in profiles of higher preference than
* current match.
* If no profiles have been have been configured then this
* does nothing.
*/
for (i = 0; i < srtp_pref; i++) {
SRTP_PROTECTION_PROFILE *sprof =
sk_SRTP_PROTECTION_PROFILE_value(srvr, i);
if (sprof->id == id) {
s->srtp_profile = sprof;
srtp_pref = i;
break;
}
}
}
/* Now extract the MKI value as a sanity check, but discard it for now */
if (!PACKET_get_1(pkt, &mki_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
if (!PACKET_forward(pkt, mki_len)
|| PACKET_remaining(pkt)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_SRTP_MKI_VALUE);
return 0;
}
return 1;
}
#endif
int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
s->ext.use_etm = 1;
return 1;
}
/*
* Process a psk_kex_modes extension received in the ClientHello. |pkt| contains
* the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
*/
int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
PACKET psk_kex_modes;
unsigned int mode;
if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes)
|| PACKET_remaining(&psk_kex_modes) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
while (PACKET_get_1(&psk_kex_modes, &mode)) {
if (mode == TLSEXT_KEX_MODE_KE_DHE)
s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE;
else if (mode == TLSEXT_KEX_MODE_KE
&& (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0)
s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
}
#endif
return 1;
}
/*
* Process a key_share extension received in the ClientHello. |pkt| contains
* the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
*/
int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned int group_id;
PACKET key_share_list, encoded_pt;
const uint16_t *clntgroups, *srvrgroups;
size_t clnt_num_groups, srvr_num_groups;
int found = 0;
if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0)
return 1;
/* Sanity check */
if (s->s3.peer_tmp != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
/* Get our list of supported groups */
tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups);
/* Get the clients list of supported groups. */
tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
if (clnt_num_groups == 0) {
/*
* This can only happen if the supported_groups extension was not sent,
* because we verify that the length is non-zero when we process that
* extension.
*/
SSLfatal(s, SSL_AD_MISSING_EXTENSION,
SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION);
return 0;
}
if (s->s3.group_id != 0 && PACKET_remaining(&key_share_list) == 0) {
/*
* If we set a group_id already, then we must have sent an HRR
* requesting a new key_share. If we haven't got one then that is an
* error
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
while (PACKET_remaining(&key_share_list) > 0) {
if (!PACKET_get_net_2(&key_share_list, &group_id)
|| !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt)
|| PACKET_remaining(&encoded_pt) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
/*
* If we already found a suitable key_share we loop through the
* rest to verify the structure, but don't process them.
*/
if (found)
continue;
/*
* If we sent an HRR then the key_share sent back MUST be for the group
* we requested, and must be the only key_share sent.
*/
if (s->s3.group_id != 0
&& (group_id != s->s3.group_id
|| PACKET_remaining(&key_share_list) != 0)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Check if this share is in supported_groups sent from client */
if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Check if this share is for a group we can use */
if (!check_in_list(s, group_id, srvrgroups, srvr_num_groups, 1)
|| !tls_group_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)
/*
* We tolerate but ignore a group id that we don't think is
* suitable for TLSv1.3
*/
|| !tls_valid_group(s, group_id, TLS1_3_VERSION, TLS1_3_VERSION,
0, NULL)) {
/* Share not suitable */
continue;
}
if ((s->s3.peer_tmp = ssl_generate_param_group(s, group_id)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
return 0;
}
s->s3.group_id = group_id;
/* Cache the selected group ID in the SSL_SESSION */
s->session->kex_group = group_id;
if (tls13_set_encoded_pub_key(s->s3.peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt)) <= 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT);
return 0;
}
found = 1;
}
#endif
return 1;
}
int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned int format, version, key_share, group_id;
EVP_MD_CTX *hctx;
EVP_PKEY *pkey;
PACKET cookie, raw, chhash, appcookie;
WPACKET hrrpkt;
const unsigned char *data, *mdin, *ciphdata;
unsigned char hmac[SHA256_DIGEST_LENGTH];
unsigned char hrr[MAX_HRR_SIZE];
size_t rawlen, hmaclen, hrrlen, ciphlen;
uint64_t tm, now;
/* Ignore any cookie if we're not set up to verify it */
if (s->ctx->verify_stateless_cookie_cb == NULL
|| (s->s3.flags & TLS1_FLAGS_STATELESS) == 0)
return 1;
if (!PACKET_as_length_prefixed_2(pkt, &cookie)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
raw = cookie;
data = PACKET_data(&raw);
rawlen = PACKET_remaining(&raw);
if (rawlen < SHA256_DIGEST_LENGTH
|| !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
mdin = PACKET_data(&raw);
/* Verify the HMAC of the cookie */
hctx = EVP_MD_CTX_create();
pkey = EVP_PKEY_new_raw_private_key_ex(s->ctx->libctx, "HMAC",
s->ctx->propq,
s->session_ctx->ext.cookie_hmac_key,
sizeof(s->session_ctx->ext.cookie_hmac_key));
if (hctx == NULL || pkey == NULL) {
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
hmaclen = SHA256_DIGEST_LENGTH;
if (EVP_DigestSignInit_ex(hctx, NULL, "SHA2-256", s->ctx->libctx,
s->ctx->propq, pkey, NULL) <= 0
|| EVP_DigestSign(hctx, hmac, &hmaclen, data,
rawlen - SHA256_DIGEST_LENGTH) <= 0
|| hmaclen != SHA256_DIGEST_LENGTH) {
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_COOKIE_MISMATCH);
return 0;
}
if (!PACKET_get_net_2(&cookie, &format)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
/* Check the cookie format is something we recognise. Ignore it if not */
if (format != COOKIE_STATE_FORMAT_VERSION)
return 1;
/*
* The rest of these checks really shouldn't fail since we have verified the
* HMAC above.
*/
/* Check the version number is sane */
if (!PACKET_get_net_2(&cookie, &version)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (version != TLS1_3_VERSION) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
return 0;
}
if (!PACKET_get_net_2(&cookie, &group_id)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
ciphdata = PACKET_data(&cookie);
if (!PACKET_forward(&cookie, 2)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (group_id != s->s3.group_id
|| s->s3.tmp.new_cipher
!= ssl_get_cipher_by_char(s, ciphdata, 0)) {
/*
* We chose a different cipher or group id this time around to what is
* in the cookie. Something must have changed.
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_CIPHER);
return 0;
}
if (!PACKET_get_1(&cookie, &key_share)
|| !PACKET_get_net_8(&cookie, &tm)
|| !PACKET_get_length_prefixed_2(&cookie, &chhash)
|| !PACKET_get_length_prefixed_1(&cookie, &appcookie)
|| PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
/* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */
now = time(NULL);
if (tm > now || (now - tm) > 600) {
/* Cookie is stale. Ignore it */
return 1;
}
/* Verify the app cookie */
if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie),
PACKET_remaining(&appcookie)) == 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_COOKIE_MISMATCH);
return 0;
}
/*
* Reconstruct the HRR that we would have sent in response to the original
* ClientHello so we can add it to the transcript hash.
* Note: This won't work with custom HRR extensions
*/
if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO)
|| !WPACKET_start_sub_packet_u24(&hrrpkt)
|| !WPACKET_put_bytes_u16(&hrrpkt, TLS1_2_VERSION)
|| !WPACKET_memcpy(&hrrpkt, hrrrandom, SSL3_RANDOM_SIZE)
|| !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id,
s->tmp_session_id_len)
|| !s->method->put_cipher_by_char(s->s3.tmp.new_cipher, &hrrpkt,
&ciphlen)
|| !WPACKET_put_bytes_u8(&hrrpkt, 0)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|| !WPACKET_put_bytes_u16(&hrrpkt, s->version)
|| !WPACKET_close(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (key_share) {
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|| !WPACKET_put_bytes_u16(&hrrpkt, s->s3.group_id)
|| !WPACKET_close(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_cookie)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|| !WPACKET_sub_memcpy_u16(&hrrpkt, data, rawlen)
|| !WPACKET_close(&hrrpkt) /* cookie extension */
|| !WPACKET_close(&hrrpkt) /* extension block */
|| !WPACKET_close(&hrrpkt) /* message */
|| !WPACKET_get_total_written(&hrrpkt, &hrrlen)
|| !WPACKET_finish(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/* Reconstruct the transcript hash */
if (!create_synthetic_message_hash(s, PACKET_data(&chhash),
PACKET_remaining(&chhash), hrr,
hrrlen)) {
/* SSLfatal() already called */
return 0;
}
/* Act as if this ClientHello came after a HelloRetryRequest */
s->hello_retry_request = SSL_HRR_PENDING;
s->ext.cookieok = 1;
#endif
return 1;
}
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
PACKET supported_groups_list;
/* Each group is 2 bytes and we must have at least 1. */
if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list)
|| PACKET_remaining(&supported_groups_list) == 0
|| (PACKET_remaining(&supported_groups_list) % 2) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit || SSL_IS_TLS13(s)) {
OPENSSL_free(s->ext.peer_supportedgroups);
s->ext.peer_supportedgroups = NULL;
s->ext.peer_supportedgroups_len = 0;
if (!tls1_save_u16(&supported_groups_list,
&s->ext.peer_supportedgroups,
&s->ext.peer_supportedgroups_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
/* The extension must always be empty */
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (s->options & SSL_OP_NO_EXTENDED_MASTER_SECRET)
return 1;
s->s3.flags |= TLS1_FLAGS_RECEIVED_EXTMS;
return 1;
}
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (s->hello_retry_request != SSL_HRR_NONE) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION);
return 0;
}
return 1;
}
static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick,
SSL_SESSION **sess)
{
SSL_SESSION *tmpsess = NULL;
s->ext.ticket_expected = 1;
switch (PACKET_remaining(tick)) {
case 0:
return SSL_TICKET_EMPTY;
case SSL_MAX_SSL_SESSION_ID_LENGTH:
break;
default:
return SSL_TICKET_NO_DECRYPT;
}
tmpsess = lookup_sess_in_cache(s, PACKET_data(tick),
SSL_MAX_SSL_SESSION_ID_LENGTH);
if (tmpsess == NULL)
return SSL_TICKET_NO_DECRYPT;
*sess = tmpsess;
return SSL_TICKET_SUCCESS;
}
int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET identities, binders, binder;
size_t binderoffset, hashsize;
SSL_SESSION *sess = NULL;
unsigned int id, i, ext = 0;
const EVP_MD *md = NULL;
/*
* If we have no PSK kex mode that we recognise then we can't resume so
* ignore this extension
*/
if ((s->ext.psk_kex_mode
& (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0)
return 1;
if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
s->ext.ticket_expected = 0;
for (id = 0; PACKET_remaining(&identities) != 0; id++) {
PACKET identity;
unsigned long ticket_agel;
size_t idlen;
if (!PACKET_get_length_prefixed_2(&identities, &identity)
|| !PACKET_get_net_4(&identities, &ticket_agel)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
idlen = PACKET_remaining(&identity);
if (s->psk_find_session_cb != NULL
&& !s->psk_find_session_cb(s, PACKET_data(&identity), idlen,
&sess)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
#ifndef OPENSSL_NO_PSK
if(sess == NULL
&& s->psk_server_callback != NULL
&& idlen <= PSK_MAX_IDENTITY_LEN) {
char *pskid = NULL;
unsigned char pskdata[PSK_MAX_PSK_LEN];
unsigned int pskdatalen;
if (!PACKET_strndup(&identity, &pskid)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
pskdatalen = s->psk_server_callback(s, pskid, pskdata,
sizeof(pskdata));
OPENSSL_free(pskid);
if (pskdatalen > PSK_MAX_PSK_LEN) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
} else if (pskdatalen > 0) {
const SSL_CIPHER *cipher;
const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
/*
* We found a PSK using an old style callback. We don't know
* the digest so we default to SHA256 as per the TLSv1.3 spec
*/
cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
if (cipher == NULL) {
OPENSSL_cleanse(pskdata, pskdatalen);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
sess = SSL_SESSION_new();
if (sess == NULL
|| !SSL_SESSION_set1_master_key(sess, pskdata,
pskdatalen)
|| !SSL_SESSION_set_cipher(sess, cipher)
|| !SSL_SESSION_set_protocol_version(sess,
TLS1_3_VERSION)) {
OPENSSL_cleanse(pskdata, pskdatalen);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_cleanse(pskdata, pskdatalen);
}
}
#endif /* OPENSSL_NO_PSK */
if (sess != NULL) {
/* We found a PSK */
SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);
if (sesstmp == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ goto err;
}
SSL_SESSION_free(sess);
sess = sesstmp;
/*
* We've just been told to use this session for this context so
* make sure the sid_ctx matches up.
*/
memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
sess->sid_ctx_length = s->sid_ctx_length;
ext = 1;
if (id == 0)
s->ext.early_data_ok = 1;
s->ext.ticket_expected = 1;
} else {
uint32_t ticket_age = 0, agesec, agems;
int ret;
/*
* If we are using anti-replay protection then we behave as if
* SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
* is no point in using full stateless tickets.
*/
if ((s->options & SSL_OP_NO_TICKET) != 0
|| (s->max_early_data > 0
&& (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))
ret = tls_get_stateful_ticket(s, &identity, &sess);
else
ret = tls_decrypt_ticket(s, PACKET_data(&identity),
PACKET_remaining(&identity), NULL, 0,
&sess);
if (ret == SSL_TICKET_EMPTY) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (ret == SSL_TICKET_FATAL_ERR_MALLOC
|| ret == SSL_TICKET_FATAL_ERR_OTHER) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (ret == SSL_TICKET_NONE || ret == SSL_TICKET_NO_DECRYPT)
continue;
/* Check for replay */
if (s->max_early_data > 0
&& (s->options & SSL_OP_NO_ANTI_REPLAY) == 0
&& !SSL_CTX_remove_session(s->session_ctx, sess)) {
SSL_SESSION_free(sess);
sess = NULL;
continue;
}
ticket_age = (uint32_t)ticket_agel;
agesec = (uint32_t)(time(NULL) - sess->time);
agems = agesec * (uint32_t)1000;
ticket_age -= sess->ext.tick_age_add;
/*
* For simplicity we do our age calculations in seconds. If the
* client does it in ms then it could appear that their ticket age
* is longer than ours (our ticket age calculation should always be
* slightly longer than the client's due to the network latency).
* Therefore we add 1000ms to our age calculation to adjust for
* rounding errors.
*/
if (id == 0
&& sess->timeout >= (long)agesec
&& agems / (uint32_t)1000 == agesec
&& ticket_age <= agems + 1000
&& ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
/*
* Ticket age is within tolerance and not expired. We allow it
* for early data
*/
s->ext.early_data_ok = 1;
}
}
md = ssl_md(s->ctx, sess->cipher->algorithm2);
if (md == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!EVP_MD_is_a(md,
EVP_MD_get0_name(ssl_md(s->ctx,
s->s3.tmp.new_cipher->algorithm2)))) {
/* The ciphersuite is not compatible with this session. */
SSL_SESSION_free(sess);
sess = NULL;
s->ext.early_data_ok = 0;
s->ext.ticket_expected = 0;
continue;
}
break;
}
if (sess == NULL)
return 1;
binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data;
hashsize = EVP_MD_get_size(md);
if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
goto err;
}
for (i = 0; i <= id; i++) {
if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
goto err;
}
}
if (PACKET_remaining(&binder) != hashsize) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
goto err;
}
if (tls_psk_do_binder(s, md, (const unsigned char *)s->init_buf->data,
binderoffset, PACKET_data(&binder), NULL, sess, 0,
ext) != 1) {
/* SSLfatal() already called */
goto err;
}
s->ext.tick_identity = id;
SSL_SESSION_free(s->session);
s->session = sess;
return 1;
err:
SSL_SESSION_free(sess);
return 0;
}
int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt,
ossl_unused unsigned int context,
ossl_unused X509 *x,
ossl_unused size_t chainidx)
{
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR);
return 0;
}
s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
return 1;
}
/*
* Add the server's renegotiation binding
*/
EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!s->s3.send_connection_binding)
return EXT_RETURN_NOT_SENT;
/* Still add this even if SSL_OP_NO_RENEGOTIATION is set */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)
|| !WPACKET_memcpy(pkt, s->s3.previous_client_finished,
s->s3.previous_client_finished_len)
|| !WPACKET_memcpy(pkt, s->s3.previous_server_finished,
s->s3.previous_server_finished_len)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (s->servername_done != 1)
return EXT_RETURN_NOT_SENT;
/*
* Prior to TLSv1.3 we ignore any SNI in the current handshake if resuming.
* We just use the servername from the initial handshake.
*/
if (s->hit && !SSL_IS_TLS13(s))
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
/* Add/include the server's max fragment len extension into ServerHello */
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
return EXT_RETURN_NOT_SENT;
/*-
* 4 bytes for this extension type and extension length
* 1 byte for the Max Fragment Length code value.
*/
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
unsigned long alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
unsigned long alg_a = s->s3.tmp.new_cipher->algorithm_auth;
int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))
&& (s->ext.peer_ecpointformats != NULL);
const unsigned char *plist;
size_t plistlen;
if (!using_ecc)
return EXT_RETURN_NOT_SENT;
tls1_get_formatlist(s, &plist, &plistlen);
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const uint16_t *groups;
size_t numgroups, i, first = 1;
int version;
/* s->s3.group_id is non zero if we accepted a key_share */
if (s->s3.group_id == 0)
return EXT_RETURN_NOT_SENT;
/* Get our list of supported groups */
tls1_get_supported_groups(s, &groups, &numgroups);
if (numgroups == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* Copy group ID if supported */
version = SSL_version(s);
for (i = 0; i < numgroups; i++) {
uint16_t group = groups[i];
if (tls_valid_group(s, group, version, version, 0, NULL)
&& tls_group_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) {
if (first) {
/*
* Check if the client is already using our preferred group. If
* so we don't need to add this extension
*/
if (s->s3.group_id == group)
return EXT_RETURN_NOT_SENT;
/* Add extension header */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
/* Sub-packet for supported_groups extension */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
first = 0;
}
if (!WPACKET_put_bytes_u16(pkt, group)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!s->ext.ticket_expected || !tls_use_ticket(s)) {
s->ext.ticket_expected = 0;
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_OCSP
EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
/* We don't currently support this extension inside a CertificateRequest */
if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST)
return EXT_RETURN_NOT_SENT;
if (!s->ext.status_expected)
return EXT_RETURN_NOT_SENT;
if (SSL_IS_TLS13(s) && chainidx != 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/*
* In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we
* send back an empty extension, with the certificate status appearing as a
* separate message
*/
if (SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const unsigned char *npa;
unsigned int npalen;
int ret;
int npn_seen = s->s3.npn_seen;
s->s3.npn_seen = 0;
if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL)
return EXT_RETURN_NOT_SENT;
ret = s->ctx->ext.npn_advertised_cb(s, &npa, &npalen,
s->ctx->ext.npn_advertised_cb_arg);
if (ret == SSL_TLSEXT_ERR_OK) {
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|| !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->s3.npn_seen = 1;
return EXT_RETURN_SENT;
}
return EXT_RETURN_NOT_SENT;
}
#endif
EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->s3.alpn_selected == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt,
TLSEXT_TYPE_application_layer_protocol_negotiation)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u8(pkt, s->s3.alpn_selected,
s->s3.alpn_selected_len)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_SRTP
EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (s->srtp_profile == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, 2)
|| !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
|| !WPACKET_put_bytes_u8(pkt, 0)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (!s->ext.use_etm)
return EXT_RETURN_NOT_SENT;
/*
* Don't use encrypt_then_mac if AEAD or RC4 might want to disable
* for other cases too.
*/
if (s->s3.tmp.new_cipher->algorithm_mac == SSL_AEAD
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_RC4
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_MAGMA
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_KUZNYECHIK) {
s->ext.use_etm = 0;
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if ((s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!ossl_assert(SSL_IS_TLS13(s))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->version)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned char *encodedPoint;
size_t encoded_pt_len = 0;
EVP_PKEY *ckey = s->s3.peer_tmp, *skey = NULL;
const TLS_GROUP_INFO *ginf = NULL;
if (s->hello_retry_request == SSL_HRR_PENDING) {
if (ckey != NULL) {
/* Original key_share was acceptable so don't ask for another one */
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->s3.group_id)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
if (ckey == NULL) {
/* No key_share received from client - must be resuming */
if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_NOT_SENT;
}
if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) {
/*
* PSK ('hit') and explicitly not doing DHE (if the client sent the
* DHE option we always take it); don't send key share.
*/
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->s3.group_id)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if ((ginf = tls1_group_id_lookup(s->ctx, s->s3.group_id)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (!ginf->is_kem) {
/* Regular KEX */
skey = ssl_generate_pkey(s, ckey);
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return EXT_RETURN_FAIL;
}
/* Generate encoding of server key */
encoded_pt_len = EVP_PKEY_get1_encoded_public_key(skey, &encodedPoint);
if (encoded_pt_len == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB);
EVP_PKEY_free(skey);
return EXT_RETURN_FAIL;
}
if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
EVP_PKEY_free(skey);
OPENSSL_free(encodedPoint);
return EXT_RETURN_FAIL;
}
OPENSSL_free(encodedPoint);
/*
* This causes the crypto state to be updated based on the derived keys
*/
s->s3.tmp.pkey = skey;
if (ssl_derive(s, skey, ckey, 1) == 0) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
} else {
/* KEM mode */
unsigned char *ct = NULL;
size_t ctlen = 0;
/*
* This does not update the crypto state.
*
* The generated pms is stored in `s->s3.tmp.pms` to be later used via
* ssl_gensecret().
*/
if (ssl_encapsulate(s, ckey, &ct, &ctlen, 0) == 0) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
if (ctlen == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
OPENSSL_free(ct);
return EXT_RETURN_FAIL;
}
if (!WPACKET_sub_memcpy_u16(pkt, ct, ctlen)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
OPENSSL_free(ct);
return EXT_RETURN_FAIL;
}
OPENSSL_free(ct);
/*
* This causes the crypto state to be updated based on the generated pms
*/
if (ssl_gensecret(s, s->s3.tmp.pms, s->s3.tmp.pmslen) == 0) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
}
s->s3.did_kex = 1;
return EXT_RETURN_SENT;
#else
return EXT_RETURN_FAIL;
#endif
}
EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie;
unsigned char *hmac, *hmac2;
size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen;
EVP_MD_CTX *hctx;
EVP_PKEY *pkey;
int ret = EXT_RETURN_FAIL;
if ((s->s3.flags & TLS1_FLAGS_STATELESS) == 0)
return EXT_RETURN_NOT_SENT;
if (s->ctx->gen_stateless_cookie_cb == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_COOKIE_CALLBACK_SET);
return EXT_RETURN_FAIL;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_get_total_written(pkt, &startlen)
|| !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie)
|| !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION)
|| !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION)
|| !WPACKET_put_bytes_u16(pkt, s->s3.group_id)
|| !s->method->put_cipher_by_char(s->s3.tmp.new_cipher, pkt,
&ciphlen)
/* Is there a key_share extension present in this HRR? */
|| !WPACKET_put_bytes_u8(pkt, s->s3.peer_tmp == NULL)
|| !WPACKET_put_bytes_u64(pkt, time(NULL))
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/*
* Get the hash of the initial ClientHello. ssl_handshake_hash() operates
* on raw buffers, so we first reserve sufficient bytes (above) and then
* subsequently allocate them (below)
*/
if (!ssl3_digest_cached_records(s, 0)
|| !ssl_handshake_hash(s, hashval1, EVP_MAX_MD_SIZE, &hashlen)) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
if (!WPACKET_allocate_bytes(pkt, hashlen, &hashval2)
|| !ossl_assert(hashval1 == hashval2)
|| !WPACKET_close(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)
|| !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* Generate the application cookie */
if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
return EXT_RETURN_FAIL;
}
if (!WPACKET_allocate_bytes(pkt, appcookielen, &appcookie2)
|| !ossl_assert(appcookie1 == appcookie2)
|| !WPACKET_close(pkt)
|| !WPACKET_get_total_written(pkt, &totcookielen)
|| !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
hmaclen = SHA256_DIGEST_LENGTH;
totcookielen -= startlen;
if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* HMAC the cookie */
hctx = EVP_MD_CTX_create();
pkey = EVP_PKEY_new_raw_private_key_ex(s->ctx->libctx, "HMAC",
s->ctx->propq,
s->session_ctx->ext.cookie_hmac_key,
sizeof(s->session_ctx->ext.cookie_hmac_key));
if (hctx == NULL || pkey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_DigestSignInit_ex(hctx, NULL, "SHA2-256", s->ctx->libctx,
s->ctx->propq, pkey, NULL) <= 0
|| EVP_DigestSign(hctx, hmac, &hmaclen, cookie,
totcookielen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!WPACKET_allocate_bytes(pkt, hmaclen, &hmac2)
|| !ossl_assert(hmac == hmac2)
|| !ossl_assert(cookie == hmac - totcookielen)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
ret = EXT_RETURN_SENT;
err:
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
return ret;
#else
return EXT_RETURN_FAIL;
#endif
}
EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const unsigned char cryptopro_ext[36] = {
0xfd, 0xe8, /* 65000 */
0x00, 0x20, /* 32 bytes length */
0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
};
if (((s->s3.tmp.new_cipher->id & 0xFFFF) != 0x80
&& (s->s3.tmp.new_cipher->id & 0xFFFF) != 0x81)
|| (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
if (s->max_early_data == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u32(pkt, s->max_early_data)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (!s->hit)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->ext.tick_identity)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
diff --git a/crypto/openssl/ssl/statem/statem_srvr.c b/crypto/openssl/ssl/statem/statem_srvr.c
index df7c868eff71..7d7c198bd63f 100644
--- a/crypto/openssl/ssl/statem/statem_srvr.c
+++ b/crypto/openssl/ssl/statem/statem_srvr.c
@@ -1,4137 +1,4137 @@
/*
- * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 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 Apache License 2.0 (the "License"). You may not 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_local.h"
#include "statem_local.h"
#include "internal/constant_time.h"
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/dh.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/trace.h>
#include <openssl/core_names.h>
#include <openssl/asn1t.h>
#define TICKET_NONCE_SIZE 8
typedef struct {
ASN1_TYPE *kxBlob;
ASN1_TYPE *opaqueBlob;
} GOST_KX_MESSAGE;
DECLARE_ASN1_FUNCTIONS(GOST_KX_MESSAGE)
ASN1_SEQUENCE(GOST_KX_MESSAGE) = {
ASN1_SIMPLE(GOST_KX_MESSAGE, kxBlob, ASN1_ANY),
ASN1_OPT(GOST_KX_MESSAGE, opaqueBlob, ASN1_ANY),
} ASN1_SEQUENCE_END(GOST_KX_MESSAGE)
IMPLEMENT_ASN1_FUNCTIONS(GOST_KX_MESSAGE)
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_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_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, 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;
}
if (s->ext.extra_tickets_expected > 0) {
st->hand_state = TLS_ST_SW_SESSION_TICKET;
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:
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 (!SSL_IS_FIRST_HANDSHAKE(s) && s->ext.extra_tickets_expected > 0) {
return WRITE_TRAN_CONTINUE;
} else 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, 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
&& s->ext.extra_tickets_expected == 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;
/* Writes to s->session are only safe for initial handshakes */
if (s->session->cipher == NULL) {
s->session->cipher = s->s3.tmp.new_cipher;
} else if (s->session->cipher != s->s3.tmp.new_cipher) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
if (!s->method->ssl3_enc->setup_key_block(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
if (SSL_IS_DTLS(s)) {
/*
* We're into the last flight. We don't retransmit the last flight
* unless we need to, so we don't use the timer. This might have
* already been set to 0 if we sent a NewSessionTicket message,
* but we'll set it again here in case we didn't.
*/
st->use_timer = 0;
}
return WORK_FINISHED_CONTINUE;
case TLS_ST_EARLY_DATA:
if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING
&& (s->s3.flags & TLS1_FLAGS_STATELESS) == 0)
return WORK_FINISHED_CONTINUE;
/* Fall through */
case TLS_ST_OK:
/* Calls SSLfatal() as required */
return tls_finish_handshake(s, wst, 1, 1);
}
return WORK_FINISHED_CONTINUE;
}
static ossl_inline int conn_is_closed(void)
{
switch (get_last_sys_error()) {
#if defined(EPIPE)
case EPIPE:
return 1;
#endif
#if defined(ECONNRESET)
case ECONNRESET:
return 1;
#endif
#if defined(WSAECONNRESET)
case WSAECONNRESET:
return 1;
#endif
default:
return 0;
}
}
/*
* Perform any work that needs to be done after sending a message from the
* server to the client.
*/
WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
s->init_num = 0;
switch (st->hand_state) {
default:
/* No post work to be done */
break;
case TLS_ST_SW_HELLO_REQ:
if (statem_flush(s) != 1)
return WORK_MORE_A;
if (!ssl3_init_finished_mac(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
break;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
if (statem_flush(s) != 1)
return WORK_MORE_A;
/* HelloVerifyRequest resets Finished MAC */
if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
/*
* The next message should be another ClientHello which we need to
* treat like it was the first packet
*/
s->first_packet = 1;
break;
case TLS_ST_SW_SRVR_HELLO:
if (SSL_IS_TLS13(s) && s->hello_retry_request == SSL_HRR_PENDING) {
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
&& statem_flush(s) != 1)
return WORK_MORE_A;
break;
}
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && s->hit) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
size_t labellen;
/*
* Add new shared key for SCTP-Auth, will be ignored if no
* SCTP used.
*/
memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
sizeof(DTLS1_SCTP_AUTH_LABEL));
/* Don't include the terminating zero. */
labellen = sizeof(labelbuffer) - 1;
if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
labellen += 1;
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0,
0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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)) {
/* TLS 1.3 gets the secret size from the handshake md */
size_t dummy;
if (!s->method->ssl3_enc->generate_master_secret(s,
s->master_secret, s->handshake_secret, 0,
&dummy)
|| !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_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, 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, 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_R_PSK_IDENTITY_NOT_FOUND);
return -1;
} else {
ret = ssl_srp_server_param_with_username_intern(s, &al);
if (ret < 0)
return 0;
if (ret == SSL3_AL_FATAL) {
SSLfatal(s, al,
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 > DTLS1_COOKIE_LENGTH) {
SSLfatal(s, SSL_AD_NO_ALERT, 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, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
/*-
* 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);
}
#define RENEG_OPTIONS_OK(options) \
((options & SSL_OP_NO_RENEGOTIATION) == 0 \
&& (options & SSL_OP_ALLOW_CLIENT_RENEGOTIATION) != 0)
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, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!RENEG_OPTIONS_OK(s->options)
|| (!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, 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_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, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, 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_R_RECORD_LENGTH_MISMATCH);
goto err;
}
if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, 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_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, 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_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_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, ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* If we require cookies and this ClientHello doesn't contain one,
* just return since we do not want to allocate any memory yet.
* So check cookie length...
*/
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
if (clienthello->dtls_cookie_len == 0) {
OPENSSL_free(clienthello);
return MSG_PROCESS_FINISHED_READING;
}
}
}
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, 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_R_LENGTH_MISMATCH);
goto err;
}
}
}
if (!PACKET_copy_all(&compression, clienthello->compressions,
MAX_COMPRESSIONS_SIZE,
&clienthello->compressions_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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_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_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, 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_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_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_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, 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_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_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_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_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.
* 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;
OSSL_TRACE_BEGIN(TLS_CIPHER) {
BIO_printf(trc_out, "client sent %d ciphers\n",
sk_SSL_CIPHER_num(ciphers));
}
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
c = sk_SSL_CIPHER_value(ciphers, i);
if (trc_out != NULL)
BIO_printf(trc_out, "client [%2d of %2d]:%s\n", i,
sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c));
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_R_REQUIRED_CIPHER_MISSING);
OSSL_TRACE_CANCEL(TLS_CIPHER);
goto err;
}
OSSL_TRACE_END(TLS_CIPHER);
}
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_R_NO_COMPRESSION_SPECIFIED);
goto err;
}
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
ssl_check_for_safari(s, clienthello);
/* 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, 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->peer_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->peer_ciphers,
SSL_get_ciphers(s));
if (pref_cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, 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->peer_ciphers);
sk_SSL_CIPHER_free(s->cipher_list_by_id);
s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->peer_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_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_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_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_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_R_INCONSISTENT_COMPRESSION);
goto err;
}
#endif
/*
* Given s->peer_ciphers and SSL_get_ciphers, we must pick a cipher
*/
if (!s->hit || SSL_IS_TLS13(s)) {
sk_SSL_CIPHER_free(s->peer_ciphers);
s->peer_ciphers = ciphers;
if (ciphers == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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_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) {
s->s3.alpn_selected_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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,
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,
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_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_R_CERT_CB_ERROR);
goto err;
}
if (rv < 0) {
s->rwstate = SSL_X509_LOOKUP;
return WORK_MORE_B;
}
s->rwstate = SSL_NOTHING;
}
/* In TLSv1.3 we selected the ciphersuite before resumption */
if (!SSL_IS_TLS13(s)) {
cipher =
ssl3_choose_cipher(s, s->peer_ciphers, SSL_get_ciphers(s));
if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
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, 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->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, 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, 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)
{
EVP_PKEY *pkdh = NULL;
unsigned char *encodedPoint = NULL;
size_t encodedlen = 0;
int curve_id = 0;
const SIGALG_LOOKUP *lu = s->s3.tmp.sigalg;
int i;
unsigned long type;
BIGNUM *r[4];
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
EVP_PKEY_CTX *pctx = NULL;
size_t paramlen, paramoffset;
int freer = 0, ret = 0;
if (!WPACKET_get_total_written(pkt, &paramoffset)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (md_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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 */
if (type & (SSL_kDHE | SSL_kDHEPSK)) {
CERT *cert = s->cert;
EVP_PKEY *pkdhp = NULL;
if (s->cert->dh_tmp_auto) {
pkdh = ssl_get_auto_dh(s);
if (pkdh == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
pkdhp = pkdh;
} else {
pkdhp = cert->dh_tmp;
}
#if !defined(OPENSSL_NO_DEPRECATED_3_0)
if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) {
pkdh = ssl_dh_to_pkey(s->cert->dh_tmp_cb(s, 0, 1024));
if (pkdh == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
pkdhp = pkdh;
}
#endif
if (pkdhp == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (!ssl_security(s, SSL_SECOP_TMP_DH,
EVP_PKEY_get_security_bits(pkdhp), 0, pkdhp)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_DH_KEY_TOO_SMALL);
goto err;
}
if (s->s3.tmp.pkey != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
s->s3.tmp.pkey = ssl_generate_pkey(s, pkdhp);
if (s->s3.tmp.pkey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_PKEY_free(pkdh);
pkdh = NULL;
/* These BIGNUMs need to be freed when we're finished */
freer = 1;
if (!EVP_PKEY_get_bn_param(s->s3.tmp.pkey, OSSL_PKEY_PARAM_FFC_P,
&r[0])
|| !EVP_PKEY_get_bn_param(s->s3.tmp.pkey, OSSL_PKEY_PARAM_FFC_G,
&r[1])
|| !EVP_PKEY_get_bn_param(s->s3.tmp.pkey,
OSSL_PKEY_PARAM_PUB_KEY, &r[2])) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
} else if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
if (s->s3.tmp.pkey != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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_R_UNSUPPORTED_ELLIPTIC_CURVE);
goto err;
}
/* Cache the group used in the SSL_SESSION */
s->session->kex_group = curve_id;
/* Generate a new key for this curve */
s->s3.tmp.pkey = ssl_generate_pkey_group(s, curve_id);
if (s->s3.tmp.pkey == NULL) {
/* SSLfatal() already called */
goto err;
}
/* Encode the public key. */
encodedlen = EVP_PKEY_get1_encoded_public_key(s->s3.tmp.pkey,
&encodedPoint);
if (encodedlen == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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
#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_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_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, 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, 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, ERR_R_INTERNAL_ERROR);
goto err;
}
/*-
* 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, ERR_R_INTERNAL_ERROR);
goto err;
}
memset(binval, 0, len);
}
}
if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
BN_bn2bin(r[i], binval);
}
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, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(encodedPoint);
encodedPoint = NULL;
}
/* 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 = 0, tbslen;
if (pkey == NULL || !tls1_lookup_md(s->ctx, lu, &md)) {
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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, 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, ERR_R_INTERNAL_ERROR);
goto err;
}
if (EVP_DigestSignInit_ex(md_ctx, &pctx,
md == NULL ? NULL : EVP_MD_get0_name(md),
s->ctx->libctx, s->ctx->propq, pkey,
NULL) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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, 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;
}
if (EVP_DigestSign(md_ctx, NULL, &siglen, tbs, tbslen) <=0
|| !WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
|| EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen) <= 0
|| !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
|| sigbytes1 != sigbytes2) {
OPENSSL_free(tbs);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(tbs);
}
ret = 1;
err:
EVP_PKEY_free(pkdh);
OPENSSL_free(encodedPoint);
EVP_MD_CTX_free(md_ctx);
if (freer) {
BN_free(r[0]);
BN_free(r[1]);
BN_free(r[2]);
BN_free(r[3]);
}
return ret;
}
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) {
s->pha_context_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (RAND_bytes_ex(s->ctx->libctx, s->pha_context,
s->pha_context_len, 0) <= 0
|| !WPACKET_sub_memcpy_u8(pkt, s->pha_context,
s->pha_context_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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, 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, 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, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (!construct_ca_names(s, get_ca_names(s), pkt)) {
/* SSLfatal() already called */
return 0;
}
done:
s->certreqs_sent++;
s->s3.tmp.cert_request = 1;
return 1;
}
static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_PSK
unsigned char psk[PSK_MAX_PSK_LEN];
size_t psklen;
PACKET psk_identity;
if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
if (s->psk_server_callback == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PSK_NO_SERVER_CB);
return 0;
}
if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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, 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_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) {
s->s3.tmp.psklen = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
s->s3.tmp.psklen = psklen;
return 1;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
{
size_t outlen;
PACKET enc_premaster;
EVP_PKEY *rsa = NULL;
unsigned char *rsa_decrypt = NULL;
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM params[3], *p = params;
rsa = s->cert->pkeys[SSL_PKEY_RSA].privatekey;
if (rsa == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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_R_LENGTH_MISMATCH);
return 0;
}
}
outlen = SSL_MAX_MASTER_KEY_LENGTH;
rsa_decrypt = OPENSSL_malloc(outlen);
if (rsa_decrypt == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, rsa, s->ctx->propq);
if (ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* 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). We use the special padding type
* RSA_PKCS1_WITH_TLS_PADDING to do that. It will automaticaly decrypt the
* RSA, check the padding and check that the client version is as expected
* in the premaster secret. If any of that fails then the function appears
* to return successfully but with a random result. The call below could
* still fail if the input is publicly invalid.
* See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
*/
if (EVP_PKEY_decrypt_init(ctx) <= 0
|| EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_WITH_TLS_PADDING) <= 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
*p++ = OSSL_PARAM_construct_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION,
(unsigned int *)&s->client_version);
if ((s->options & SSL_OP_TLS_ROLLBACK_BUG) != 0)
*p++ = OSSL_PARAM_construct_uint(
OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION,
(unsigned int *)&s->version);
*p++ = OSSL_PARAM_construct_end();
if (!EVP_PKEY_CTX_set_params(ctx, params)
|| EVP_PKEY_decrypt(ctx, rsa_decrypt, &outlen,
PACKET_data(&enc_premaster),
PACKET_remaining(&enc_premaster)) <= 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
/*
* This test should never fail (otherwise we should have failed above) but
* we double check anyway.
*/
if (outlen != SSL_MAX_MASTER_KEY_LENGTH) {
OPENSSL_cleanse(rsa_decrypt, SSL_MAX_MASTER_KEY_LENGTH);
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
/* Also cleanses rsa_decrypt (on success or failure) */
if (!ssl_generate_master_secret(s, rsa_decrypt,
SSL_MAX_MASTER_KEY_LENGTH, 0)) {
/* SSLfatal() already called */
goto err;
}
ret = 1;
err:
OPENSSL_free(rsa_decrypt);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int tls_process_cke_dhe(SSL *s, PACKET *pkt)
{
EVP_PKEY *skey = NULL;
unsigned int i;
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_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
goto err;
}
skey = s->s3.tmp.pkey;
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (PACKET_remaining(pkt) == 0L) {
SSLfatal(s, SSL_AD_DECODE_ERROR, 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, 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_R_COPY_PARAMETERS_FAILED);
goto err;
}
if (!EVP_PKEY_set1_encoded_public_key(ckey, data, i)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
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;
}
static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
{
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_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_R_LENGTH_MISMATCH);
goto err;
}
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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_R_COPY_PARAMETERS_FAILED);
goto err;
}
if (EVP_PKEY_set1_encoded_public_key(ckey, data, i) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
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;
}
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_R_BAD_SRP_A_LENGTH);
return 0;
}
if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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_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, 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, 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;
GOST_KX_MESSAGE *pKX = NULL;
const unsigned char *ptr;
int ret = 0;
/* 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_from_pkey(s->ctx->libctx, pk, s->ctx->propq);
if (pkey_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* 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();
}
ptr = PACKET_data(pkt);
/* Some implementations provide extra data in the opaqueBlob
* We have nothing to do with this blob so we just skip it */
pKX = d2i_GOST_KX_MESSAGE(NULL, &ptr, PACKET_remaining(pkt));
if (pKX == NULL
|| pKX->kxBlob == NULL
|| ASN1_TYPE_get(pKX->kxBlob) != V_ASN1_SEQUENCE) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (!PACKET_forward(pkt, ptr - PACKET_data(pkt))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
inlen = pKX->kxBlob->value.sequence->length;
start = pKX->kxBlob->value.sequence->data;
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
inlen) <= 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, 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);
GOST_KX_MESSAGE_free(pKX);
return ret;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_gost18(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_GOST
unsigned char rnd_dgst[32];
EVP_PKEY_CTX *pkey_ctx = NULL;
EVP_PKEY *pk = NULL;
unsigned char premaster_secret[32];
const unsigned char *start = NULL;
size_t outlen = 32, inlen = 0;
int ret = 0;
int cipher_nid = ossl_gost18_cke_cipher_nid(s);
if (cipher_nid == NID_undef) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (ossl_gost_ukm(s, rnd_dgst) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* Get our certificate private key */
pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey != NULL ?
s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey :
s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
if (pk == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_STATE);
goto err;
}
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pk, s->ctx->propq);
if (pkey_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code depending on size */
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
goto err;
}
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
goto err;
}
inlen = PACKET_remaining(pkt);
start = PACKET_data(pkt);
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, 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;
}
ret = 1;
err:
EVP_PKEY_CTX_free(pkey_ctx);
return ret;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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_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 if (alg_k & SSL_kGOST18) {
if (!tls_process_cke_gost18(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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;
s->s3.tmp.psklen = 0;
#endif
return MSG_PROCESS_ERROR;
}
WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
{
#ifndef OPENSSL_NO_SCTP
if (wst == WORK_MORE_A) {
if (SSL_IS_DTLS(s)) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
size_t labellen;
/*
* Add new shared key for SCTP-Auth, will be ignored if no SCTP
* used.
*/
memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
sizeof(DTLS1_SCTP_AUTH_LABEL));
/* Don't include the terminating zero. */
labellen = sizeof(labelbuffer) - 1;
if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
labellen += 1;
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0,
0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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, 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, 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_R_INVALID_CONTEXT);
goto err;
}
if (!PACKET_get_length_prefixed_3(pkt, &spkt)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, 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_R_CERT_LENGTH_MISMATCH);
goto err;
}
certstart = certbytes;
x = X509_new_ex(s->ctx->libctx, s->ctx->propq);
if (x == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (d2i_X509(&x, (const unsigned char **)&certbytes, l) == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_ASN1_LIB);
goto err;
}
if (certbytes != (certstart + l)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, 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_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, 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_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_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_R_CERTIFICATE_VERIFY_FAILED);
goto err;
}
pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
if (pkey == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
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, 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;
sk = NULL;
/*
* 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
*/
/* 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, 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, 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)
{
uint32_t timeout = (uint32_t)s->session->timeout;
/*
* Ticket lifetime hint:
* In TLSv1.3 we reset the "time" field above, and always specify the
* timeout, limited to a 1 week period per RFC8446.
* For TLSv1.2 this is advisory only and we leave this unspecified for
* resumed session (for simplicity).
*/
#define ONE_WEEK_SEC (7 * 24 * 60 * 60)
if (SSL_IS_TLS13(s)) {
if (s->session->timeout > ONE_WEEK_SEC)
timeout = ONE_WEEK_SEC;
} else if (s->hit)
timeout = 0;
if (!WPACKET_put_bytes_u32(pkt, timeout)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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, 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, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
/*
* Returns 1 on success, 0 to abort construction of the ticket (non-fatal), or
* -1 on fatal error
*/
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;
SSL_HMAC *hctx = NULL;
unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2;
const unsigned char *const_p;
int len, slen_full, slen, lenfinal;
SSL_SESSION *sess;
size_t 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 = -1;
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, ERR_R_INTERNAL_ERROR);
goto err;
}
senc = OPENSSL_malloc(slen_full);
if (senc == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
ctx = EVP_CIPHER_CTX_new();
hctx = ssl_hmac_new(tctx);
if (ctx == NULL || hctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
p = senc;
if (!i2d_SSL_SESSION(s->session, &p)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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, 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, ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(sess);
goto err;
}
p = senc;
if (!i2d_SSL_SESSION(sess, &p)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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.
*/
#ifndef OPENSSL_NO_DEPRECATED_3_0
if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL)
#else
if (tctx->ext.ticket_key_evp_cb != NULL)
#endif
{
int ret = 0;
if (tctx->ext.ticket_key_evp_cb != NULL)
ret = tctx->ext.ticket_key_evp_cb(s, key_name, iv, ctx,
ssl_hmac_get0_EVP_MAC_CTX(hctx),
1);
#ifndef OPENSSL_NO_DEPRECATED_3_0
else if (tctx->ext.ticket_key_cb != NULL)
/* if 0 is returned, write an empty ticket */
ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
ssl_hmac_get0_HMAC_CTX(hctx), 1);
#endif
if (ret == 0) {
/*
* In TLSv1.2 we construct a 0 length ticket. In TLSv1.3 a 0
* length ticket is not allowed so we abort construction of the
* ticket
*/
if (SSL_IS_TLS13(s)) {
ok = 0;
goto err;
}
/* Put timeout and length */
if (!WPACKET_put_bytes_u32(pkt, 0)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
ssl_hmac_free(hctx);
return 1;
}
if (ret < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
goto err;
}
iv_len = EVP_CIPHER_CTX_get_iv_length(ctx);
if (iv_len < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
EVP_CIPHER *cipher = EVP_CIPHER_fetch(s->ctx->libctx, "AES-256-CBC",
s->ctx->propq);
if (cipher == NULL) {
/* Error is already recorded */
SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
goto err;
}
iv_len = EVP_CIPHER_get_iv_length(cipher);
if (iv_len < 0
|| RAND_bytes_ex(s->ctx->libctx, iv, iv_len, 0) <= 0
|| !EVP_EncryptInit_ex(ctx, cipher, NULL,
tctx->ext.secure->tick_aes_key, iv)
|| !ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key,
sizeof(tctx->ext.secure->tick_hmac_key),
"SHA256")) {
EVP_CIPHER_free(cipher);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_CIPHER_free(cipher);
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)
|| !ssl_hmac_update(hctx,
(unsigned char *)s->init_buf->data + macoffset,
macendoffset - macoffset)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
|| !ssl_hmac_final(hctx, macdata1, &hlen, EVP_MAX_MD_SIZE)
|| hlen > EVP_MAX_MD_SIZE
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|| macdata1 != macdata2) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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, ERR_R_INTERNAL_ERROR);
goto err;
}
ok = 1;
err:
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
ssl_hmac_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, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
static void tls_update_ticket_counts(SSL *s)
{
/*
* 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. If we're sending extra
* tickets, decrement the count of pending extra tickets.
*/
s->sent_tickets++;
s->next_ticket_nonce++;
if (s->ext.extra_tickets_expected > 0)
s->ext.extra_tickets_expected--;
}
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;
int ret = 0;
age_add_u.age_add = 0;
if (SSL_IS_TLS13(s)) {
size_t i, hashlen;
uint64_t nonce;
static const unsigned char nonce_label[] = "resumption";
const EVP_MD *md = ssl_handshake_md(s);
int hashleni = EVP_MD_get_size(md);
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
hashlen = (size_t)hashleni;
/*
* If we already sent one NewSessionTicket, or we resumed then
* s->session may already be in a cache and so we must not modify it.
* Instead we need to take a copy of it and modify that.
*/
if (s->sent_tickets != 0 || s->hit) {
SSL_SESSION *new_sess = ssl_session_dup(s->session, 0);
if (new_sess == NULL) {
/* SSLfatal already called */
goto err;
}
SSL_SESSION_free(s->session);
s->session = new_sess;
}
if (!ssl_generate_session_id(s, s->session)) {
/* SSLfatal() already called */
goto err;
}
if (RAND_bytes_ex(s->ctx->libctx, age_add_u.age_add_c,
sizeof(age_add_u), 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
s->session->ext.tick_age_add = age_add_u.age_add;
nonce = s->next_ticket_nonce;
for (i = TICKET_NONCE_SIZE; i > 0; i--) {
tick_nonce[i - 1] = (unsigned char)(nonce & 0xff);
nonce >>= 8;
}
if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
nonce_label,
sizeof(nonce_label) - 1,
tick_nonce,
TICKET_NONCE_SIZE,
s->session->master_key,
hashlen, 1)) {
/* SSLfatal() already called */
goto err;
}
s->session->master_key_length = hashlen;
s->session->time = time(NULL);
ssl_session_calculate_timeout(s->session);
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) {
s->session->ext.alpn_selected_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
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 {
int tmpret;
tmpret = construct_stateless_ticket(s, pkt, age_add_u.age_add,
tick_nonce);
if (tmpret != 1) {
if (tmpret == 0) {
ret = 2; /* Non-fatal. Abort construction but continue */
/* We count this as a success so update the counts anwyay */
tls_update_ticket_counts(s);
}
/* else 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;
}
tls_update_ticket_counts(s);
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
}
ret = 1;
err:
return ret;
}
/*
* 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, 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_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, 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_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, 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_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/crypto/openssl/test/acvp_test.c b/crypto/openssl/test/acvp_test.c
index fee880d441b0..eccf9d90a021 100644
--- a/crypto/openssl/test/acvp_test.c
+++ b/crypto/openssl/test/acvp_test.c
@@ -1,1502 +1,1502 @@
/*
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* A set of tests demonstrating uses cases for CAVS/ACVP testing.
*
* For examples of testing KDF's, Digests, KeyAgreement & DRBG's refer to
* providers/fips/self_test_kats.c
*/
#include <string.h>
#include <openssl/opensslconf.h> /* To see if OPENSSL_NO_EC is defined */
#include <openssl/core_names.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/dh.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/param_build.h>
#include <openssl/provider.h>
#include <openssl/self_test.h>
#include "testutil.h"
#include "testutil/output.h"
#include "acvp_test.inc"
#include "internal/nelem.h"
typedef enum OPTION_choice {
OPT_ERR = -1,
OPT_EOF = 0,
OPT_CONFIG_FILE,
OPT_TEST_ENUM
} OPTION_CHOICE;
typedef struct st_args {
int enable;
int called;
} SELF_TEST_ARGS;
static OSSL_PROVIDER *prov_null = NULL;
static OSSL_LIB_CTX *libctx = NULL;
static SELF_TEST_ARGS self_test_args = { 0 };
static OSSL_CALLBACK self_test_events;
const OPTIONS *test_get_options(void)
{
static const OPTIONS test_options[] = {
OPT_TEST_OPTIONS_DEFAULT_USAGE,
{ "config", OPT_CONFIG_FILE, '<',
"The configuration file to use for the libctx" },
{ NULL }
};
return test_options;
}
static int pkey_get_bn_bytes(EVP_PKEY *pkey, const char *name,
unsigned char **out, size_t *out_len)
{
unsigned char *buf = NULL;
BIGNUM *bn = NULL;
int sz;
if (!EVP_PKEY_get_bn_param(pkey, name, &bn))
goto err;
sz = BN_num_bytes(bn);
buf = OPENSSL_zalloc(sz);
if (buf == NULL)
goto err;
if (BN_bn2binpad(bn, buf, sz) <= 0)
goto err;
*out_len = sz;
*out = buf;
BN_free(bn);
return 1;
err:
OPENSSL_free(buf);
BN_free(bn);
return 0;
}
static int sig_gen(EVP_PKEY *pkey, OSSL_PARAM *params, const char *digest_name,
const unsigned char *msg, size_t msg_len,
unsigned char **sig_out, size_t *sig_out_len)
{
int ret = 0;
EVP_MD_CTX *md_ctx = NULL;
unsigned char *sig = NULL;
size_t sig_len;
size_t sz = EVP_PKEY_get_size(pkey);
sig_len = sz;
if (!TEST_ptr(sig = OPENSSL_malloc(sz))
|| !TEST_ptr(md_ctx = EVP_MD_CTX_new())
|| !TEST_int_eq(EVP_DigestSignInit_ex(md_ctx, NULL, digest_name, libctx,
NULL, pkey, NULL), 1)
|| !TEST_int_gt(EVP_DigestSign(md_ctx, sig, &sig_len, msg, msg_len), 0))
goto err;
*sig_out = sig;
*sig_out_len = sig_len;
sig = NULL;
ret = 1;
err:
OPENSSL_free(sig);
EVP_MD_CTX_free(md_ctx);
return ret;
}
#ifndef OPENSSL_NO_EC
static int ecdsa_keygen_test(int id)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
unsigned char *priv = NULL;
unsigned char *pubx = NULL, *puby = NULL;
size_t priv_len = 0, pubx_len = 0, puby_len = 0;
const struct ecdsa_keygen_st *tst = &ecdsa_keygen_data[id];
self_test_args.called = 0;
self_test_args.enable = 1;
if (!TEST_ptr(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "EC", tst->curve_name))
|| !TEST_int_ge(self_test_args.called, 3)
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv,
&priv_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &pubx,
&pubx_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &puby,
&puby_len)))
goto err;
test_output_memory("qy", puby, puby_len);
test_output_memory("qx", pubx, pubx_len);
test_output_memory("d", priv, priv_len);
ret = 1;
err:
self_test_args.enable = 0;
self_test_args.called = 0;
OPENSSL_clear_free(priv, priv_len);
OPENSSL_free(pubx);
OPENSSL_free(puby);
EVP_PKEY_free(pkey);
return ret;
}
static int ecdsa_create_pkey(EVP_PKEY **pkey, const char *curve_name,
const unsigned char *pub, size_t pub_len,
int expected)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *params = NULL;
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| (curve_name != NULL
&& !TEST_true(OSSL_PARAM_BLD_push_utf8_string(
bld, OSSL_PKEY_PARAM_GROUP_NAME, curve_name, 0) > 0))
|| !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld,
OSSL_PKEY_PARAM_PUB_KEY,
pub, pub_len) > 0)
|| !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))
|| !TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_PUBLIC_KEY,
params), expected))
goto err;
ret = 1;
err:
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int ecdsa_pub_verify_test(int id)
{
const struct ecdsa_pub_verify_st *tst = &ecdsa_pv_data[id];
int ret = 0;
EVP_PKEY_CTX *key_ctx = NULL;
EVP_PKEY *pkey = NULL;
if (!TEST_true(ecdsa_create_pkey(&pkey, tst->curve_name,
tst->pub, tst->pub_len, tst->pass)))
goto err;
if (tst->pass) {
if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, ""))
|| !TEST_int_eq(EVP_PKEY_public_check(key_ctx), tst->pass))
goto err;
}
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(key_ctx);
return ret;
}
/* Extract r and s from an ecdsa signature */
static int get_ecdsa_sig_rs_bytes(const unsigned char *sig, size_t sig_len,
unsigned char **r, unsigned char **s,
size_t *rlen, size_t *slen)
{
int ret = 0;
unsigned char *rbuf = NULL, *sbuf = NULL;
size_t r1_len, s1_len;
const BIGNUM *r1, *s1;
ECDSA_SIG *sign = d2i_ECDSA_SIG(NULL, &sig, sig_len);
if (sign == NULL)
return 0;
r1 = ECDSA_SIG_get0_r(sign);
s1 = ECDSA_SIG_get0_s(sign);
if (r1 == NULL || s1 == NULL)
goto err;
r1_len = BN_num_bytes(r1);
s1_len = BN_num_bytes(s1);
rbuf = OPENSSL_zalloc(r1_len);
sbuf = OPENSSL_zalloc(s1_len);
if (rbuf == NULL || sbuf == NULL)
goto err;
if (BN_bn2binpad(r1, rbuf, r1_len) <= 0)
goto err;
if (BN_bn2binpad(s1, sbuf, s1_len) <= 0)
goto err;
*r = rbuf;
*s = sbuf;
*rlen = r1_len;
*slen = s1_len;
ret = 1;
err:
if (ret == 0) {
OPENSSL_free(rbuf);
OPENSSL_free(sbuf);
}
ECDSA_SIG_free(sign);
return ret;
}
static int ecdsa_siggen_test(int id)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
size_t sig_len = 0, rlen = 0, slen = 0;
unsigned char *sig = NULL;
unsigned char *r = NULL, *s = NULL;
const struct ecdsa_siggen_st *tst = &ecdsa_siggen_data[id];
if (!TEST_ptr(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "EC", tst->curve_name)))
goto err;
if (!TEST_true(sig_gen(pkey, NULL, tst->digest_alg, tst->msg, tst->msg_len,
&sig, &sig_len))
|| !TEST_true(get_ecdsa_sig_rs_bytes(sig, sig_len, &r, &s, &rlen, &slen)))
goto err;
test_output_memory("r", r, rlen);
test_output_memory("s", s, slen);
ret = 1;
err:
OPENSSL_free(r);
OPENSSL_free(s);
OPENSSL_free(sig);
EVP_PKEY_free(pkey);
return ret;
}
static int ecdsa_sigver_test(int id)
{
int ret = 0;
EVP_MD_CTX *md_ctx = NULL;
EVP_PKEY *pkey = NULL;
ECDSA_SIG *sign = NULL;
size_t sig_len;
unsigned char *sig = NULL;
BIGNUM *rbn = NULL, *sbn = NULL;
const struct ecdsa_sigver_st *tst = &ecdsa_sigver_data[id];
if (!TEST_true(ecdsa_create_pkey(&pkey, tst->curve_name,
tst->pub, tst->pub_len, 1)))
goto err;
if (!TEST_ptr(sign = ECDSA_SIG_new())
|| !TEST_ptr(rbn = BN_bin2bn(tst->r, tst->r_len, NULL))
|| !TEST_ptr(sbn = BN_bin2bn(tst->s, tst->s_len, NULL))
|| !TEST_true(ECDSA_SIG_set0(sign, rbn, sbn)))
goto err;
rbn = sbn = NULL;
ret = TEST_int_gt((sig_len = i2d_ECDSA_SIG(sign, &sig)), 0)
&& TEST_ptr(md_ctx = EVP_MD_CTX_new())
&& TEST_true(EVP_DigestVerifyInit_ex(md_ctx, NULL, tst->digest_alg,
libctx, NULL, pkey, NULL)
&& TEST_int_eq(EVP_DigestVerify(md_ctx, sig, sig_len,
tst->msg, tst->msg_len), tst->pass));
err:
BN_free(rbn);
BN_free(sbn);
OPENSSL_free(sig);
ECDSA_SIG_free(sign);
EVP_PKEY_free(pkey);
EVP_MD_CTX_free(md_ctx);
return ret;
}
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_DSA
static int pkey_get_octet_bytes(EVP_PKEY *pkey, const char *name,
unsigned char **out, size_t *out_len)
{
size_t len = 0;
unsigned char *buf = NULL;
if (!EVP_PKEY_get_octet_string_param(pkey, name, NULL, 0, &len))
goto err;
buf = OPENSSL_zalloc(len);
if (buf == NULL)
goto err;
if (!EVP_PKEY_get_octet_string_param(pkey, name, buf, len, out_len))
goto err;
*out = buf;
return 1;
err:
OPENSSL_free(buf);
return 0;
}
static EVP_PKEY *dsa_paramgen(int L, int N)
{
EVP_PKEY_CTX *paramgen_ctx = NULL;
EVP_PKEY *param_key = NULL;
if (!TEST_ptr(paramgen_ctx = EVP_PKEY_CTX_new_from_name(libctx, "DSA", NULL))
|| !TEST_int_gt(EVP_PKEY_paramgen_init(paramgen_ctx), 0)
|| !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_bits(paramgen_ctx, L))
|| !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_q_bits(paramgen_ctx, N))
|| !TEST_true(EVP_PKEY_paramgen(paramgen_ctx, &param_key)))
return NULL;
EVP_PKEY_CTX_free(paramgen_ctx);
return param_key;
}
static EVP_PKEY *dsa_keygen(int L, int N)
{
EVP_PKEY *param_key = NULL, *key = NULL;
EVP_PKEY_CTX *keygen_ctx = NULL;
if (!TEST_ptr(param_key = dsa_paramgen(L, N))
|| !TEST_ptr(keygen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, param_key,
NULL))
|| !TEST_int_gt(EVP_PKEY_keygen_init(keygen_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_keygen(keygen_ctx, &key), 0))
goto err;
err:
EVP_PKEY_free(param_key);
EVP_PKEY_CTX_free(keygen_ctx);
return key;
}
static int dsa_keygen_test(int id)
{
int ret = 0, i;
EVP_PKEY_CTX *paramgen_ctx = NULL, *keygen_ctx = NULL;
EVP_PKEY *param_key = NULL, *key = NULL;
unsigned char *priv = NULL, *pub = NULL;
size_t priv_len = 0, pub_len = 0;
const struct dsa_paramgen_st *tst = &dsa_keygen_data[id];
if (!TEST_ptr(param_key = dsa_paramgen(tst->L, tst->N))
|| !TEST_ptr(keygen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, param_key,
NULL))
|| !TEST_int_gt(EVP_PKEY_keygen_init(keygen_ctx), 0))
goto err;
for (i = 0; i < 2; ++i) {
if (!TEST_int_gt(EVP_PKEY_keygen(keygen_ctx, &key), 0)
|| !TEST_true(pkey_get_bn_bytes(key, OSSL_PKEY_PARAM_PRIV_KEY,
&priv, &priv_len))
|| !TEST_true(pkey_get_bn_bytes(key, OSSL_PKEY_PARAM_PUB_KEY,
&pub, &pub_len)))
goto err;
test_output_memory("y", pub, pub_len);
test_output_memory("x", priv, priv_len);
EVP_PKEY_free(key);
OPENSSL_clear_free(priv, priv_len);
OPENSSL_free(pub);
key = NULL;
pub = priv = NULL;
}
ret = 1;
err:
OPENSSL_clear_free(priv, priv_len);
OPENSSL_free(pub);
EVP_PKEY_free(param_key);
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(keygen_ctx);
EVP_PKEY_CTX_free(paramgen_ctx);
return ret;
}
static int dsa_paramgen_test(int id)
{
int ret = 0, counter = 0;
EVP_PKEY_CTX *paramgen_ctx = NULL;
EVP_PKEY *param_key = NULL;
unsigned char *p = NULL, *q = NULL, *seed = NULL;
size_t plen = 0, qlen = 0, seedlen = 0;
const struct dsa_paramgen_st *tst = &dsa_paramgen_data[id];
if (!TEST_ptr(paramgen_ctx = EVP_PKEY_CTX_new_from_name(libctx, "DSA", NULL))
|| !TEST_int_gt(EVP_PKEY_paramgen_init(paramgen_ctx), 0)
|| !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_bits(paramgen_ctx, tst->L))
|| !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_q_bits(paramgen_ctx, tst->N))
|| !TEST_true(EVP_PKEY_paramgen(paramgen_ctx, &param_key))
|| !TEST_true(pkey_get_bn_bytes(param_key, OSSL_PKEY_PARAM_FFC_P,
&p, &plen))
|| !TEST_true(pkey_get_bn_bytes(param_key, OSSL_PKEY_PARAM_FFC_Q,
&q, &qlen))
|| !TEST_true(pkey_get_octet_bytes(param_key, OSSL_PKEY_PARAM_FFC_SEED,
&seed, &seedlen))
|| !TEST_true(EVP_PKEY_get_int_param(param_key,
OSSL_PKEY_PARAM_FFC_PCOUNTER,
&counter)))
goto err;
test_output_memory("p", p, plen);
test_output_memory("q", q, qlen);
test_output_memory("domainSeed", seed, seedlen);
test_printf_stderr("%s: %d\n", "counter", counter);
ret = 1;
err:
OPENSSL_free(p);
OPENSSL_free(q);
OPENSSL_free(seed);
EVP_PKEY_free(param_key);
EVP_PKEY_CTX_free(paramgen_ctx);
return ret;
}
static int dsa_create_pkey(EVP_PKEY **pkey,
const unsigned char *p, size_t p_len,
const unsigned char *q, size_t q_len,
const unsigned char *g, size_t g_len,
const unsigned char *seed, size_t seed_len,
int counter,
int validate_pq, int validate_g,
const unsigned char *pub, size_t pub_len,
BN_CTX *bn_ctx)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *params = NULL;
BIGNUM *p_bn = NULL, *q_bn = NULL, *g_bn = NULL, *pub_bn = NULL;
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| !TEST_ptr(p_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(p, p_len, p_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_int(bld,
OSSL_PKEY_PARAM_FFC_VALIDATE_PQ,
validate_pq))
|| !TEST_true(OSSL_PARAM_BLD_push_int(bld,
OSSL_PKEY_PARAM_FFC_VALIDATE_G,
validate_g))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p_bn))
|| !TEST_ptr(q_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(q, q_len, q_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q_bn)))
goto err;
if (g != NULL) {
if (!TEST_ptr(g_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(g, g_len, g_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld,
OSSL_PKEY_PARAM_FFC_G, g_bn)))
goto err;
}
if (seed != NULL) {
if (!TEST_true(OSSL_PARAM_BLD_push_octet_string(bld,
OSSL_PKEY_PARAM_FFC_SEED, seed, seed_len)))
goto err;
}
if (counter != -1) {
if (!TEST_true(OSSL_PARAM_BLD_push_int(bld,
OSSL_PKEY_PARAM_FFC_PCOUNTER,
counter)))
goto err;
}
if (pub != NULL) {
if (!TEST_ptr(pub_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(pub, pub_len, pub_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld,
OSSL_PKEY_PARAM_PUB_KEY,
pub_bn)))
goto err;
}
if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "DSA", NULL))
|| !TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_PUBLIC_KEY,
params), 1))
goto err;
ret = 1;
err:
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int dsa_pqver_test(int id)
{
int ret = 0;
BN_CTX *bn_ctx = NULL;
EVP_PKEY_CTX *key_ctx = NULL;
EVP_PKEY *param_key = NULL;
const struct dsa_pqver_st *tst = &dsa_pqver_data[id];
if (!TEST_ptr(bn_ctx = BN_CTX_new_ex(libctx))
|| !TEST_true(dsa_create_pkey(&param_key, tst->p, tst->p_len,
tst->q, tst->q_len, NULL, 0,
tst->seed, tst->seed_len, tst->counter,
1, 0,
NULL, 0,
bn_ctx))
|| !TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, param_key,
NULL))
|| !TEST_int_eq(EVP_PKEY_param_check(key_ctx), tst->pass))
goto err;
ret = 1;
err:
BN_CTX_free(bn_ctx);
EVP_PKEY_free(param_key);
EVP_PKEY_CTX_free(key_ctx);
return ret;
}
/* Extract r and s from a dsa signature */
static int get_dsa_sig_rs_bytes(const unsigned char *sig, size_t sig_len,
unsigned char **r, unsigned char **s,
size_t *r_len, size_t *s_len)
{
int ret = 0;
unsigned char *rbuf = NULL, *sbuf = NULL;
size_t r1_len, s1_len;
const BIGNUM *r1, *s1;
DSA_SIG *sign = d2i_DSA_SIG(NULL, &sig, sig_len);
if (sign == NULL)
return 0;
DSA_SIG_get0(sign, &r1, &s1);
if (r1 == NULL || s1 == NULL)
goto err;
r1_len = BN_num_bytes(r1);
s1_len = BN_num_bytes(s1);
rbuf = OPENSSL_zalloc(r1_len);
sbuf = OPENSSL_zalloc(s1_len);
if (rbuf == NULL || sbuf == NULL)
goto err;
if (BN_bn2binpad(r1, rbuf, r1_len) <= 0)
goto err;
if (BN_bn2binpad(s1, sbuf, s1_len) <= 0)
goto err;
*r = rbuf;
*s = sbuf;
*r_len = r1_len;
*s_len = s1_len;
ret = 1;
err:
if (ret == 0) {
OPENSSL_free(rbuf);
OPENSSL_free(sbuf);
}
DSA_SIG_free(sign);
return ret;
}
static int dsa_siggen_test(int id)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
unsigned char *sig = NULL, *r = NULL, *s = NULL;
size_t sig_len = 0, rlen = 0, slen = 0;
const struct dsa_siggen_st *tst = &dsa_siggen_data[id];
if (!TEST_ptr(pkey = dsa_keygen(tst->L, tst->N)))
goto err;
if (!TEST_true(sig_gen(pkey, NULL, tst->digest_alg, tst->msg, tst->msg_len,
&sig, &sig_len))
|| !TEST_true(get_dsa_sig_rs_bytes(sig, sig_len, &r, &s, &rlen, &slen)))
goto err;
test_output_memory("r", r, rlen);
test_output_memory("s", s, slen);
ret = 1;
err:
OPENSSL_free(r);
OPENSSL_free(s);
OPENSSL_free(sig);
EVP_PKEY_free(pkey);
return ret;
}
static int dsa_sigver_test(int id)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
DSA_SIG *sign = NULL;
size_t sig_len;
unsigned char *sig = NULL;
BIGNUM *rbn = NULL, *sbn = NULL;
EVP_MD *md = NULL;
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digest_len;
BN_CTX *bn_ctx = NULL;
const struct dsa_sigver_st *tst = &dsa_sigver_data[id];
if (!TEST_ptr(bn_ctx = BN_CTX_new())
|| !TEST_true(dsa_create_pkey(&pkey, tst->p, tst->p_len,
tst->q, tst->q_len, tst->g, tst->g_len,
NULL, 0, 0, 0, 0, tst->pub, tst->pub_len,
bn_ctx)))
goto err;
if (!TEST_ptr(sign = DSA_SIG_new())
|| !TEST_ptr(rbn = BN_bin2bn(tst->r, tst->r_len, NULL))
|| !TEST_ptr(sbn = BN_bin2bn(tst->s, tst->s_len, NULL))
|| !TEST_true(DSA_SIG_set0(sign, rbn, sbn)))
goto err;
rbn = sbn = NULL;
if (!TEST_ptr(md = EVP_MD_fetch(libctx, tst->digest_alg, ""))
|| !TEST_true(EVP_Digest(tst->msg, tst->msg_len,
digest, &digest_len, md, NULL)))
goto err;
if (!TEST_int_gt((sig_len = i2d_DSA_SIG(sign, &sig)), 0)
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, ""))
|| !TEST_int_gt(EVP_PKEY_verify_init(ctx), 0)
|| !TEST_int_eq(EVP_PKEY_verify(ctx, sig, sig_len, digest, digest_len),
tst->pass))
goto err;
ret = 1;
err:
EVP_PKEY_CTX_free(ctx);
OPENSSL_free(sig);
EVP_MD_free(md);
DSA_SIG_free(sign);
EVP_PKEY_free(pkey);
BN_free(rbn);
BN_free(sbn);
BN_CTX_free(bn_ctx);
return ret;
}
#endif /* OPENSSL_NO_DSA */
/* cipher encrypt/decrypt */
static int cipher_enc(const char *alg,
const unsigned char *pt, size_t pt_len,
const unsigned char *key, size_t key_len,
const unsigned char *iv, size_t iv_len,
const unsigned char *ct, size_t ct_len,
int enc)
{
int ret = 0, out_len = 0, len = 0;
EVP_CIPHER_CTX *ctx = NULL;
EVP_CIPHER *cipher = NULL;
unsigned char out[256] = { 0 };
TEST_note("%s : %s", alg, enc ? "encrypt" : "decrypt");
if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
|| !TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, alg, ""))
|| !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc))
|| !TEST_true(EVP_CIPHER_CTX_set_padding(ctx, 0))
|| !TEST_true(EVP_CipherUpdate(ctx, out, &len, pt, pt_len))
|| !TEST_true(EVP_CipherFinal_ex(ctx, out + len, &out_len)))
goto err;
out_len += len;
if (!TEST_mem_eq(out, out_len, ct, ct_len))
goto err;
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
static int cipher_enc_dec_test(int id)
{
const struct cipher_st *tst = &cipher_enc_data[id];
const int enc = 1;
return TEST_true(cipher_enc(tst->alg, tst->pt, tst->pt_len,
tst->key, tst->key_len,
tst->iv, tst->iv_len,
tst->ct, tst->ct_len, enc))
&& TEST_true(cipher_enc(tst->alg, tst->ct, tst->ct_len,
tst->key, tst->key_len,
tst->iv, tst->iv_len,
tst->pt, tst->pt_len, !enc));
}
static int aes_ccm_enc_dec(const char *alg,
const unsigned char *pt, size_t pt_len,
const unsigned char *key, size_t key_len,
const unsigned char *iv, size_t iv_len,
const unsigned char *aad, size_t aad_len,
const unsigned char *ct, size_t ct_len,
const unsigned char *tag, size_t tag_len,
int enc, int pass)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int out_len, len;
unsigned char out[1024];
TEST_note("%s : %s : expected to %s", alg, enc ? "encrypt" : "decrypt",
pass ? "pass" : "fail");
if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
|| !TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, alg, ""))
|| !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc))
|| !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv_len,
NULL), 0)
|| !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len,
enc ? NULL : (void *)tag), 0)
|| !TEST_true(EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc))
|| !TEST_true(EVP_CIPHER_CTX_set_padding(ctx, 0))
|| !TEST_true(EVP_CipherUpdate(ctx, NULL, &len, NULL, pt_len))
|| !TEST_true(EVP_CipherUpdate(ctx, NULL, &len, aad, aad_len))
|| !TEST_int_eq(EVP_CipherUpdate(ctx, out, &len, pt, pt_len), pass))
goto err;
if (!pass) {
ret = 1;
goto err;
}
if (!TEST_true(EVP_CipherFinal_ex(ctx, out + len, &out_len)))
goto err;
if (enc) {
out_len += len;
if (!TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG,
tag_len, out + out_len), 0)
|| !TEST_mem_eq(out, out_len, ct, ct_len)
|| !TEST_mem_eq(out + out_len, tag_len, tag, tag_len))
goto err;
} else {
if (!TEST_mem_eq(out, out_len + len, ct, ct_len))
goto err;
}
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
static int aes_ccm_enc_dec_test(int id)
{
const struct cipher_ccm_st *tst = &aes_ccm_enc_data[id];
/* The tag is on the end of the cipher text */
const size_t tag_len = tst->ct_len - tst->pt_len;
const size_t ct_len = tst->ct_len - tag_len;
const unsigned char *tag = tst->ct + ct_len;
const int enc = 1;
const int pass = 1;
if (ct_len < 1)
return 0;
return aes_ccm_enc_dec(tst->alg, tst->pt, tst->pt_len,
tst->key, tst->key_len,
tst->iv, tst->iv_len, tst->aad, tst->aad_len,
tst->ct, ct_len, tag, tag_len, enc, pass)
&& aes_ccm_enc_dec(tst->alg, tst->ct, ct_len,
tst->key, tst->key_len,
tst->iv, tst->iv_len, tst->aad, tst->aad_len,
tst->pt, tst->pt_len, tag, tag_len, !enc, pass)
/* test that it fails if the tag is incorrect */
&& aes_ccm_enc_dec(tst->alg, tst->ct, ct_len,
tst->key, tst->key_len,
tst->iv, tst->iv_len, tst->aad, tst->aad_len,
tst->pt, tst->pt_len,
tag - 1, tag_len, !enc, !pass);
}
static int aes_gcm_enc_dec(const char *alg,
const unsigned char *pt, size_t pt_len,
const unsigned char *key, size_t key_len,
const unsigned char *iv, size_t iv_len,
const unsigned char *aad, size_t aad_len,
const unsigned char *ct, size_t ct_len,
const unsigned char *tag, size_t tag_len,
int enc, int pass)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int out_len, len;
unsigned char out[1024];
TEST_note("%s : %s : expected to %s", alg, enc ? "encrypt" : "decrypt",
pass ? "pass" : "fail");
if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
|| !TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, alg, ""))
|| !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc))
|| !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv_len,
NULL), 0))
goto err;
if (!enc) {
if (!TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len,
(void *)tag), 0))
goto err;
}
/*
* For testing purposes the IV it being set here. In a compliant application
* the IV would be generated internally. A fake entropy source could also
* be used to feed in the random IV bytes (see fake_random.c)
*/
if (!TEST_true(EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc))
|| !TEST_true(EVP_CIPHER_CTX_set_padding(ctx, 0))
|| !TEST_true(EVP_CipherUpdate(ctx, NULL, &len, aad, aad_len))
|| !TEST_true(EVP_CipherUpdate(ctx, out, &len, pt, pt_len)))
goto err;
if (!TEST_int_eq(EVP_CipherFinal_ex(ctx, out + len, &out_len), pass))
goto err;
if (!pass) {
ret = 1;
goto err;
}
out_len += len;
if (enc) {
if (!TEST_mem_eq(out, out_len, ct, ct_len)
|| !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG,
tag_len, out + out_len), 0)
|| !TEST_mem_eq(out + out_len, tag_len, tag, tag_len))
goto err;
} else {
if (!TEST_mem_eq(out, out_len, ct, ct_len))
goto err;
}
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
static int aes_gcm_enc_dec_test(int id)
{
const struct cipher_gcm_st *tst = &aes_gcm_enc_data[id];
int enc = 1;
int pass = 1;
return aes_gcm_enc_dec(tst->alg, tst->pt, tst->pt_len,
tst->key, tst->key_len,
tst->iv, tst->iv_len, tst->aad, tst->aad_len,
tst->ct, tst->ct_len, tst->tag, tst->tag_len,
enc, pass)
&& aes_gcm_enc_dec(tst->alg, tst->ct, tst->ct_len,
tst->key, tst->key_len,
tst->iv, tst->iv_len, tst->aad, tst->aad_len,
tst->pt, tst->pt_len, tst->tag, tst->tag_len,
!enc, pass)
/* Fail if incorrect tag passed to decrypt */
&& aes_gcm_enc_dec(tst->alg, tst->ct, tst->ct_len,
tst->key, tst->key_len,
tst->iv, tst->iv_len, tst->aad, tst->aad_len,
tst->pt, tst->pt_len, tst->aad, tst->tag_len,
!enc, !pass);
}
#ifndef OPENSSL_NO_DH
static int dh_create_pkey(EVP_PKEY **pkey, const char *group_name,
const unsigned char *pub, size_t pub_len,
const unsigned char *priv, size_t priv_len,
BN_CTX *bn_ctx, int pass)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *params = NULL;
BIGNUM *pub_bn = NULL, *priv_bn = NULL;
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| (group_name != NULL
&& !TEST_int_gt(OSSL_PARAM_BLD_push_utf8_string(
bld, OSSL_PKEY_PARAM_GROUP_NAME,
group_name, 0), 0)))
goto err;
if (pub != NULL) {
if (!TEST_ptr(pub_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(pub, pub_len, pub_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY,
pub_bn)))
goto err;
}
if (priv != NULL) {
if (!TEST_ptr(priv_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(priv, priv_len, priv_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY,
priv_bn)))
goto err;
}
if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "DH", NULL))
|| !TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_KEYPAIR, params),
pass))
goto err;
ret = 1;
err:
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int dh_safe_prime_keygen_test(int id)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
unsigned char *priv = NULL;
unsigned char *pub = NULL;
size_t priv_len = 0, pub_len = 0;
OSSL_PARAM params[2];
const struct dh_safe_prime_keygen_st *tst = &dh_safe_prime_keygen_data[id];
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
(char *)tst->group_name, 0);
params[1] = OSSL_PARAM_construct_end();
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "DH", NULL))
|| !TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0)
|| !TEST_true(EVP_PKEY_CTX_set_params(ctx, params))
|| !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0)
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
&priv, &priv_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_PUB_KEY,
&pub, &pub_len)))
goto err;
test_output_memory("x", priv, priv_len);
test_output_memory("y", pub, pub_len);
ret = 1;
err:
OPENSSL_clear_free(priv, priv_len);
OPENSSL_free(pub);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int dh_safe_prime_keyver_test(int id)
{
int ret = 0;
BN_CTX *bn_ctx = NULL;
EVP_PKEY_CTX *key_ctx = NULL;
EVP_PKEY *pkey = NULL;
const struct dh_safe_prime_keyver_st *tst = &dh_safe_prime_keyver_data[id];
if (!TEST_ptr(bn_ctx = BN_CTX_new_ex(libctx))
|| !TEST_true(dh_create_pkey(&pkey, tst->group_name,
tst->pub, tst->pub_len,
tst->priv, tst->priv_len, bn_ctx, 1))
|| !TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, ""))
|| !TEST_int_eq(EVP_PKEY_check(key_ctx), tst->pass))
goto err;
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(key_ctx);
BN_CTX_free(bn_ctx);
return ret;
}
#endif /* OPENSSL_NO_DH */
static int rsa_create_pkey(EVP_PKEY **pkey,
const unsigned char *n, size_t n_len,
const unsigned char *e, size_t e_len,
const unsigned char *d, size_t d_len,
BN_CTX *bn_ctx)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *params = NULL;
BIGNUM *e_bn = NULL, *d_bn = NULL, *n_bn = NULL;
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| !TEST_ptr(n_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(n, n_len, n_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n_bn)))
goto err;
if (e != NULL) {
if (!TEST_ptr(e_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(e, e_len, e_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E,
e_bn)))
goto err;
}
if (d != NULL) {
if (!TEST_ptr(d_bn = BN_CTX_get(bn_ctx))
|| !TEST_ptr(BN_bin2bn(d, d_len, d_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D,
d_bn)))
goto err;
}
if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL))
|| !TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_KEYPAIR, params),
1))
goto err;
ret = 1;
err:
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int rsa_keygen_test(int id)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
BIGNUM *e_bn = NULL;
BIGNUM *xp1_bn = NULL, *xp2_bn = NULL, *xp_bn = NULL;
BIGNUM *xq1_bn = NULL, *xq2_bn = NULL, *xq_bn = NULL;
unsigned char *n = NULL, *d = NULL;
unsigned char *p = NULL, *p1 = NULL, *p2 = NULL;
unsigned char *q = NULL, *q1 = NULL, *q2 = NULL;
size_t n_len = 0, d_len = 0;
size_t p_len = 0, p1_len = 0, p2_len = 0;
size_t q_len = 0, q1_len = 0, q2_len = 0;
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *params = NULL;
const struct rsa_keygen_st *tst = &rsa_keygen_data[id];
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| !TEST_ptr(xp1_bn = BN_bin2bn(tst->xp1, tst->xp1_len, NULL))
|| !TEST_ptr(xp2_bn = BN_bin2bn(tst->xp2, tst->xp2_len, NULL))
|| !TEST_ptr(xp_bn = BN_bin2bn(tst->xp, tst->xp_len, NULL))
|| !TEST_ptr(xq1_bn = BN_bin2bn(tst->xq1, tst->xq1_len, NULL))
|| !TEST_ptr(xq2_bn = BN_bin2bn(tst->xq2, tst->xq2_len, NULL))
|| !TEST_ptr(xq_bn = BN_bin2bn(tst->xq, tst->xq_len, NULL))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XP1,
xp1_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XP2,
xp2_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XP,
xp_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XQ1,
xq1_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XQ2,
xq2_bn))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XQ,
xq_bn))
|| !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
goto err;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL))
|| !TEST_ptr(e_bn = BN_bin2bn(tst->e, tst->e_len, NULL))
|| !TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0)
|| !TEST_int_gt(EVP_PKEY_CTX_set_params(ctx, params), 0)
|| !TEST_int_gt(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, tst->mod), 0)
|| !TEST_int_gt(EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, e_bn), 0)
|| !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0)
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_TEST_P1,
&p1, &p1_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_TEST_P2,
&p2, &p2_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_TEST_Q1,
&q1, &q1_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_TEST_Q2,
&q2, &q2_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_FACTOR1,
&p, &p_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_FACTOR2,
&q, &q_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_N,
&n, &n_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_D,
&d, &d_len)))
goto err;
if (!TEST_mem_eq(tst->p1, tst->p1_len, p1, p1_len)
|| !TEST_mem_eq(tst->p2, tst->p2_len, p2, p2_len)
|| !TEST_mem_eq(tst->p, tst->p_len, p, p_len)
|| !TEST_mem_eq(tst->q1, tst->q1_len, q1, q1_len)
|| !TEST_mem_eq(tst->q2, tst->q2_len, q2, q2_len)
|| !TEST_mem_eq(tst->q, tst->q_len, q, q_len)
|| !TEST_mem_eq(tst->n, tst->n_len, n, n_len)
|| !TEST_mem_eq(tst->d, tst->d_len, d, d_len))
goto err;
test_output_memory("p1", p1, p1_len);
test_output_memory("p2", p2, p2_len);
test_output_memory("p", p, p_len);
test_output_memory("q1", q1, q1_len);
test_output_memory("q2", q2, q2_len);
test_output_memory("q", q, q_len);
test_output_memory("n", n, n_len);
test_output_memory("d", d, d_len);
ret = 1;
err:
BN_free(xp1_bn);
BN_free(xp2_bn);
BN_free(xp_bn);
BN_free(xq1_bn);
BN_free(xq2_bn);
BN_free(xq_bn);
BN_free(e_bn);
OPENSSL_free(p1);
OPENSSL_free(p2);
OPENSSL_free(q1);
OPENSSL_free(q2);
OPENSSL_free(p);
OPENSSL_free(q);
OPENSSL_free(n);
OPENSSL_free(d);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
return ret;
}
static int rsa_siggen_test(int id)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
unsigned char *sig = NULL, *n = NULL, *e = NULL;
size_t sig_len = 0, n_len = 0, e_len = 0;
OSSL_PARAM params[4], *p;
const struct rsa_siggen_st *tst = &rsa_siggen_data[id];
int salt_len = tst->pss_salt_len;
TEST_note("RSA %s signature generation", tst->sig_pad_mode);
p = params;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE,
(char *)tst->sig_pad_mode, 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
(char *)tst->digest_alg, 0);
if (salt_len >= 0)
*p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN,
&salt_len);
*p++ = OSSL_PARAM_construct_end();
if (!TEST_ptr(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "RSA", tst->mod))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_N, &n, &n_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_E, &e, &e_len))
|| !TEST_true(sig_gen(pkey, params, tst->digest_alg,
tst->msg, tst->msg_len,
&sig, &sig_len)))
goto err;
test_output_memory("n", n, n_len);
test_output_memory("e", e, e_len);
test_output_memory("sig", sig, sig_len);
ret = 1;
err:
OPENSSL_free(n);
OPENSSL_free(e);
OPENSSL_free(sig);
EVP_PKEY_free(pkey);
return ret;
}
static int rsa_sigver_test(int id)
{
int ret = 0;
EVP_PKEY_CTX *pkey_ctx = NULL;
EVP_PKEY *pkey = NULL;
EVP_MD_CTX *md_ctx = NULL;
BN_CTX *bn_ctx = NULL;
OSSL_PARAM params[4], *p;
const struct rsa_sigver_st *tst = &rsa_sigver_data[id];
int salt_len = tst->pss_salt_len;
TEST_note("RSA %s Signature Verify : expected to %s ", tst->sig_pad_mode,
tst->pass == PASS ? "pass" : "fail");
p = params;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE,
(char *)tst->sig_pad_mode, 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
(char *)tst->digest_alg, 0);
if (salt_len >= 0)
*p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN,
&salt_len);
*p++ = OSSL_PARAM_construct_end();
if (!TEST_ptr(bn_ctx = BN_CTX_new())
|| !TEST_true(rsa_create_pkey(&pkey, tst->n, tst->n_len,
tst->e, tst->e_len, NULL, 0, bn_ctx))
|| !TEST_ptr(md_ctx = EVP_MD_CTX_new())
|| !TEST_true(EVP_DigestVerifyInit_ex(md_ctx, &pkey_ctx,
tst->digest_alg, libctx, NULL,
pkey, NULL))
|| !TEST_true(EVP_PKEY_CTX_set_params(pkey_ctx, params))
|| !TEST_int_eq(EVP_DigestVerify(md_ctx, tst->sig, tst->sig_len,
tst->msg, tst->msg_len), tst->pass))
goto err;
ret = 1;
err:
EVP_PKEY_free(pkey);
BN_CTX_free(bn_ctx);
EVP_MD_CTX_free(md_ctx);
return ret;
}
static int rsa_decryption_primitive_test(int id)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
unsigned char pt[2048];
size_t pt_len = sizeof(pt);
unsigned char *n = NULL, *e = NULL;
size_t n_len = 0, e_len = 0;
BN_CTX *bn_ctx = NULL;
const struct rsa_decrypt_prim_st *tst = &rsa_decrypt_prim_data[id];
- if (!TEST_ptr(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "RSA", 2048))
+ if (!TEST_ptr(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "RSA", (size_t)2048))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_N, &n, &n_len))
|| !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_E, &e, &e_len))
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, ""))
|| !TEST_int_gt(EVP_PKEY_decrypt_init(ctx), 0)
|| !TEST_int_gt(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING), 0))
goto err;
test_output_memory("n", n, n_len);
test_output_memory("e", e, e_len);
if (EVP_PKEY_decrypt(ctx, pt, &pt_len, tst->ct, tst->ct_len) <= 0)
TEST_note("Decryption Failed");
else
test_output_memory("pt", pt, pt_len);
ret = 1;
err:
OPENSSL_free(n);
OPENSSL_free(e);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
BN_CTX_free(bn_ctx);
return ret;
}
static int self_test_events(const OSSL_PARAM params[], void *varg)
{
SELF_TEST_ARGS *args = varg;
const OSSL_PARAM *p = NULL;
const char *phase = NULL, *type = NULL, *desc = NULL;
int ret = 0;
if (!args->enable)
return 1;
args->called++;
p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
phase = (const char *)p->data;
p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
desc = (const char *)p->data;
p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
type = (const char *)p->data;
BIO_printf(bio_out, "%s %s %s\n", phase, desc, type);
ret = 1;
err:
return ret;
}
static int drbg_test(int id)
{
OSSL_PARAM params[3];
EVP_RAND *rand = NULL;
EVP_RAND_CTX *ctx = NULL, *parent = NULL;
unsigned char returned_bits[64];
const size_t returned_bits_len = sizeof(returned_bits);
unsigned int strength = 256;
const struct drbg_st *tst = &drbg_data[id];
int res = 0;
/* Create the seed source */
if (!TEST_ptr(rand = EVP_RAND_fetch(libctx, "TEST-RAND", "-fips"))
|| !TEST_ptr(parent = EVP_RAND_CTX_new(rand, NULL)))
goto err;
EVP_RAND_free(rand);
rand = NULL;
params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &strength);
params[1] = OSSL_PARAM_construct_end();
if (!TEST_true(EVP_RAND_CTX_set_params(parent, params)))
goto err;
/* Get the DRBG */
if (!TEST_ptr(rand = EVP_RAND_fetch(libctx, tst->drbg_name, ""))
|| !TEST_ptr(ctx = EVP_RAND_CTX_new(rand, parent)))
goto err;
/* Set the DRBG up */
params[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_USE_DF,
(int *)&tst->use_df);
params[1] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
(char *)tst->cipher, 0);
params[2] = OSSL_PARAM_construct_end();
if (!TEST_true(EVP_RAND_CTX_set_params(ctx, params)))
goto err;
/* Feed in the entropy and nonce */
params[0] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
(void *)tst->entropy_input,
tst->entropy_input_len);
params[1] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE,
(void *)tst->nonce,
tst->nonce_len);
params[2] = OSSL_PARAM_construct_end();
if (!TEST_true(EVP_RAND_CTX_set_params(parent, params)))
goto err;
/*
* Run the test
* A NULL personalisation string defaults to the built in so something
* non-NULL is needed if there is no personalisation string
*/
if (!TEST_true(EVP_RAND_instantiate(ctx, 0, 0, (void *)"", 0, NULL))
|| !TEST_true(EVP_RAND_generate(ctx, returned_bits, returned_bits_len,
0, 0, NULL, 0))
|| !TEST_true(EVP_RAND_generate(ctx, returned_bits, returned_bits_len,
0, 0, NULL, 0)))
goto err;
test_output_memory("returned bits", returned_bits, returned_bits_len);
/* Clean up */
if (!TEST_true(EVP_RAND_uninstantiate(ctx))
|| !TEST_true(EVP_RAND_uninstantiate(parent)))
goto err;
/* Verify the output */
if (!TEST_mem_eq(returned_bits, returned_bits_len,
tst->returned_bits, tst->returned_bits_len))
goto err;
res = 1;
err:
EVP_RAND_CTX_free(ctx);
EVP_RAND_CTX_free(parent);
EVP_RAND_free(rand);
return res;
}
static int aes_cfb1_bits_test(void)
{
int ret = 0;
EVP_CIPHER *cipher = NULL;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char out[16] = { 0 };
int outlen;
const OSSL_PARAM *params, *p;
static const unsigned char key[] = {
0x12, 0x22, 0x58, 0x2F, 0x1C, 0x1A, 0x8A, 0x88,
0x30, 0xFC, 0x18, 0xB7, 0x24, 0x89, 0x7F, 0xC0
};
static const unsigned char iv[] = {
0x05, 0x28, 0xB5, 0x2B, 0x58, 0x27, 0x63, 0x5C,
0x81, 0x86, 0xD3, 0x63, 0x60, 0xB0, 0xAA, 0x2B
};
static const unsigned char pt[] = {
0xB4
};
static const unsigned char expected[] = {
0x6C
};
if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, "AES-128-CFB1", "fips=yes")))
goto err;
if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()))
goto err;
if (!TEST_int_gt(EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1), 0))
goto err;
if (!TEST_ptr(params = EVP_CIPHER_CTX_settable_params(ctx))
|| !TEST_ptr(p = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_USE_BITS)))
goto err;
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS);
if (!TEST_int_gt(EVP_CipherUpdate(ctx, out, &outlen, pt, 7), 0))
goto err;
if (!TEST_int_eq(outlen, 7))
goto err;
if (!TEST_mem_eq(out, (outlen + 7) / 8, expected, sizeof(expected)))
goto err;
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
int setup_tests(void)
{
char *config_file = NULL;
OPTION_CHOICE o;
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_CONFIG_FILE:
config_file = opt_arg();
break;
case OPT_TEST_CASES:
break;
default:
case OPT_ERR:
return 0;
}
}
if (!test_get_libctx(&libctx, &prov_null, config_file, NULL, NULL))
return 0;
OSSL_SELF_TEST_set_callback(libctx, self_test_events, &self_test_args);
ADD_TEST(aes_cfb1_bits_test);
ADD_ALL_TESTS(cipher_enc_dec_test, OSSL_NELEM(cipher_enc_data));
ADD_ALL_TESTS(aes_ccm_enc_dec_test, OSSL_NELEM(aes_ccm_enc_data));
ADD_ALL_TESTS(aes_gcm_enc_dec_test, OSSL_NELEM(aes_gcm_enc_data));
ADD_ALL_TESTS(rsa_keygen_test, OSSL_NELEM(rsa_keygen_data));
ADD_ALL_TESTS(rsa_siggen_test, OSSL_NELEM(rsa_siggen_data));
ADD_ALL_TESTS(rsa_sigver_test, OSSL_NELEM(rsa_sigver_data));
ADD_ALL_TESTS(rsa_decryption_primitive_test,
OSSL_NELEM(rsa_decrypt_prim_data));
#ifndef OPENSSL_NO_DH
ADD_ALL_TESTS(dh_safe_prime_keygen_test,
OSSL_NELEM(dh_safe_prime_keygen_data));
ADD_ALL_TESTS(dh_safe_prime_keyver_test,
OSSL_NELEM(dh_safe_prime_keyver_data));
#endif /* OPENSSL_NO_DH */
#ifndef OPENSSL_NO_DSA
ADD_ALL_TESTS(dsa_keygen_test, OSSL_NELEM(dsa_keygen_data));
ADD_ALL_TESTS(dsa_paramgen_test, OSSL_NELEM(dsa_paramgen_data));
ADD_ALL_TESTS(dsa_pqver_test, OSSL_NELEM(dsa_pqver_data));
ADD_ALL_TESTS(dsa_siggen_test, OSSL_NELEM(dsa_siggen_data));
ADD_ALL_TESTS(dsa_sigver_test, OSSL_NELEM(dsa_sigver_data));
#endif /* OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_EC
ADD_ALL_TESTS(ecdsa_keygen_test, OSSL_NELEM(ecdsa_keygen_data));
ADD_ALL_TESTS(ecdsa_pub_verify_test, OSSL_NELEM(ecdsa_pv_data));
ADD_ALL_TESTS(ecdsa_siggen_test, OSSL_NELEM(ecdsa_siggen_data));
ADD_ALL_TESTS(ecdsa_sigver_test, OSSL_NELEM(ecdsa_sigver_data));
#endif /* OPENSSL_NO_EC */
ADD_ALL_TESTS(drbg_test, OSSL_NELEM(drbg_data));
return 1;
}
void cleanup_tests(void)
{
OSSL_PROVIDER_unload(prov_null);
OSSL_LIB_CTX_free(libctx);
}
diff --git a/crypto/openssl/test/build.info b/crypto/openssl/test/build.info
index 76ff945ab8b3..6089b8c97cf8 100644
--- a/crypto/openssl/test/build.info
+++ b/crypto/openssl/test/build.info
@@ -1,981 +1,985 @@
# TODO: use ../apps/libapps.a instead of direct ../apps/lib source.
# This can't currently be done, because some of its units drag in too many
# unresolved references that don't apply here.
# Most of all, ../apps/lib/apps.c needs to be divided in smaller pieces to
# be useful here.
#
# Auxiliary program source (copied from ../apps/build.info)
IF[{- $config{target} =~ /^(?:VC-|mingw|BC-)/ -}]
# It's called 'init', but doesn't have much 'init' in it...
$AUXLIBAPPSSRC=../apps/lib/win32_init.c
ENDIF
IF[{- $config{target} =~ /^vms-/ -}]
$AUXLIBAPPSSRC=../apps/lib/vms_term_sock.c ../apps/lib/vms_decc_argv.c
ENDIF
# Program init source, that don't have direct linkage with the rest of the
# source, and can therefore not be part of a library.
IF[{- !$disabled{uplink} -}]
$INITSRC=../ms/applink.c
ENDIF
$LIBAPPSSRC=../apps/lib/opt.c $AUXLIBAPPSSRC
IF[{- !$disabled{tests} -}]
LIBS{noinst,has_main}=libtestutil.a
SOURCE[libtestutil.a]=testutil/basic_output.c testutil/output.c \
testutil/driver.c testutil/tests.c testutil/cb.c testutil/stanza.c \
testutil/format_output.c testutil/load.c testutil/fake_random.c \
testutil/test_cleanup.c testutil/main.c testutil/testutil_init.c \
testutil/options.c testutil/test_options.c testutil/provider.c \
testutil/apps_shims.c testutil/random.c $LIBAPPSSRC
INCLUDE[libtestutil.a]=../include ../apps/include ..
DEPEND[libtestutil.a]=../libcrypto
PROGRAMS{noinst}= \
confdump \
versions \
aborttest test_test pkcs12_format_test \
sanitytest rsa_complex exdatatest bntest \
ecstresstest gmdifftest pbelutest \
destest mdc2test sha_test \
exptest pbetest localetest evp_pkey_ctx_new_from_name\
evp_pkey_provided_test evp_test evp_extra_test evp_extra_test2 \
evp_fetch_prov_test evp_libctx_test ossl_store_test \
v3nametest v3ext punycode_test evp_byname_test \
crltest danetest bad_dtls_test lhash_test sparse_array_test \
conf_include_test params_api_test params_conversion_test \
constant_time_test verify_extra_test clienthellotest \
packettest asynctest secmemtest srptest memleaktest stack_test \
dtlsv1listentest ct_test threadstest afalgtest d2i_test \
ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \
bio_callback_test bio_memleak_test bio_core_test param_build_test \
bioprinttest sslapitest dtlstest sslcorrupttest \
bio_enc_test pkey_meth_test pkey_meth_kdf_test evp_kdf_test uitest \
cipherbytes_test threadstest_fips \
asn1_encode_test asn1_decode_test asn1_string_table_test asn1_stable_parse_test \
x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
recordlentest drbgtest rand_status_test sslbuffertest \
time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \
http_test servername_test ocspapitest fatalerrtest tls13ccstest \
sysdefaulttest errtest ssl_ctx_test \
context_internal_test aesgcmtest params_test evp_pkey_dparams_test \
keymgmt_internal_test hexstr_test provider_status_test defltfips_test \
bio_readbuffer_test user_property_test pkcs7_test upcallstest \
provfetchtest prov_config_test rand_test fips_version_test \
- nodefltctxtest
+ nodefltctxtest bio_pw_callback_test
IF[{- !$disabled{'deprecated-3.0'} -}]
PROGRAMS{noinst}=enginetest
ENDIF
SOURCE[confdump]=confdump.c
INCLUDE[confdump]=../include ../apps/include
DEPEND[confdump]=../libcrypto
SOURCE[versions]=versions.c
INCLUDE[versions]=../include ../apps/include
DEPEND[versions]=../libcrypto
SOURCE[aborttest]=aborttest.c
INCLUDE[aborttest]=../include ../apps/include
DEPEND[aborttest]=../libcrypto
SOURCE[sanitytest]=sanitytest.c
INCLUDE[sanitytest]=../include ../apps/include
DEPEND[sanitytest]=../libcrypto libtestutil.a
SOURCE[rand_test]=rand_test.c
INCLUDE[rand_test]=../include ../apps/include
DEPEND[rand_test]=../libcrypto libtestutil.a
SOURCE[rsa_complex]=rsa_complex.c
INCLUDE[rsa_complex]=../include ../apps/include
SOURCE[test_test]=test_test.c
INCLUDE[test_test]=../include ../apps/include
DEPEND[test_test]=../libcrypto libtestutil.a
SOURCE[exdatatest]=exdatatest.c
INCLUDE[exdatatest]=../include ../apps/include
DEPEND[exdatatest]=../libcrypto libtestutil.a
SOURCE[bntest]=bntest.c
INCLUDE[bntest]=../include ../apps/include
DEPEND[bntest]=../libcrypto libtestutil.a
SOURCE[ectest]=ectest.c
INCLUDE[ectest]=../include ../apps/include
DEPEND[ectest]=../libcrypto.a libtestutil.a
SOURCE[ecstresstest]=ecstresstest.c
INCLUDE[ecstresstest]=../include ../apps/include
DEPEND[ecstresstest]=../libcrypto libtestutil.a
SOURCE[gmdifftest]=gmdifftest.c
INCLUDE[gmdifftest]=../include ../apps/include
DEPEND[gmdifftest]=../libcrypto libtestutil.a
SOURCE[pbelutest]=pbelutest.c
INCLUDE[pbelutest]=../include ../apps/include
DEPEND[pbelutest]=../libcrypto libtestutil.a
SOURCE[mdc2test]=mdc2test.c
INCLUDE[mdc2test]=../include ../apps/include
DEPEND[mdc2test]=../libcrypto libtestutil.a
SOURCE[sha_test]=sha_test.c
INCLUDE[sha_test]=../include ../apps/include
DEPEND[sha_test]=../libcrypto libtestutil.a
SOURCE[enginetest]=enginetest.c
INCLUDE[enginetest]=../include ../apps/include
DEPEND[enginetest]=../libcrypto libtestutil.a
SOURCE[exptest]=exptest.c
INCLUDE[exptest]=../include ../apps/include
DEPEND[exptest]=../libcrypto libtestutil.a
SOURCE[localetest]=localetest.c
INCLUDE[localetest]=../include ../apps/include
DEPEND[localetest]=../libcrypto libtestutil.a
SOURCE[evp_pkey_ctx_new_from_name]=evp_pkey_ctx_new_from_name.c
INCLUDE[evp_pkey_ctx_new_from_name]=../include ../apps/include
DEPEND[evp_pkey_ctx_new_from_name]=../libcrypto
SOURCE[pbetest]=pbetest.c
INCLUDE[pbetest]=../include ../apps/include
DEPEND[pbetest]=../libcrypto libtestutil.a
SOURCE[fatalerrtest]=fatalerrtest.c helpers/ssltestlib.c
INCLUDE[fatalerrtest]=../include ../apps/include
DEPEND[fatalerrtest]=../libcrypto ../libssl libtestutil.a
SOURCE[tls13ccstest]=tls13ccstest.c helpers/ssltestlib.c
INCLUDE[tls13ccstest]=../include ../apps/include
DEPEND[tls13ccstest]=../libcrypto ../libssl libtestutil.a
SOURCE[upcallstest]=upcallstest.c
INCLUDE[upcallstest]=../include ../apps/include
DEPEND[upcallstest]=../libcrypto libtestutil.a
SOURCE[user_property_test]=user_property_test.c
INCLUDE[user_property_test]=../include ../apps/include
DEPEND[user_property_test]=../libcrypto libtestutil.a
SOURCE[evp_test]=evp_test.c
INCLUDE[evp_test]=../include ../apps/include
DEPEND[evp_test]=../libcrypto libtestutil.a
IF[{- $disabled{legacy} || !$target{dso_scheme} -}]
DEFINE[evp_test]=NO_LEGACY_MODULE
ENDIF
SOURCE[evp_extra_test]=evp_extra_test.c
INCLUDE[evp_extra_test]=../include ../apps/include
DEPEND[evp_extra_test]=../libcrypto.a libtestutil.a
IF[{- !$disabled{module} && !$disabled{legacy} -}]
DEFINE[evp_extra_test]=STATIC_LEGACY
SOURCE[evp_extra_test]=../providers/legacyprov.c
INCLUDE[evp_extra_test]=../providers/common/include \
../providers/implementations/include
DEPEND[evp_extra_test]=../providers/liblegacy.a \
../providers/libcommon.a
ENDIF
SOURCE[evp_extra_test2]=evp_extra_test2.c
INCLUDE[evp_extra_test2]=../include ../apps/include
DEPEND[evp_extra_test2]=../libcrypto libtestutil.a
SOURCE[evp_libctx_test]=evp_libctx_test.c
INCLUDE[evp_libctx_test]=../include ../apps/include
DEPEND[evp_libctx_test]=../libcrypto.a libtestutil.a
SOURCE[evp_fetch_prov_test]=evp_fetch_prov_test.c
INCLUDE[evp_fetch_prov_test]=../include ../apps/include
DEPEND[evp_fetch_prov_test]=../libcrypto libtestutil.a
SOURCE[provfetchtest]=provfetchtest.c
INCLUDE[provfetchtest]=../include ../apps/include
DEPEND[provfetchtest]=../libcrypto.a libtestutil.a
SOURCE[prov_config_test]=prov_config_test.c
INCLUDE[prov_config_test]=../include ../apps/include
DEPEND[prov_config_test]=../libcrypto.a libtestutil.a
SOURCE[evp_pkey_provided_test]=evp_pkey_provided_test.c
INCLUDE[evp_pkey_provided_test]=../include ../apps/include
DEPEND[evp_pkey_provided_test]=../libcrypto.a libtestutil.a
IF[{- !$disabled{'acvp-tests'} -}]
PROGRAMS{noinst}=acvp_test
SOURCE[acvp_test]=acvp_test.c
INCLUDE[acvp_test]=../include ../apps/include
DEPEND[acvp_test]=../libcrypto.a libtestutil.a
ENDIF
SOURCE[ossl_store_test]=ossl_store_test.c
INCLUDE[ossl_store_test]=../include ../apps/include
DEPEND[ossl_store_test]=../libcrypto.a libtestutil.a
SOURCE[provider_status_test]=provider_status_test.c
INCLUDE[provider_status_test]=../include ../apps/include
DEPEND[provider_status_test]=../libcrypto.a libtestutil.a
SOURCE[nodefltctxtest]=nodefltctxtest.c
INCLUDE[nodefltctxtest]=../include ../apps/include
DEPEND[nodefltctxtest]=../libcrypto.a libtestutil.a
IF[{- !$disabled{'deprecated-3.0'} -}]
PROGRAMS{noinst}=igetest bftest casttest
SOURCE[igetest]=igetest.c
INCLUDE[igetest]=../include ../apps/include
DEPEND[igetest]=../libcrypto libtestutil.a
SOURCE[bftest]=bftest.c
INCLUDE[bftest]=../include ../apps/include
DEPEND[bftest]=../libcrypto libtestutil.a
SOURCE[casttest]=casttest.c
INCLUDE[casttest]=../include ../apps/include
DEPEND[casttest]=../libcrypto libtestutil.a
ENDIF
SOURCE[v3nametest]=v3nametest.c
INCLUDE[v3nametest]=../include ../apps/include
DEPEND[v3nametest]=../libcrypto libtestutil.a
SOURCE[crltest]=crltest.c
INCLUDE[crltest]=../include ../apps/include
DEPEND[crltest]=../libcrypto libtestutil.a
SOURCE[v3ext]=v3ext.c
INCLUDE[v3ext]=../include ../apps/include
DEPEND[v3ext]=../libcrypto libtestutil.a
SOURCE[danetest]=danetest.c
INCLUDE[danetest]=../include ../apps/include
DEPEND[danetest]=../libcrypto ../libssl libtestutil.a
SOURCE[constant_time_test]=constant_time_test.c
INCLUDE[constant_time_test]=../include ../apps/include
DEPEND[constant_time_test]=../libcrypto libtestutil.a
SOURCE[verify_extra_test]=verify_extra_test.c
INCLUDE[verify_extra_test]=../include ../apps/include
DEPEND[verify_extra_test]=../libcrypto libtestutil.a
SOURCE[clienthellotest]=clienthellotest.c
INCLUDE[clienthellotest]=../include ../apps/include
DEPEND[clienthellotest]=../libcrypto ../libssl libtestutil.a
SOURCE[bad_dtls_test]=bad_dtls_test.c
INCLUDE[bad_dtls_test]=../include ../apps/include
DEPEND[bad_dtls_test]=../libcrypto ../libssl libtestutil.a
SOURCE[packettest]=packettest.c
INCLUDE[packettest]=../include ../apps/include
DEPEND[packettest]=../libcrypto libtestutil.a
SOURCE[asynctest]=asynctest.c
INCLUDE[asynctest]=../include ../apps/include
DEPEND[asynctest]=../libcrypto
SOURCE[secmemtest]=secmemtest.c
INCLUDE[secmemtest]=../include ../apps/include
DEPEND[secmemtest]=../libcrypto libtestutil.a
SOURCE[srptest]=srptest.c
INCLUDE[srptest]=../include ../apps/include
DEPEND[srptest]=../libcrypto libtestutil.a
SOURCE[memleaktest]=memleaktest.c
INCLUDE[memleaktest]=../include ../apps/include
DEPEND[memleaktest]=../libcrypto libtestutil.a
SOURCE[pkcs12_format_test]=pkcs12_format_test.c helpers/pkcs12.c
INCLUDE[pkcs12_format_test]=../include ../apps/include
DEPEND[pkcs12_format_test]=../libcrypto libtestutil.a
SOURCE[pkcs7_test]=pkcs7_test.c
INCLUDE[pkcs7_test]=../include ../apps/include
DEPEND[pkcs7_test]=../libcrypto libtestutil.a
SOURCE[punycode_test]=punycode_test.c
INCLUDE[punycode_test]=../include ../apps/include
DEPEND[punycode_test]=../libcrypto.a libtestutil.a
SOURCE[evp_byname_test]=evp_byname_test.c
INCLUDE[evp_byname_test]=../include ../apps/include
DEPEND[evp_byname_test]=../libcrypto libtestutil.a
SOURCE[stack_test]=stack_test.c
INCLUDE[stack_test]=../include ../apps/include
DEPEND[stack_test]=../libcrypto libtestutil.a
SOURCE[lhash_test]=lhash_test.c
INCLUDE[lhash_test]=../include ../apps/include
DEPEND[lhash_test]=../libcrypto libtestutil.a
SOURCE[dtlsv1listentest]=dtlsv1listentest.c
INCLUDE[dtlsv1listentest]=../include ../apps/include
DEPEND[dtlsv1listentest]=../libssl libtestutil.a
SOURCE[ct_test]=ct_test.c
INCLUDE[ct_test]=../include ../apps/include
DEPEND[ct_test]=../libcrypto libtestutil.a
SOURCE[threadstest]=threadstest.c
INCLUDE[threadstest]=../include ../apps/include
DEPEND[threadstest]=../libcrypto libtestutil.a
SOURCE[threadstest_fips]=threadstest_fips.c
INCLUDE[threadstest_fips]=../include ../apps/include
DEPEND[threadstest_fips]=../libcrypto libtestutil.a
SOURCE[afalgtest]=afalgtest.c
INCLUDE[afalgtest]=../include ../apps/include
DEPEND[afalgtest]=../libcrypto libtestutil.a
SOURCE[d2i_test]=d2i_test.c
INCLUDE[d2i_test]=../include ../apps/include
DEPEND[d2i_test]=../libcrypto libtestutil.a
SOURCE[ssl_test_ctx_test]=ssl_test_ctx_test.c helpers/ssl_test_ctx.c
INCLUDE[ssl_test_ctx_test]=../include ../apps/include
DEPEND[ssl_test_ctx_test]=../libcrypto ../libssl libtestutil.a
SOURCE[ssl_test]=ssl_test.c helpers/ssl_test_ctx.c helpers/handshake.c
IF[{- !$disabled{'srp'} -}]
SOURCE[ssl_test]=helpers/handshake_srp.c
ENDIF
INCLUDE[ssl_test]=../include ../apps/include
DEPEND[ssl_test]=../libcrypto ../libssl libtestutil.a
SOURCE[cipherlist_test]=cipherlist_test.c
INCLUDE[cipherlist_test]=../include ../apps/include
DEPEND[cipherlist_test]=../libcrypto ../libssl libtestutil.a
INCLUDE[helpers/ssl_test_ctx.o]=../include
INCLUDE[helpers/handshake.o]=.. ../include
INCLUDE[helpers/pkcs12.o]=.. ../include
INCLUDE[helpers/ssltestlib.o]=.. ../include
INCLUDE[helpers/cmp_testlib.o]=.. ../include ../apps/include
SOURCE[x509aux]=x509aux.c
INCLUDE[x509aux]=../include ../apps/include
DEPEND[x509aux]=../libcrypto libtestutil.a
SOURCE[asynciotest]=asynciotest.c helpers/ssltestlib.c
INCLUDE[asynciotest]=../include ../apps/include
DEPEND[asynciotest]=../libcrypto ../libssl libtestutil.a
SOURCE[bio_callback_test]=bio_callback_test.c
INCLUDE[bio_callback_test]=../include ../apps/include
DEPEND[bio_callback_test]=../libcrypto libtestutil.a
SOURCE[bio_readbuffer_test]=bio_readbuffer_test.c
INCLUDE[bio_readbuffer_test]=../include ../apps/include
DEPEND[bio_readbuffer_test]=../libcrypto libtestutil.a
SOURCE[bio_memleak_test]=bio_memleak_test.c
INCLUDE[bio_memleak_test]=../include ../apps/include
DEPEND[bio_memleak_test]=../libcrypto libtestutil.a
SOURCE[bioprinttest]=bioprinttest.c
INCLUDE[bioprinttest]=../include ../apps/include
DEPEND[bioprinttest]=../libcrypto libtestutil.a
SOURCE[bio_core_test]=bio_core_test.c
INCLUDE[bio_core_test]=../include ../apps/include
DEPEND[bio_core_test]=../libcrypto libtestutil.a
SOURCE[params_api_test]=params_api_test.c
INCLUDE[params_api_test]=../include ../apps/include
DEPEND[params_api_test]=../libcrypto libtestutil.a
SOURCE[params_conversion_test]=params_conversion_test.c
INCLUDE[params_conversion_test]=../include ../apps/include
DEPEND[params_conversion_test]=../libcrypto libtestutil.a
SOURCE[param_build_test]=param_build_test.c
INCLUDE[param_build_test]=../include ../apps/include
DEPEND[param_build_test]=../libcrypto.a libtestutil.a
SOURCE[sslapitest]=sslapitest.c helpers/ssltestlib.c filterprov.c tls-provider.c
INCLUDE[sslapitest]=../include ../apps/include ..
DEPEND[sslapitest]=../libcrypto ../libssl libtestutil.a
SOURCE[defltfips_test]=defltfips_test.c
INCLUDE[defltfips_test]=../include ../apps/include
DEPEND[defltfips_test]=../libcrypto libtestutil.a
SOURCE[fips_version_test]=fips_version_test.c
INCLUDE[fips_version_test]=../include ../apps/include
DEPEND[fips_version_test]=../libcrypto libtestutil.a
SOURCE[ocspapitest]=ocspapitest.c
INCLUDE[ocspapitest]=../include ../apps/include
DEPEND[ocspapitest]=../libcrypto libtestutil.a
IF[{- !$disabled{sock} -}]
PROGRAMS{noinst}=http_test
ENDIF
SOURCE[http_test]=http_test.c
INCLUDE[http_test]=../include ../apps/include
DEPEND[http_test]=../libcrypto libtestutil.a
SOURCE[dtlstest]=dtlstest.c helpers/ssltestlib.c
INCLUDE[dtlstest]=../include ../apps/include
DEPEND[dtlstest]=../libcrypto ../libssl libtestutil.a
SOURCE[sslcorrupttest]=sslcorrupttest.c helpers/ssltestlib.c
INCLUDE[sslcorrupttest]=../include ../apps/include
DEPEND[sslcorrupttest]=../libcrypto ../libssl libtestutil.a
SOURCE[bio_enc_test]=bio_enc_test.c
INCLUDE[bio_enc_test]=../include ../apps/include
DEPEND[bio_enc_test]=../libcrypto libtestutil.a
SOURCE[pkey_meth_test]=pkey_meth_test.c
INCLUDE[pkey_meth_test]=../include ../apps/include
DEPEND[pkey_meth_test]=../libcrypto libtestutil.a
SOURCE[pkey_meth_kdf_test]=pkey_meth_kdf_test.c
INCLUDE[pkey_meth_kdf_test]=../include ../apps/include
DEPEND[pkey_meth_kdf_test]=../libcrypto libtestutil.a
SOURCE[evp_kdf_test]=evp_kdf_test.c
INCLUDE[evp_kdf_test]=../include ../apps/include
DEPEND[evp_kdf_test]=../libcrypto libtestutil.a
SOURCE[evp_pkey_dparams_test]=evp_pkey_dparams_test.c
INCLUDE[evp_pkey_dparams_test]=../include ../apps/include
DEPEND[evp_pkey_dparams_test]=../libcrypto libtestutil.a
SOURCE[x509_time_test]=x509_time_test.c
INCLUDE[x509_time_test]=../include ../apps/include
DEPEND[x509_time_test]=../libcrypto libtestutil.a
SOURCE[recordlentest]=recordlentest.c helpers/ssltestlib.c
INCLUDE[recordlentest]=../include ../apps/include
DEPEND[recordlentest]=../libcrypto ../libssl libtestutil.a
SOURCE[drbgtest]=drbgtest.c
INCLUDE[drbgtest]=../include ../apps/include ../providers/common/include
DEPEND[drbgtest]=../libcrypto.a libtestutil.a
SOURCE[rand_status_test]=rand_status_test.c
INCLUDE[rand_status_test]=../include ../apps/include
DEPEND[rand_status_test]=../libcrypto libtestutil.a
SOURCE[x509_dup_cert_test]=x509_dup_cert_test.c
INCLUDE[x509_dup_cert_test]=../include ../apps/include
DEPEND[x509_dup_cert_test]=../libcrypto libtestutil.a
SOURCE[x509_check_cert_pkey_test]=x509_check_cert_pkey_test.c
INCLUDE[x509_check_cert_pkey_test]=../include ../apps/include
DEPEND[x509_check_cert_pkey_test]=../libcrypto libtestutil.a
SOURCE[pemtest]=pemtest.c
INCLUDE[pemtest]=../include ../apps/include
DEPEND[pemtest]=../libcrypto libtestutil.a
SOURCE[ssl_cert_table_internal_test]=ssl_cert_table_internal_test.c
INCLUDE[ssl_cert_table_internal_test]=.. ../include ../apps/include
DEPEND[ssl_cert_table_internal_test]=../libcrypto libtestutil.a
SOURCE[ciphername_test]=ciphername_test.c
INCLUDE[ciphername_test]=../include ../apps/include
DEPEND[ciphername_test]=../libcrypto ../libssl libtestutil.a
SOURCE[http_test]=http_test.c
INCLUDE[http_test]=../include ../apps/include
DEPEND[http_test]=../libcrypto libtestutil.a
SOURCE[servername_test]=servername_test.c helpers/ssltestlib.c
INCLUDE[servername_test]=../include ../apps/include
DEPEND[servername_test]=../libcrypto ../libssl libtestutil.a
IF[{- !$disabled{cms} -}]
PROGRAMS{noinst}=cmsapitest
SOURCE[cmsapitest]=cmsapitest.c
INCLUDE[cmsapitest]=../include ../apps/include
DEPEND[cmsapitest]=../libcrypto libtestutil.a
ENDIF
IF[{- !$disabled{psk} -}]
PROGRAMS{noinst}=dtls_mtu_test
SOURCE[dtls_mtu_test]=dtls_mtu_test.c helpers/ssltestlib.c
INCLUDE[dtls_mtu_test]=.. ../include ../apps/include
DEPEND[dtls_mtu_test]=../libcrypto ../libssl libtestutil.a
ENDIF
IF[{- !$disabled{shared} -}]
PROGRAMS{noinst}=shlibloadtest
SOURCE[shlibloadtest]=shlibloadtest.c simpledynamic.c
INCLUDE[shlibloadtest]=../include ../apps/include
PROGRAMS{noinst}=moduleloadtest
SOURCE[moduleloadtest]=moduleloadtest.c simpledynamic.c
INCLUDE[moduleloadtest]=../include ../apps/include
ENDIF
# cipher_overhead_test uses internal symbols, so it must be linked with
# the static libraries
PROGRAMS{noinst}=cipher_overhead_test
SOURCE[cipher_overhead_test]=cipher_overhead_test.c
INCLUDE[cipher_overhead_test]=.. ../include ../apps/include
DEPEND[cipher_overhead_test]=../libcrypto.a ../libssl.a libtestutil.a
SOURCE[uitest]=uitest.c ../apps/lib/apps_ui.c
INCLUDE[uitest]=.. ../include ../apps/include
DEPEND[uitest]=../libcrypto ../libssl libtestutil.a
SOURCE[cipherbytes_test]=cipherbytes_test.c
INCLUDE[cipherbytes_test]=../include ../apps/include
DEPEND[cipherbytes_test]=../libcrypto ../libssl libtestutil.a
SOURCE[asn1_encode_test]=asn1_encode_test.c
INCLUDE[asn1_encode_test]=../include ../apps/include
DEPEND[asn1_encode_test]=../libcrypto libtestutil.a
SOURCE[asn1_decode_test]=asn1_decode_test.c
INCLUDE[asn1_decode_test]=../include ../apps/include
DEPEND[asn1_decode_test]=../libcrypto libtestutil.a
SOURCE[asn1_string_table_test]=asn1_string_table_test.c
INCLUDE[asn1_string_table_test]=../include ../apps/include
DEPEND[asn1_string_table_test]=../libcrypto libtestutil.a
SOURCE[asn1_stable_parse_test]=asn1_stable_parse_test.c
INCLUDE[asn1_stable_parse_test]=../include ../apps/include
DEPEND[asn1_stable_parse_test]=../libcrypto libtestutil.a
SOURCE[time_offset_test]=time_offset_test.c
INCLUDE[time_offset_test]=../include ../apps/include
DEPEND[time_offset_test]=../libcrypto libtestutil.a
SOURCE[conf_include_test]=conf_include_test.c
INCLUDE[conf_include_test]=../include ../apps/include
DEPEND[conf_include_test]=../libcrypto libtestutil.a
IF[{- !$disabled{cmp} -}]
PROGRAMS{noinst}=cmp_asn_test cmp_ctx_test cmp_status_test cmp_hdr_test \
cmp_protect_test cmp_msg_test cmp_vfy_test \
cmp_server_test cmp_client_test
ENDIF
SOURCE[cmp_asn_test]=cmp_asn_test.c helpers/cmp_testlib.c
INCLUDE[cmp_asn_test]=.. ../include ../apps/include
DEPEND[cmp_asn_test]=../libcrypto.a libtestutil.a
SOURCE[cmp_ctx_test]=cmp_ctx_test.c helpers/cmp_testlib.c
INCLUDE[cmp_ctx_test]=.. ../include ../apps/include
DEPEND[cmp_ctx_test]=../libcrypto.a libtestutil.a
SOURCE[cmp_hdr_test]=cmp_hdr_test.c helpers/cmp_testlib.c
INCLUDE[cmp_hdr_test]=.. ../include ../apps/include
DEPEND[cmp_hdr_test]=../libcrypto.a libtestutil.a
SOURCE[cmp_status_test]=cmp_status_test.c helpers/cmp_testlib.c
INCLUDE[cmp_status_test]=.. ../include ../apps/include
DEPEND[cmp_status_test]=../libcrypto.a libtestutil.a
SOURCE[cmp_protect_test]=cmp_protect_test.c helpers/cmp_testlib.c
INCLUDE[cmp_protect_test]=.. ../include ../apps/include
DEPEND[cmp_protect_test]=../libcrypto.a libtestutil.a
SOURCE[cmp_msg_test]=cmp_msg_test.c helpers/cmp_testlib.c
INCLUDE[cmp_msg_test]=.. ../include ../apps/include
DEPEND[cmp_msg_test]=../libcrypto.a libtestutil.a
SOURCE[cmp_vfy_test]=cmp_vfy_test.c helpers/cmp_testlib.c
INCLUDE[cmp_vfy_test]=.. ../include ../apps/include
DEPEND[cmp_vfy_test]=../libcrypto.a libtestutil.a
SOURCE[cmp_server_test]=cmp_server_test.c helpers/cmp_testlib.c
INCLUDE[cmp_server_test]=.. ../include ../apps/include
DEPEND[cmp_server_test]=../libcrypto.a libtestutil.a
SOURCE[cmp_client_test]=cmp_client_test.c helpers/cmp_testlib.c ../apps/lib/cmp_mock_srv.c
INCLUDE[cmp_client_test]=.. ../include ../apps/include
DEPEND[cmp_client_test]=../libcrypto.a libtestutil.a
# Internal test programs. These are essentially a collection of internal
# test routines. Some of them need to reach internal symbols that aren't
# available through the shared library (at least on Linux, Solaris, Windows
# and VMS, where the exported symbols are those listed in util/*.num), these
# programs are forcibly linked with the static libraries, where all symbols
# are always available.
IF[1]
PROGRAMS{noinst}=asn1_internal_test modes_internal_test x509_internal_test \
tls13encryptiontest wpackettest ctype_internal_test \
rdrand_sanitytest property_test ideatest rsa_mp_test \
rsa_sp800_56b_test bn_internal_test ecdsatest rsa_test \
rc2test rc4test rc5test hmactest ffc_internal_test \
asn1_dsa_internal_test dsatest dsa_no_digest_size_test \
dhtest ssl_old_test
IF[{- !$disabled{poly1305} -}]
PROGRAMS{noinst}=poly1305_internal_test
ENDIF
IF[{- !$disabled{chacha} -}]
PROGRAMS{noinst}=chacha_internal_test
ENDIF
IF[{- !$disabled{siphash} -}]
PROGRAMS{noinst}=siphash_internal_test
ENDIF
IF[{- !$disabled{sm2} -}]
PROGRAMS{noinst}=sm2_internal_test
ENDIF
IF[{- !$disabled{sm3} -}]
PROGRAMS{noinst}=sm3_internal_test
ENDIF
IF[{- !$disabled{sm4} -}]
PROGRAMS{noinst}=sm4_internal_test
ENDIF
IF[{- !$disabled{ec} -}]
PROGRAMS{noinst}=ectest ec_internal_test curve448_internal_test
ENDIF
IF[{- !$disabled{cmac} -}]
PROGRAMS{noinst}=cmactest
ENDIF
SOURCE[poly1305_internal_test]=poly1305_internal_test.c
INCLUDE[poly1305_internal_test]=.. ../include ../apps/include
DEPEND[poly1305_internal_test]=../libcrypto.a libtestutil.a
SOURCE[chacha_internal_test]=chacha_internal_test.c
INCLUDE[chacha_internal_test]=.. ../include ../apps/include
DEPEND[chacha_internal_test]=../libcrypto.a libtestutil.a
SOURCE[asn1_internal_test]=asn1_internal_test.c
INCLUDE[asn1_internal_test]=.. ../include ../apps/include
DEPEND[asn1_internal_test]=../libcrypto.a libtestutil.a
SOURCE[modes_internal_test]=modes_internal_test.c
INCLUDE[modes_internal_test]=.. ../include ../apps/include
DEPEND[modes_internal_test]=../libcrypto.a libtestutil.a
SOURCE[x509_internal_test]=x509_internal_test.c
INCLUDE[x509_internal_test]=.. ../include ../apps/include
DEPEND[x509_internal_test]=../libcrypto.a libtestutil.a
SOURCE[rsa_test]=rsa_test.c
INCLUDE[rsa_test]=../include ../apps/include
DEPEND[rsa_test]=../libcrypto.a libtestutil.a
SOURCE[rsa_mp_test]=rsa_mp_test.c
INCLUDE[rsa_mp_test]=../include ../apps/include
DEPEND[rsa_mp_test]=../libcrypto.a libtestutil.a
SOURCE[ecdsatest]=ecdsatest.c
INCLUDE[ecdsatest]=../include ../apps/include
DEPEND[ecdsatest]=../libcrypto.a libtestutil.a
SOURCE[dsatest]=dsatest.c
INCLUDE[dsatest]=../include ../apps/include
DEPEND[dsatest]=../libcrypto.a libtestutil.a
SOURCE[dsa_no_digest_size_test]=dsa_no_digest_size_test.c
INCLUDE[dsa_no_digest_size_test]=../include ../apps/include
DEPEND[dsa_no_digest_size_test]=../libcrypto.a libtestutil.a
SOURCE[tls13encryptiontest]=tls13encryptiontest.c
INCLUDE[tls13encryptiontest]=.. ../include ../apps/include
DEPEND[tls13encryptiontest]=../libcrypto.a ../libssl.a libtestutil.a
SOURCE[ideatest]=ideatest.c
INCLUDE[ideatest]=../include ../apps/include
DEPEND[ideatest]=../libcrypto.a libtestutil.a
SOURCE[wpackettest]=wpackettest.c
INCLUDE[wpackettest]=../include ../apps/include
DEPEND[wpackettest]=../libcrypto.a ../libssl.a libtestutil.a
SOURCE[property_test]=property_test.c
INCLUDE[property_test]=.. ../include ../apps/include
DEPEND[property_test]=../libcrypto.a libtestutil.a
SOURCE[ctype_internal_test]=ctype_internal_test.c
INCLUDE[ctype_internal_test]=.. ../include ../apps/include
DEPEND[ctype_internal_test]=../libcrypto.a libtestutil.a
SOURCE[sparse_array_test]=sparse_array_test.c
INCLUDE[sparse_array_test]=../include ../apps/include
DEPEND[sparse_array_test]=../libcrypto.a libtestutil.a
SOURCE[dhtest]=dhtest.c
INCLUDE[dhtest]=../include ../apps/include
DEPEND[dhtest]=../libcrypto.a libtestutil.a
SOURCE[hmactest]=hmactest.c
INCLUDE[hmactest]=../include ../apps/include
DEPEND[hmactest]=../libcrypto.a libtestutil.a
IF[{- !$disabled{cmac} -}]
SOURCE[cmactest]=cmactest.c
INCLUDE[cmactest]=../include ../apps/include
DEPEND[cmactest]=../libcrypto.a libtestutil.a
ENDIF
SOURCE[siphash_internal_test]=siphash_internal_test.c
INCLUDE[siphash_internal_test]=.. ../include ../apps/include
DEPEND[siphash_internal_test]=../libcrypto.a libtestutil.a
SOURCE[sm2_internal_test]=sm2_internal_test.c
INCLUDE[sm2_internal_test]=../include ../apps/include
DEPEND[sm2_internal_test]=../libcrypto.a libtestutil.a
SOURCE[sm3_internal_test]=sm3_internal_test.c
INCLUDE[sm3_internal_test]=../include ../apps/include
DEPEND[sm3_internal_test]=../libcrypto.a libtestutil.a
SOURCE[sm4_internal_test]=sm4_internal_test.c
INCLUDE[sm4_internal_test]=.. ../include ../apps/include
DEPEND[sm4_internal_test]=../libcrypto.a libtestutil.a
SOURCE[destest]=destest.c
INCLUDE[destest]=../include ../apps/include
DEPEND[destest]=../libcrypto.a libtestutil.a
SOURCE[rc2test]=rc2test.c
INCLUDE[rc2test]=../include ../apps/include
DEPEND[rc2test]=../libcrypto.a libtestutil.a
SOURCE[rc4test]=rc4test.c
INCLUDE[rc4test]=../include ../apps/include
DEPEND[rc4test]=../libcrypto.a libtestutil.a
SOURCE[rc5test]=rc5test.c
INCLUDE[rc5test]=../include ../apps/include
DEPEND[rc5test]=../libcrypto.a libtestutil.a
SOURCE[ec_internal_test]=ec_internal_test.c $INITSRC
INCLUDE[ec_internal_test]=../include ../crypto/ec ../apps/include
DEPEND[ec_internal_test]=../libcrypto.a libtestutil.a
SOURCE[curve448_internal_test]=curve448_internal_test.c
INCLUDE[curve448_internal_test]=.. ../include ../apps/include ../crypto/ec/curve448
DEPEND[curve448_internal_test]=../libcrypto.a libtestutil.a
SOURCE[rc4test]=rc4test.c
INCLUDE[rc4test]=../include ../apps/include
DEPEND[rc4test]=../libcrypto.a libtestutil.a
SOURCE[rdrand_sanitytest]=rdrand_sanitytest.c
INCLUDE[rdrand_sanitytest]=../include ../apps/include
DEPEND[rdrand_sanitytest]=../libcrypto.a libtestutil.a
SOURCE[rsa_sp800_56b_test]=rsa_sp800_56b_test.c
INCLUDE[rsa_sp800_56b_test]=.. ../include ../crypto/rsa ../apps/include
DEPEND[rsa_sp800_56b_test]=../libcrypto.a libtestutil.a
SOURCE[bn_internal_test]=bn_internal_test.c
INCLUDE[bn_internal_test]=.. ../include ../crypto/bn ../apps/include
DEPEND[bn_internal_test]=../libcrypto.a libtestutil.a
SOURCE[asn1_dsa_internal_test]=asn1_dsa_internal_test.c
INCLUDE[asn1_dsa_internal_test]=.. ../include ../apps/include
DEPEND[asn1_dsa_internal_test]=../libcrypto.a libtestutil.a
SOURCE[keymgmt_internal_test]=keymgmt_internal_test.c
INCLUDE[keymgmt_internal_test]=.. ../include ../apps/include
DEPEND[keymgmt_internal_test]=../libcrypto.a libtestutil.a
SOURCE[ffc_internal_test]=ffc_internal_test.c
INCLUDE[ffc_internal_test]=.. ../include ../apps/include
DEPEND[ffc_internal_test]=../libcrypto.a libtestutil.a
IF[{- !$disabled{mdc2} -}]
PROGRAMS{noinst}=mdc2_internal_test
ENDIF
SOURCE[mdc2_internal_test]=mdc2_internal_test.c
INCLUDE[mdc2_internal_test]=.. ../include ../apps/include
DEPEND[mdc2_internal_test]=../libcrypto.a libtestutil.a
SOURCE[ssl_old_test]=ssl_old_test.c helpers/predefined_dhparams.c
INCLUDE[ssl_old_test]=.. ../include ../apps/include
DEPEND[ssl_old_test]=../libcrypto.a ../libssl.a libtestutil.a
PROGRAMS{noinst}=ext_internal_test
SOURCE[ext_internal_test]=ext_internal_test.c
INCLUDE[ext_internal_test]=.. ../include ../apps/include
DEPEND[ext_internal_test]=../libcrypto.a ../libssl.a libtestutil.a
PROGRAMS{noinst}=algorithmid_test
SOURCE[algorithmid_test]=algorithmid_test.c
INCLUDE[algorithmid_test]=../include ../apps/include
DEPEND[algorithmid_test]=../libcrypto.a libtestutil.a
ENDIF
PROGRAMS{noinst}=asn1_time_test
SOURCE[asn1_time_test]=asn1_time_test.c
INCLUDE[asn1_time_test]=../include ../apps/include
DEPEND[asn1_time_test]=../libcrypto libtestutil.a
# We disable this test completely in a shared build because it deliberately
# redefines some internal libssl symbols. This doesn't work in a non-shared
# build
IF[{- !$disabled{shared} -}]
PROGRAMS{noinst}=tls13secretstest
SOURCE[tls13secretstest]=tls13secretstest.c
DEFINE[tls13secretstest]=OPENSSL_NO_KTLS
SOURCE[tls13secretstest]= ../ssl/tls13_enc.c ../crypto/packet.c
INCLUDE[tls13secretstest]=.. ../include ../apps/include
DEPEND[tls13secretstest]=../libcrypto ../libssl libtestutil.a
ENDIF
SOURCE[sslbuffertest]=sslbuffertest.c helpers/ssltestlib.c
INCLUDE[sslbuffertest]=../include ../apps/include
DEPEND[sslbuffertest]=../libcrypto ../libssl libtestutil.a
SOURCE[sysdefaulttest]=sysdefaulttest.c
INCLUDE[sysdefaulttest]=../include ../apps/include
DEPEND[sysdefaulttest]=../libcrypto ../libssl libtestutil.a
SOURCE[errtest]=errtest.c
INCLUDE[errtest]=../include ../apps/include
DEPEND[errtest]=../libcrypto libtestutil.a
SOURCE[aesgcmtest]=aesgcmtest.c
INCLUDE[aesgcmtest]=../include ../apps/include ..
DEPEND[aesgcmtest]=../libcrypto libtestutil.a
PROGRAMS{noinst}=context_internal_test
SOURCE[context_internal_test]=context_internal_test.c
INCLUDE[context_internal_test]=.. ../include ../apps/include
DEPEND[context_internal_test]=../libcrypto.a libtestutil.a
PROGRAMS{noinst}=provider_internal_test
DEFINE[provider_internal_test]=PROVIDER_INIT_FUNCTION_NAME=p_test_init
SOURCE[provider_internal_test]=provider_internal_test.c p_test.c
INCLUDE[provider_internal_test]=../include ../apps/include ..
DEPEND[provider_internal_test]=../libcrypto.a libtestutil.a
PROGRAMS{noinst}=provider_test
DEFINE[provider_test]=PROVIDER_INIT_FUNCTION_NAME=p_test_init
SOURCE[provider_test]=provider_test.c p_test.c
INCLUDE[provider_test]=../include ../apps/include ..
DEPEND[provider_test]=../libcrypto.a libtestutil.a
IF[{- !$disabled{module} -}]
MODULES{noinst}=p_test
SOURCE[p_test]=p_test.c
INCLUDE[p_test]=../include ..
IF[{- defined $target{shared_defflag} -}]
SOURCE[p_test]=p_test.ld
GENERATE[p_test.ld]=../util/providers.num
ENDIF
MODULES{noinst}=p_minimal
SOURCE[p_minimal]=p_minimal.c
INCLUDE[p_minimal]=../include ..
IF[{- defined $target{shared_defflag} -}]
SOURCE[p_minimal]=p_minimal.ld
GENERATE[p_minimal.ld]=../util/providers.num
ENDIF
ENDIF
IF[{- $disabled{module} || !$target{dso_scheme} -}]
DEFINE[provider_test]=NO_PROVIDER_MODULE
DEFINE[prov_config_test]=NO_PROVIDER_MODULE
DEFINE[provider_internal_test]=NO_PROVIDER_MODULE
ENDIF
DEPEND[]=provider_internal_test.cnf
GENERATE[provider_internal_test.cnf]=provider_internal_test.cnf.in
PROGRAMS{noinst}=provider_fallback_test
SOURCE[provider_fallback_test]=provider_fallback_test.c
INCLUDE[provider_fallback_test]=../include ../apps/include
DEPEND[provider_fallback_test]=../libcrypto libtestutil.a
PROGRAMS{noinst}=provider_pkey_test
SOURCE[provider_pkey_test]=provider_pkey_test.c fake_rsaprov.c
INCLUDE[provider_pkey_test]=../include ../apps/include
DEPEND[provider_pkey_test]=../libcrypto libtestutil.a
PROGRAMS{noinst}=params_test
SOURCE[params_test]=params_test.c
INCLUDE[params_test]=.. ../include ../apps/include
DEPEND[params_test]=../libcrypto.a libtestutil.a
PROGRAMS{noinst}=hexstr_test
SOURCE[hexstr_test]=hexstr_test.c
INCLUDE[hexstr_test]=.. ../include ../apps/include
DEPEND[hexstr_test]=../libcrypto.a libtestutil.a
PROGRAMS{noinst}=trace_api_test
SOURCE[trace_api_test]=trace_api_test.c
INCLUDE[trace_api_test]=.. ../include ../apps/include
DEPEND[trace_api_test]=../libcrypto.a libtestutil.a
PROGRAMS{noinst}=endecode_test
SOURCE[endecode_test]=endecode_test.c helpers/predefined_dhparams.c
INCLUDE[endecode_test]=.. ../include ../apps/include
DEPEND[endecode_test]=../libcrypto.a libtestutil.a
IF[{- !$disabled{'deprecated-3.0'} -}]
PROGRAMS{noinst}=endecoder_legacy_test
SOURCE[endecoder_legacy_test]=endecoder_legacy_test.c
INCLUDE[endecoder_legacy_test]=.. ../include ../apps/include
DEPEND[endecoder_legacy_test]=../libcrypto.a libtestutil.a
ENDIF
PROGRAMS{noinst}=namemap_internal_test
SOURCE[namemap_internal_test]=namemap_internal_test.c
INCLUDE[namemap_internal_test]=.. ../include ../apps/include
DEPEND[namemap_internal_test]=../libcrypto.a libtestutil.a
PROGRAMS{noinst}=bio_prefix_text
SOURCE[bio_prefix_text]=bio_prefix_text.c
INCLUDE[bio_prefix_text]=.. ../include ../apps/include
DEPEND[bio_prefix_text]=../libcrypto libtestutil.a
IF[{- !$disabled{'deprecated-3.0'} -}]
PROGRAMS{noinst}=pem_read_depr_test
SOURCE[pem_read_depr_test]=pem_read_depr_test.c
INCLUDE[pem_read_depr_test]=../include ../apps/include
DEPEND[pem_read_depr_test]=../libcrypto libtestutil.a
ENDIF
ENDIF
SOURCE[ssl_ctx_test]=ssl_ctx_test.c
INCLUDE[ssl_ctx_test]=../include ../apps/include
DEPEND[ssl_ctx_test]=../libcrypto ../libssl libtestutil.a
+ SOURCE[bio_pw_callback_test]=bio_pw_callback_test.c
+ INCLUDE[bio_pw_callback_test]=../include ../apps/include
+ DEPEND[bio_pw_callback_test]=../libcrypto libtestutil.a
+
{-
use File::Spec::Functions;
use File::Basename;
use OpenSSL::Glob;
my @nogo_headers = ( "asn1_mac.h",
"opensslconf.h",
"__decc_include_prologue.h",
"__decc_include_epilogue.h" );
my @nogo_headers_re = ( qr/.*err\.h/ );
my @headerfiles = glob catfile($sourcedir,
updir(), "include", "openssl", "*.h");
foreach my $headerfile (@headerfiles) {
my $name = basename($headerfile, ".h");
next if $disabled{$name};
next if grep { $_ eq lc("$name.h") } @nogo_headers;
next if grep { lc("$name.h") =~ m/$_/i } @nogo_headers_re;
$OUT .= <<"_____";
PROGRAMS{noinst}=buildtest_c_$name
SOURCE[buildtest_c_$name]=buildtest_$name.c
GENERATE[buildtest_$name.c]=generate_buildtest.pl $name
INCLUDE[buildtest_c_$name]=../include
DEPEND[buildtest_c_$name]=../libssl ../libcrypto
_____
$OUT .= <<"_____" if $config{CXX} && !$disabled{"buildtest-c++"};
PROGRAMS{noinst}=buildtest_cc_$name
SOURCE[buildtest_cc_$name]=buildtest_$name.cc
GENERATE[buildtest_$name.cc]=generate_buildtest.pl $name
INCLUDE[buildtest_cc_$name]=../include
DEPEND[buildtest_cc_$name]=../libssl ../libcrypto
_____
}
-}
diff --git a/crypto/openssl/test/cmactest.c b/crypto/openssl/test/cmactest.c
index cb2b273b0f4f..72f7a0d9366b 100644
--- a/crypto/openssl/test/cmactest.c
+++ b/crypto/openssl/test/cmactest.c
@@ -1,216 +1,218 @@
/*
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* CMAC low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "internal/nelem.h"
#include <openssl/cmac.h>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include "testutil.h"
static const char xtskey[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
};
static struct test_st {
const char key[32];
int key_len;
const unsigned char data[64];
int data_len;
const char *mac;
} test[3] = {
{
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f
},
16,
"My test data",
12,
"29cec977c48f63c200bd5c4a6881b224"
},
{
{
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
},
32,
"My test data",
12,
"db6493aa04e4761f473b2b453c031c9a"
},
{
{
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
},
32,
"My test data again",
18,
"65c11c75ecf590badd0a5e56cbb8af60"
},
};
static char *pt(unsigned char *md, unsigned int len);
static int test_cmac_bad(void)
{
CMAC_CTX *ctx = NULL;
int ret = 0;
ctx = CMAC_CTX_new();
if (!TEST_ptr(ctx)
|| !TEST_false(CMAC_Init(ctx, NULL, 0, NULL, NULL))
|| !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len))
/* Should be able to pass cipher first, and then key */
|| !TEST_true(CMAC_Init(ctx, NULL, 0, EVP_aes_128_cbc(), NULL))
/* Must have a key */
|| !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len))
/* Now supply the key */
|| !TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len, NULL, NULL))
/* Update should now work */
|| !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
/* XTS is not a suitable cipher to use */
|| !TEST_false(CMAC_Init(ctx, xtskey, sizeof(xtskey), EVP_aes_128_xts(),
NULL))
|| !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len)))
goto err;
ret = 1;
err:
CMAC_CTX_free(ctx);
return ret;
}
static int test_cmac_run(void)
{
char *p;
CMAC_CTX *ctx = NULL;
unsigned char buf[AES_BLOCK_SIZE];
size_t len;
int ret = 0;
ctx = CMAC_CTX_new();
if (!TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len,
EVP_aes_128_cbc(), NULL))
|| !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
|| !TEST_true(CMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_str_eq(p, test[0].mac))
goto err;
if (!TEST_true(CMAC_Init(ctx, test[1].key, test[1].key_len,
EVP_aes_256_cbc(), NULL))
|| !TEST_true(CMAC_Update(ctx, test[1].data, test[1].data_len))
|| !TEST_true(CMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_str_eq(p, test[1].mac))
goto err;
if (!TEST_true(CMAC_Init(ctx, test[2].key, test[2].key_len, NULL, NULL))
|| !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
|| !TEST_true(CMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_str_eq(p, test[2].mac))
goto err;
/* Test reusing a key */
if (!TEST_true(CMAC_Init(ctx, NULL, 0, NULL, NULL))
|| !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
|| !TEST_true(CMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_str_eq(p, test[2].mac))
goto err;
/* Test setting the cipher and key separately */
if (!TEST_true(CMAC_Init(ctx, NULL, 0, EVP_aes_256_cbc(), NULL))
|| !TEST_true(CMAC_Init(ctx, test[2].key, test[2].key_len, NULL, NULL))
|| !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
|| !TEST_true(CMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_str_eq(p, test[2].mac))
goto err;
ret = 1;
err:
CMAC_CTX_free(ctx);
return ret;
}
static int test_cmac_copy(void)
{
char *p;
CMAC_CTX *ctx = NULL, *ctx2 = NULL;
unsigned char buf[AES_BLOCK_SIZE];
size_t len;
int ret = 0;
ctx = CMAC_CTX_new();
ctx2 = CMAC_CTX_new();
if (!TEST_ptr(ctx) || !TEST_ptr(ctx2))
goto err;
if (!TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len,
EVP_aes_128_cbc(), NULL))
|| !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
|| !TEST_true(CMAC_CTX_copy(ctx2, ctx))
|| !TEST_true(CMAC_Final(ctx2, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_str_eq(p, test[0].mac))
goto err;
ret = 1;
err:
CMAC_CTX_free(ctx2);
CMAC_CTX_free(ctx);
return ret;
}
+#define OSSL_HEX_CHARS_PER_BYTE 2
static char *pt(unsigned char *md, unsigned int len)
{
unsigned int i;
- static char buf[80];
+ static char buf[81];
- for (i = 0; i < len; i++)
- sprintf(&(buf[i * 2]), "%02x", md[i]);
+ for (i = 0; i < len && (i + 1) * OSSL_HEX_CHARS_PER_BYTE < sizeof(buf); i++)
+ BIO_snprintf(buf + i * OSSL_HEX_CHARS_PER_BYTE,
+ OSSL_HEX_CHARS_PER_BYTE + 1, "%02x", md[i]);
return buf;
}
int setup_tests(void)
{
ADD_TEST(test_cmac_bad);
ADD_TEST(test_cmac_run);
ADD_TEST(test_cmac_copy);
return 1;
}
diff --git a/crypto/openssl/test/conf_include_test.c b/crypto/openssl/test/conf_include_test.c
index 2481a2380b76..f6835d59e79e 100644
--- a/crypto/openssl/test/conf_include_test.c
+++ b/crypto/openssl/test/conf_include_test.c
@@ -1,238 +1,238 @@
/*
* Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/err.h>
#include "testutil.h"
#ifdef _WIN32
# include <direct.h>
# define DIRSEP "/\\"
# ifndef __BORLANDC__
# define chdir _chdir
# endif
# define DIRSEP_PRESERVE 0
#elif !defined(OPENSSL_NO_POSIX_IO)
# include <unistd.h>
# ifndef OPENSSL_SYS_VMS
# define DIRSEP "/"
# define DIRSEP_PRESERVE 0
# else
# define DIRSEP "/]:"
# define DIRSEP_PRESERVE 1
# endif
#else
/* the test does not work without chdir() */
# define chdir(x) (-1);
# define DIRSEP "/"
# define DIRSEP_PRESERVE 0
#endif
/* changes path to that of the filename */
static int change_path(const char *file)
{
char *s = OPENSSL_strdup(file);
char *p = s;
char *last = NULL;
int ret = 0;
if (s == NULL)
return -1;
while ((p = strpbrk(p, DIRSEP)) != NULL) {
last = p++;
}
if (last == NULL)
goto err;
last[DIRSEP_PRESERVE] = 0;
TEST_note("changing path to %s", s);
ret = chdir(s);
err:
OPENSSL_free(s);
return ret;
}
/*
* This test program checks the operation of the .include directive.
*/
static CONF *conf;
static BIO *in;
static int expect_failure = 0;
static int test_load_config(void)
{
long errline;
long val;
char *str;
long err;
if (!TEST_int_gt(NCONF_load_bio(conf, in, &errline), 0)
|| !TEST_int_eq(err = ERR_peek_error(), 0)) {
if (expect_failure)
return 1;
TEST_note("Failure loading the configuration at line %ld", errline);
return 0;
}
if (expect_failure) {
TEST_note("Failure expected but did not happen");
return 0;
}
if (!TEST_int_gt(CONF_modules_load(conf, NULL, 0), 0)) {
TEST_note("Failed in CONF_modules_load");
return 0;
}
/* verify whether CA_default/default_days is set */
val = 0;
if (!TEST_int_eq(NCONF_get_number(conf, "CA_default", "default_days", &val), 1)
|| !TEST_int_eq(val, 365)) {
TEST_note("default_days incorrect");
return 0;
}
/* verify whether req/default_bits is set */
val = 0;
if (!TEST_int_eq(NCONF_get_number(conf, "req", "default_bits", &val), 1)
|| !TEST_int_eq(val, 2048)) {
TEST_note("default_bits incorrect");
return 0;
}
/* verify whether countryName_default is set correctly */
str = NCONF_get_string(conf, "req_distinguished_name", "countryName_default");
if (!TEST_ptr(str) || !TEST_str_eq(str, "AU")) {
TEST_note("countryName_default incorrect");
return 0;
}
return 1;
}
static int test_check_null_numbers(void)
{
#if defined(_BSD_SOURCE) \
|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \
|| (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
long val = 0;
/* Verify that a NULL config with a present environment variable returns
* success and the value.
*/
if (!TEST_int_eq(setenv("FNORD", "123", 1), 0)
|| !TEST_true(NCONF_get_number(NULL, "missing", "FNORD", &val))
|| !TEST_long_eq(val, 123)) {
TEST_note("environment variable with NULL conf failed");
return 0;
}
/*
* Verify that a NULL config with a missing environment variable returns
* a failure code.
*/
if (!TEST_int_eq(unsetenv("FNORD"), 0)
|| !TEST_false(NCONF_get_number(NULL, "missing", "FNORD", &val))) {
TEST_note("missing environment variable with NULL conf failed");
return 0;
}
#endif
return 1;
}
static int test_check_overflow(void)
{
#if defined(_BSD_SOURCE) \
|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \
|| (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
long val = 0;
char max[(sizeof(long) * 8) / 3 + 3];
char *p;
- p = max + sprintf(max, "0%ld", LONG_MAX) - 1;
+ p = max + BIO_snprintf(max, sizeof(max), "0%ld", LONG_MAX) - 1;
setenv("FNORD", max, 1);
if (!TEST_true(NCONF_get_number(NULL, "missing", "FNORD", &val))
|| !TEST_long_eq(val, LONG_MAX))
return 0;
while (++*p > '9')
*p-- = '0';
setenv("FNORD", max, 1);
if (!TEST_false(NCONF_get_number(NULL, "missing", "FNORD", &val)))
return 0;
#endif
return 1;
}
typedef enum OPTION_choice {
OPT_ERR = -1,
OPT_EOF = 0,
OPT_FAIL,
OPT_TEST_ENUM
} OPTION_CHOICE;
const OPTIONS *test_get_options(void)
{
static const OPTIONS test_options[] = {
OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("conf_file\n"),
{ "f", OPT_FAIL, '-', "A failure is expected" },
{ NULL }
};
return test_options;
}
int setup_tests(void)
{
const char *conf_file;
OPTION_CHOICE o;
if (!TEST_ptr(conf = NCONF_new(NULL)))
return 0;
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_FAIL:
expect_failure = 1;
break;
case OPT_TEST_CASES:
break;
default:
return 0;
}
}
conf_file = test_get_argument(0);
if (!TEST_ptr(conf_file)
|| !TEST_ptr(in = BIO_new_file(conf_file, "r"))) {
TEST_note("Unable to open the file argument");
return 0;
}
/*
* For this test we need to chdir as we use relative
* path names in the config files.
*/
change_path(conf_file);
ADD_TEST(test_load_config);
ADD_TEST(test_check_null_numbers);
ADD_TEST(test_check_overflow);
return 1;
}
void cleanup_tests(void)
{
BIO_vfree(in);
NCONF_free(conf);
CONF_modules_unload(1);
}
diff --git a/crypto/openssl/test/drbgtest.c b/crypto/openssl/test/drbgtest.c
index b5122b60bdd4..afbc55112529 100644
--- a/crypto/openssl/test/drbgtest.c
+++ b/crypto/openssl/test/drbgtest.c
@@ -1,906 +1,906 @@
/*
* Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* We need to use some deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
#include <string.h>
#include "internal/nelem.h"
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include "../crypto/rand/rand_local.h"
#include "../include/crypto/rand.h"
#include "../include/crypto/evp.h"
#include "../providers/implementations/rands/drbg_local.h"
#include "../crypto/evp/evp_local.h"
#if defined(_WIN32)
# include <windows.h>
#endif
#if defined(__TANDEM)
# if defined(OPENSSL_TANDEM_FLOSS)
# include <floss.h(floss_fork)>
# endif
#endif
#if defined(OPENSSL_SYS_UNIX)
# include <sys/types.h>
# include <sys/wait.h>
# include <unistd.h>
#endif
#include "testutil.h"
/*
* DRBG generate wrappers
*/
static int gen_bytes(EVP_RAND_CTX *drbg, unsigned char *buf, int num)
{
#ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth != RAND_OpenSSL()) {
if (meth->bytes != NULL)
return meth->bytes(buf, num);
return -1;
}
#endif
if (drbg != NULL)
return EVP_RAND_generate(drbg, buf, num, 0, 0, NULL, 0);
return 0;
}
static int rand_bytes(unsigned char *buf, int num)
{
return gen_bytes(RAND_get0_public(NULL), buf, num);
}
static int rand_priv_bytes(unsigned char *buf, int num)
{
return gen_bytes(RAND_get0_private(NULL), buf, num);
}
/* size of random output generated in test_drbg_reseed() */
#define RANDOM_SIZE 16
/*
* DRBG query functions
*/
static int state(EVP_RAND_CTX *drbg)
{
return EVP_RAND_get_state(drbg);
}
static unsigned int query_rand_uint(EVP_RAND_CTX *drbg, const char *name)
{
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
unsigned int n;
*params = OSSL_PARAM_construct_uint(name, &n);
if (EVP_RAND_CTX_get_params(drbg, params))
return n;
return 0;
}
#define DRBG_UINT(name) \
static unsigned int name(EVP_RAND_CTX *drbg) \
{ \
return query_rand_uint(drbg, #name); \
}
DRBG_UINT(reseed_counter)
static PROV_DRBG *prov_rand(EVP_RAND_CTX *drbg)
{
return (PROV_DRBG *)drbg->algctx;
}
static void set_reseed_counter(EVP_RAND_CTX *drbg, unsigned int n)
{
PROV_DRBG *p = prov_rand(drbg);
p->reseed_counter = n;
}
static void inc_reseed_counter(EVP_RAND_CTX *drbg)
{
set_reseed_counter(drbg, reseed_counter(drbg) + 1);
}
static time_t reseed_time(EVP_RAND_CTX *drbg)
{
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
time_t t;
*params = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME, &t);
if (EVP_RAND_CTX_get_params(drbg, params))
return t;
return 0;
}
/*
* When building the FIPS module, it isn't possible to disable the continuous
* RNG tests. Tests that require this are skipped and this means a detection
* mechanism for the FIPS provider being in use.
*/
static int using_fips_rng(void)
{
EVP_RAND_CTX *primary = RAND_get0_primary(NULL);
const OSSL_PROVIDER *prov;
const char *name;
if (!TEST_ptr(primary))
return 0;
prov = EVP_RAND_get0_provider(EVP_RAND_CTX_get0_rand(primary));
if (!TEST_ptr(prov))
return 0;
name = OSSL_PROVIDER_get0_name(prov);
return strcmp(name, "OpenSSL FIPS Provider") == 0;
}
/*
* Disable CRNG testing if it is enabled.
* This stub remains to indicate the calling locations where it is necessary.
* Once the RNG infrastructure is able to disable these tests, it should be
* reconstituted.
*/
static int disable_crngt(EVP_RAND_CTX *drbg)
{
return 1;
}
/*
* Generates random output using rand_bytes() and rand_priv_bytes()
* and checks whether the three shared DRBGs were reseeded as
* expected.
*
* |expect_success|: expected outcome (as reported by RAND_status())
* |primary|, |public|, |private|: pointers to the three shared DRBGs
* |public_random|, |private_random|: generated random output
* |expect_xxx_reseed| =
* 1: it is expected that the specified DRBG is reseeded
* 0: it is expected that the specified DRBG is not reseeded
* -1: don't check whether the specified DRBG was reseeded or not
* |reseed_when|: if nonzero, used instead of time(NULL) to set the
* |before_reseed| time.
*/
static int test_drbg_reseed(int expect_success,
EVP_RAND_CTX *primary,
EVP_RAND_CTX *public,
EVP_RAND_CTX *private,
unsigned char *public_random,
unsigned char *private_random,
int expect_primary_reseed,
int expect_public_reseed,
int expect_private_reseed,
time_t reseed_when
)
{
time_t before_reseed, after_reseed;
int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR);
unsigned int primary_reseed, public_reseed, private_reseed;
unsigned char dummy[RANDOM_SIZE];
if (public_random == NULL)
public_random = dummy;
if (private_random == NULL)
private_random = dummy;
/*
* step 1: check preconditions
*/
/* Test whether seed propagation is enabled */
if (!TEST_int_ne(primary_reseed = reseed_counter(primary), 0)
|| !TEST_int_ne(public_reseed = reseed_counter(public), 0)
|| !TEST_int_ne(private_reseed = reseed_counter(private), 0))
return 0;
/*
* step 2: generate random output
*/
if (reseed_when == 0)
reseed_when = time(NULL);
/* Generate random output from the public and private DRBG */
before_reseed = expect_primary_reseed == 1 ? reseed_when : 0;
if (!TEST_int_eq(rand_bytes((unsigned char*)public_random,
RANDOM_SIZE), expect_success)
|| !TEST_int_eq(rand_priv_bytes((unsigned char*) private_random,
RANDOM_SIZE), expect_success))
return 0;
after_reseed = time(NULL);
/*
* step 3: check postconditions
*/
/* Test whether reseeding succeeded as expected */
if (!TEST_int_eq(state(primary), expected_state)
|| !TEST_int_eq(state(public), expected_state)
|| !TEST_int_eq(state(private), expected_state))
return 0;
if (expect_primary_reseed >= 0) {
/* Test whether primary DRBG was reseeded as expected */
if (!TEST_int_ge(reseed_counter(primary), primary_reseed))
return 0;
}
if (expect_public_reseed >= 0) {
/* Test whether public DRBG was reseeded as expected */
if (!TEST_int_ge(reseed_counter(public), public_reseed)
|| !TEST_uint_ge(reseed_counter(public),
reseed_counter(primary)))
return 0;
}
if (expect_private_reseed >= 0) {
/* Test whether public DRBG was reseeded as expected */
if (!TEST_int_ge(reseed_counter(private), private_reseed)
|| !TEST_uint_ge(reseed_counter(private),
reseed_counter(primary)))
return 0;
}
if (expect_success == 1) {
/* Test whether reseed time of primary DRBG is set correctly */
if (!TEST_time_t_le(before_reseed, reseed_time(primary))
|| !TEST_time_t_le(reseed_time(primary), after_reseed))
return 0;
/* Test whether reseed times of child DRBGs are synchronized with primary */
if (!TEST_time_t_ge(reseed_time(public), reseed_time(primary))
|| !TEST_time_t_ge(reseed_time(private), reseed_time(primary)))
return 0;
} else {
ERR_clear_error();
}
return 1;
}
#if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
/* number of children to fork */
#define DRBG_FORK_COUNT 9
/* two results per child, two for the parent */
#define DRBG_FORK_RESULT_COUNT (2 * (DRBG_FORK_COUNT + 1))
typedef struct drbg_fork_result_st {
unsigned char random[RANDOM_SIZE]; /* random output */
int pindex; /* process index (0: parent, 1,2,3...: children)*/
pid_t pid; /* process id */
int private; /* true if the private drbg was used */
char name[10]; /* 'parent' resp. 'child 1', 'child 2', ... */
} drbg_fork_result;
/*
* Sort the drbg_fork_result entries in lexicographical order
*
* This simplifies finding duplicate random output and makes
* the printout in case of an error more readable.
*/
static int compare_drbg_fork_result(const void * left, const void * right)
{
int result;
const drbg_fork_result *l = left;
const drbg_fork_result *r = right;
/* separate public and private results */
result = l->private - r->private;
if (result == 0)
result = memcmp(l->random, r->random, RANDOM_SIZE);
if (result == 0)
result = l->pindex - r->pindex;
return result;
}
/*
* Sort two-byte chunks of random data
*
* Used for finding collisions in two-byte chunks
*/
static int compare_rand_chunk(const void * left, const void * right)
{
return memcmp(left, right, 2);
}
/*
* Test whether primary, public and private DRBG are reseeded
* in the child after forking the process. Collect the random
* output of the public and private DRBG and send it back to
* the parent process.
*/
static int test_drbg_reseed_in_child(EVP_RAND_CTX *primary,
EVP_RAND_CTX *public,
EVP_RAND_CTX *private,
drbg_fork_result result[2])
{
int rv = 0, status;
int fd[2];
pid_t pid;
unsigned char random[2 * RANDOM_SIZE];
if (!TEST_int_ge(pipe(fd), 0))
return 0;
if (!TEST_int_ge(pid = fork(), 0)) {
close(fd[0]);
close(fd[1]);
return 0;
} else if (pid > 0) {
/* I'm the parent; close the write end */
close(fd[1]);
/* wait for children to terminate and collect their random output */
if (TEST_int_eq(waitpid(pid, &status, 0), pid)
&& TEST_int_eq(status, 0)
&& TEST_true(read(fd[0], &random[0], sizeof(random))
== sizeof(random))) {
/* random output of public drbg */
result[0].pid = pid;
result[0].private = 0;
memcpy(result[0].random, &random[0], RANDOM_SIZE);
/* random output of private drbg */
result[1].pid = pid;
result[1].private = 1;
memcpy(result[1].random, &random[RANDOM_SIZE], RANDOM_SIZE);
rv = 1;
}
/* close the read end */
close(fd[0]);
return rv;
} else {
/* I'm the child; close the read end */
close(fd[0]);
/* check whether all three DRBGs reseed and send output to parent */
if (TEST_true(test_drbg_reseed(1, primary, public, private,
&random[0], &random[RANDOM_SIZE],
1, 1, 1, 0))
&& TEST_true(write(fd[1], random, sizeof(random))
== sizeof(random))) {
rv = 1;
}
/* close the write end */
close(fd[1]);
/* convert boolean to exit code */
exit(rv == 0);
}
}
static int test_rand_reseed_on_fork(EVP_RAND_CTX *primary,
EVP_RAND_CTX *public,
EVP_RAND_CTX *private)
{
unsigned int i;
pid_t pid = getpid();
int verbose = (getenv("V") != NULL);
int success = 1;
int duplicate[2] = {0, 0};
unsigned char random[2 * RANDOM_SIZE];
unsigned char sample[DRBG_FORK_RESULT_COUNT * RANDOM_SIZE];
unsigned char *psample = &sample[0];
drbg_fork_result result[DRBG_FORK_RESULT_COUNT];
drbg_fork_result *presult = &result[2];
memset(&result, 0, sizeof(result));
for (i = 1 ; i <= DRBG_FORK_COUNT ; ++i) {
presult[0].pindex = presult[1].pindex = i;
- sprintf(presult[0].name, "child %d", i);
+ BIO_snprintf(presult[0].name, sizeof(presult[0].name), "child %d", i);
strcpy(presult[1].name, presult[0].name);
/* collect the random output of the children */
if (!TEST_true(test_drbg_reseed_in_child(primary,
public,
private,
presult)))
return 0;
presult += 2;
}
/* collect the random output of the parent */
if (!TEST_true(test_drbg_reseed(1,
primary, public, private,
&random[0], &random[RANDOM_SIZE],
0, 0, 0, 0)))
return 0;
strcpy(result[0].name, "parent");
strcpy(result[1].name, "parent");
/* output of public drbg */
result[0].pid = pid;
result[0].private = 0;
memcpy(result[0].random, &random[0], RANDOM_SIZE);
/* output of private drbg */
result[1].pid = pid;
result[1].private = 1;
memcpy(result[1].random, &random[RANDOM_SIZE], RANDOM_SIZE);
/* collect all sampled random data in a single buffer */
for (i = 0 ; i < DRBG_FORK_RESULT_COUNT ; ++i) {
memcpy(psample, &result[i].random[0], RANDOM_SIZE);
psample += RANDOM_SIZE;
}
/* sort the results... */
qsort(result, DRBG_FORK_RESULT_COUNT, sizeof(drbg_fork_result),
compare_drbg_fork_result);
/* ...and count duplicate prefixes by looking at the first byte only */
for (i = 1 ; i < DRBG_FORK_RESULT_COUNT ; ++i) {
if (result[i].random[0] == result[i-1].random[0]) {
/* count public and private duplicates separately */
++duplicate[result[i].private];
}
}
if (duplicate[0] >= DRBG_FORK_COUNT - 1) {
/* just too many duplicates to be a coincidence */
TEST_note("ERROR: %d duplicate prefixes in public random output", duplicate[0]);
success = 0;
}
if (duplicate[1] >= DRBG_FORK_COUNT - 1) {
/* just too many duplicates to be a coincidence */
TEST_note("ERROR: %d duplicate prefixes in private random output", duplicate[1]);
success = 0;
}
duplicate[0] = 0;
/* sort the two-byte chunks... */
qsort(sample, sizeof(sample)/2, 2, compare_rand_chunk);
/* ...and count duplicate chunks */
for (i = 2, psample = sample + 2 ; i < sizeof(sample) ; i += 2, psample += 2) {
if (compare_rand_chunk(psample - 2, psample) == 0)
++duplicate[0];
}
if (duplicate[0] >= DRBG_FORK_COUNT - 1) {
/* just too many duplicates to be a coincidence */
TEST_note("ERROR: %d duplicate chunks in random output", duplicate[0]);
success = 0;
}
if (verbose || !success) {
for (i = 0 ; i < DRBG_FORK_RESULT_COUNT ; ++i) {
char *rand_hex = OPENSSL_buf2hexstr(result[i].random, RANDOM_SIZE);
TEST_note(" random: %s, pid: %d (%s, %s)",
rand_hex,
result[i].pid,
result[i].name,
result[i].private ? "private" : "public"
);
OPENSSL_free(rand_hex);
}
}
return success;
}
static int test_rand_fork_safety(int i)
{
int success = 1;
unsigned char random[1];
EVP_RAND_CTX *primary, *public, *private;
/* All three DRBGs should be non-null */
if (!TEST_ptr(primary = RAND_get0_primary(NULL))
|| !TEST_ptr(public = RAND_get0_public(NULL))
|| !TEST_ptr(private = RAND_get0_private(NULL)))
return 0;
/* run the actual test */
if (!TEST_true(test_rand_reseed_on_fork(primary, public, private)))
success = 0;
/* request a single byte from each of the DRBGs before the next run */
if (!TEST_int_gt(RAND_bytes(random, 1), 0) || !TEST_int_gt(RAND_priv_bytes(random, 1), 0))
success = 0;
return success;
}
#endif
/*
* Test whether the default rand_method (RAND_OpenSSL()) is
* setup correctly, in particular whether reseeding works
* as designed.
*/
static int test_rand_reseed(void)
{
EVP_RAND_CTX *primary, *public, *private;
unsigned char rand_add_buf[256];
int rv = 0;
time_t before_reseed;
if (using_fips_rng())
return TEST_skip("CRNGT cannot be disabled");
#ifndef OPENSSL_NO_DEPRECATED_3_0
/* Check whether RAND_OpenSSL() is the default method */
if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
return 0;
#endif
/* All three DRBGs should be non-null */
if (!TEST_ptr(primary = RAND_get0_primary(NULL))
|| !TEST_ptr(public = RAND_get0_public(NULL))
|| !TEST_ptr(private = RAND_get0_private(NULL)))
return 0;
/* There should be three distinct DRBGs, two of them chained to primary */
if (!TEST_ptr_ne(public, private)
|| !TEST_ptr_ne(public, primary)
|| !TEST_ptr_ne(private, primary)
|| !TEST_ptr_eq(prov_rand(public)->parent, prov_rand(primary))
|| !TEST_ptr_eq(prov_rand(private)->parent, prov_rand(primary)))
return 0;
/* Disable CRNG testing for the primary DRBG */
if (!TEST_true(disable_crngt(primary)))
return 0;
/* uninstantiate the three global DRBGs */
EVP_RAND_uninstantiate(primary);
EVP_RAND_uninstantiate(private);
EVP_RAND_uninstantiate(public);
/*
* Test initial seeding of shared DRBGs
*/
if (!TEST_true(test_drbg_reseed(1,
primary, public, private,
NULL, NULL,
1, 1, 1, 0)))
goto error;
/*
* Test initial state of shared DRBGs
*/
if (!TEST_true(test_drbg_reseed(1,
primary, public, private,
NULL, NULL,
0, 0, 0, 0)))
goto error;
/*
* Test whether the public and private DRBG are both reseeded when their
* reseed counters differ from the primary's reseed counter.
*/
inc_reseed_counter(primary);
if (!TEST_true(test_drbg_reseed(1,
primary, public, private,
NULL, NULL,
0, 1, 1, 0)))
goto error;
/*
* Test whether the public DRBG is reseeded when its reseed counter differs
* from the primary's reseed counter.
*/
inc_reseed_counter(primary);
inc_reseed_counter(private);
if (!TEST_true(test_drbg_reseed(1,
primary, public, private,
NULL, NULL,
0, 1, 0, 0)))
goto error;
/*
* Test whether the private DRBG is reseeded when its reseed counter differs
* from the primary's reseed counter.
*/
inc_reseed_counter(primary);
inc_reseed_counter(public);
if (!TEST_true(test_drbg_reseed(1,
primary, public, private,
NULL, NULL,
0, 0, 1, 0)))
goto error;
/* fill 'randomness' buffer with some arbitrary data */
memset(rand_add_buf, 'r', sizeof(rand_add_buf));
/*
* Test whether all three DRBGs are reseeded by RAND_add().
* The before_reseed time has to be measured here and passed into the
* test_drbg_reseed() test, because the primary DRBG gets already reseeded
* in RAND_add(), whence the check for the condition
* before_reseed <= reseed_time(primary) will fail if the time value happens
* to increase between the RAND_add() and the test_drbg_reseed() call.
*/
before_reseed = time(NULL);
RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
if (!TEST_true(test_drbg_reseed(1,
primary, public, private,
NULL, NULL,
1, 1, 1,
before_reseed)))
goto error;
rv = 1;
error:
return rv;
}
#if defined(OPENSSL_THREADS)
static int multi_thread_rand_bytes_succeeded = 1;
static int multi_thread_rand_priv_bytes_succeeded = 1;
static int set_reseed_time_interval(EVP_RAND_CTX *drbg, int t)
{
OSSL_PARAM params[2];
params[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
&t);
params[1] = OSSL_PARAM_construct_end();
return EVP_RAND_CTX_set_params(drbg, params);
}
static void run_multi_thread_test(void)
{
unsigned char buf[256];
time_t start = time(NULL);
EVP_RAND_CTX *public = NULL, *private = NULL;
if (!TEST_ptr(public = RAND_get0_public(NULL))
|| !TEST_ptr(private = RAND_get0_private(NULL))
|| !TEST_true(set_reseed_time_interval(private, 1))
|| !TEST_true(set_reseed_time_interval(public, 1))) {
multi_thread_rand_bytes_succeeded = 0;
return;
}
do {
if (rand_bytes(buf, sizeof(buf)) <= 0)
multi_thread_rand_bytes_succeeded = 0;
if (rand_priv_bytes(buf, sizeof(buf)) <= 0)
multi_thread_rand_priv_bytes_succeeded = 0;
}
while (time(NULL) - start < 5);
}
# if defined(OPENSSL_SYS_WINDOWS)
typedef HANDLE thread_t;
static DWORD WINAPI thread_run(LPVOID arg)
{
run_multi_thread_test();
/*
* Because we're linking with a static library, we must stop each
* thread explicitly, or so says OPENSSL_thread_stop(3)
*/
OPENSSL_thread_stop();
return 0;
}
static int run_thread(thread_t *t)
{
*t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL);
return *t != NULL;
}
static int wait_for_thread(thread_t thread)
{
return WaitForSingleObject(thread, INFINITE) == 0;
}
# else
typedef pthread_t thread_t;
static void *thread_run(void *arg)
{
run_multi_thread_test();
/*
* Because we're linking with a static library, we must stop each
* thread explicitly, or so says OPENSSL_thread_stop(3)
*/
OPENSSL_thread_stop();
return NULL;
}
static int run_thread(thread_t *t)
{
return pthread_create(t, NULL, thread_run, NULL) == 0;
}
static int wait_for_thread(thread_t thread)
{
return pthread_join(thread, NULL) == 0;
}
# endif
/*
* The main thread will also run the test, so we'll have THREADS+1 parallel
* tests running
*/
# define THREADS 3
static int test_multi_thread(void)
{
thread_t t[THREADS];
int i;
for (i = 0; i < THREADS; i++)
run_thread(&t[i]);
run_multi_thread_test();
for (i = 0; i < THREADS; i++)
wait_for_thread(t[i]);
if (!TEST_true(multi_thread_rand_bytes_succeeded))
return 0;
if (!TEST_true(multi_thread_rand_priv_bytes_succeeded))
return 0;
return 1;
}
#endif
static EVP_RAND_CTX *new_drbg(EVP_RAND_CTX *parent)
{
OSSL_PARAM params[2];
EVP_RAND *rand = NULL;
EVP_RAND_CTX *drbg = NULL;
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
"AES-256-CTR", 0);
params[1] = OSSL_PARAM_construct_end();
if (!TEST_ptr(rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL))
|| !TEST_ptr(drbg = EVP_RAND_CTX_new(rand, parent))
|| !TEST_true(EVP_RAND_CTX_set_params(drbg, params))) {
EVP_RAND_CTX_free(drbg);
drbg = NULL;
}
EVP_RAND_free(rand);
return drbg;
}
static int test_rand_prediction_resistance(void)
{
EVP_RAND_CTX *x = NULL, *y = NULL, *z = NULL;
unsigned char buf1[51], buf2[sizeof(buf1)];
int ret = 0, xreseed, yreseed, zreseed;
if (using_fips_rng())
return TEST_skip("CRNGT cannot be disabled");
/* Initialise a three long DRBG chain */
if (!TEST_ptr(x = new_drbg(NULL))
|| !TEST_true(disable_crngt(x))
|| !TEST_true(EVP_RAND_instantiate(x, 0, 0, NULL, 0, NULL))
|| !TEST_ptr(y = new_drbg(x))
|| !TEST_true(EVP_RAND_instantiate(y, 0, 0, NULL, 0, NULL))
|| !TEST_ptr(z = new_drbg(y))
|| !TEST_true(EVP_RAND_instantiate(z, 0, 0, NULL, 0, NULL)))
goto err;
/*
* During a normal reseed, only the last DRBG in the chain should
* be reseeded.
*/
inc_reseed_counter(y);
xreseed = reseed_counter(x);
yreseed = reseed_counter(y);
zreseed = reseed_counter(z);
if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0))
|| !TEST_int_eq(reseed_counter(x), xreseed)
|| !TEST_int_eq(reseed_counter(y), yreseed)
|| !TEST_int_gt(reseed_counter(z), zreseed))
goto err;
/*
* When prediction resistance is requested, the request should be
* propagated to the primary, so that the entire DRBG chain reseeds.
*/
zreseed = reseed_counter(z);
if (!TEST_true(EVP_RAND_reseed(z, 1, NULL, 0, NULL, 0))
|| !TEST_int_gt(reseed_counter(x), xreseed)
|| !TEST_int_gt(reseed_counter(y), yreseed)
|| !TEST_int_gt(reseed_counter(z), zreseed))
goto err;
/*
* During a normal generate, only the last DRBG should be reseed */
inc_reseed_counter(y);
xreseed = reseed_counter(x);
yreseed = reseed_counter(y);
zreseed = reseed_counter(z);
if (!TEST_true(EVP_RAND_generate(z, buf1, sizeof(buf1), 0, 0, NULL, 0))
|| !TEST_int_eq(reseed_counter(x), xreseed)
|| !TEST_int_eq(reseed_counter(y), yreseed)
|| !TEST_int_gt(reseed_counter(z), zreseed))
goto err;
/*
* When a prediction resistant generate is requested, the request
* should be propagated to the primary, reseeding the entire DRBG chain.
*/
zreseed = reseed_counter(z);
if (!TEST_true(EVP_RAND_generate(z, buf2, sizeof(buf2), 0, 1, NULL, 0))
|| !TEST_int_gt(reseed_counter(x), xreseed)
|| !TEST_int_gt(reseed_counter(y), yreseed)
|| !TEST_int_gt(reseed_counter(z), zreseed)
|| !TEST_mem_ne(buf1, sizeof(buf1), buf2, sizeof(buf2)))
goto err;
/* Verify that a normal reseed still only reseeds the last DRBG */
inc_reseed_counter(y);
xreseed = reseed_counter(x);
yreseed = reseed_counter(y);
zreseed = reseed_counter(z);
if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0))
|| !TEST_int_eq(reseed_counter(x), xreseed)
|| !TEST_int_eq(reseed_counter(y), yreseed)
|| !TEST_int_gt(reseed_counter(z), zreseed))
goto err;
ret = 1;
err:
EVP_RAND_CTX_free(z);
EVP_RAND_CTX_free(y);
EVP_RAND_CTX_free(x);
return ret;
}
int setup_tests(void)
{
ADD_TEST(test_rand_reseed);
#if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
ADD_ALL_TESTS(test_rand_fork_safety, RANDOM_SIZE);
#endif
ADD_TEST(test_rand_prediction_resistance);
#if defined(OPENSSL_THREADS)
ADD_TEST(test_multi_thread);
#endif
return 1;
}
diff --git a/crypto/openssl/test/ec_internal_test.c b/crypto/openssl/test/ec_internal_test.c
index 8c2cd0563169..02cfd4e9d885 100644
--- a/crypto/openssl/test/ec_internal_test.c
+++ b/crypto/openssl/test/ec_internal_test.c
@@ -1,462 +1,513 @@
/*
* Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* Low level APIs are deprecated for public use, but still ok for internal use.
*/
#include "internal/deprecated.h"
#include "internal/nelem.h"
#include "testutil.h"
#include <openssl/ec.h>
#include "ec_local.h"
#include <openssl/objects.h>
static size_t crv_len = 0;
static EC_builtin_curve *curves = NULL;
/* sanity checks field_inv function pointer in EC_METHOD */
static int group_field_tests(const EC_GROUP *group, BN_CTX *ctx)
{
BIGNUM *a = NULL, *b = NULL, *c = NULL;
int ret = 0;
if (group->meth->field_inv == NULL || group->meth->field_mul == NULL)
return 1;
BN_CTX_start(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
if (!TEST_ptr(c = BN_CTX_get(ctx))
/* 1/1 = 1 */
|| !TEST_true(group->meth->field_inv(group, b, BN_value_one(), ctx))
|| !TEST_true(BN_is_one(b))
/* (1/a)*a = 1 */
|| !TEST_true(BN_rand(a, BN_num_bits(group->field) - 1,
BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
|| !TEST_true(group->meth->field_inv(group, b, a, ctx))
|| (group->meth->field_encode &&
!TEST_true(group->meth->field_encode(group, a, a, ctx)))
|| (group->meth->field_encode &&
!TEST_true(group->meth->field_encode(group, b, b, ctx)))
|| !TEST_true(group->meth->field_mul(group, c, a, b, ctx))
|| (group->meth->field_decode &&
!TEST_true(group->meth->field_decode(group, c, c, ctx)))
|| !TEST_true(BN_is_one(c)))
goto err;
/* 1/0 = error */
BN_zero(a);
if (!TEST_false(group->meth->field_inv(group, b, a, ctx))
|| !TEST_true(ERR_GET_LIB(ERR_peek_last_error()) == ERR_LIB_EC)
|| !TEST_true(ERR_GET_REASON(ERR_peek_last_error()) ==
EC_R_CANNOT_INVERT)
/* 1/p = error */
|| !TEST_false(group->meth->field_inv(group, b, group->field, ctx))
|| !TEST_true(ERR_GET_LIB(ERR_peek_last_error()) == ERR_LIB_EC)
|| !TEST_true(ERR_GET_REASON(ERR_peek_last_error()) ==
EC_R_CANNOT_INVERT))
goto err;
ERR_clear_error();
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/* wrapper for group_field_tests for explicit curve params and EC_METHOD */
static int field_tests(const EC_METHOD *meth, const unsigned char *params,
int len)
{
BN_CTX *ctx = NULL;
BIGNUM *p = NULL, *a = NULL, *b = NULL;
EC_GROUP *group = NULL;
int ret = 0;
if (!TEST_ptr(ctx = BN_CTX_new()))
return 0;
BN_CTX_start(ctx);
p = BN_CTX_get(ctx);
a = BN_CTX_get(ctx);
if (!TEST_ptr(b = BN_CTX_get(ctx))
|| !TEST_ptr(group = EC_GROUP_new(meth))
|| !TEST_true(BN_bin2bn(params, len, p))
|| !TEST_true(BN_bin2bn(params + len, len, a))
|| !TEST_true(BN_bin2bn(params + 2 * len, len, b))
|| !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
|| !group_field_tests(group, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
if (group != NULL)
EC_GROUP_free(group);
return ret;
}
/* NIST prime curve P-256 */
static const unsigned char params_p256[] = {
/* p */
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* a */
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
/* b */
0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B
};
#ifndef OPENSSL_NO_EC2M
/* NIST binary curve B-283 */
static const unsigned char params_b283[] = {
/* p */
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1,
/* a */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
/* b */
0x02, 0x7B, 0x68, 0x0A, 0xC8, 0xB8, 0x59, 0x6D, 0xA5, 0xA4, 0xAF, 0x8A,
0x19, 0xA0, 0x30, 0x3F, 0xCA, 0x97, 0xFD, 0x76, 0x45, 0x30, 0x9F, 0xA2,
0xA5, 0x81, 0x48, 0x5A, 0xF6, 0x26, 0x3E, 0x31, 0x3B, 0x79, 0xA2, 0xF5
};
#endif
/* test EC_GFp_simple_method directly */
static int field_tests_ecp_simple(void)
{
TEST_info("Testing EC_GFp_simple_method()\n");
return field_tests(EC_GFp_simple_method(), params_p256,
sizeof(params_p256) / 3);
}
/* test EC_GFp_mont_method directly */
static int field_tests_ecp_mont(void)
{
TEST_info("Testing EC_GFp_mont_method()\n");
return field_tests(EC_GFp_mont_method(), params_p256,
sizeof(params_p256) / 3);
}
#ifndef OPENSSL_NO_EC2M
+/* Test that decoding of invalid GF2m field parameters fails. */
+static int ec2m_field_sanity(void)
+{
+ int ret = 0;
+ BN_CTX *ctx = BN_CTX_new();
+ BIGNUM *p, *a, *b;
+ EC_GROUP *group1 = NULL, *group2 = NULL, *group3 = NULL;
+
+ TEST_info("Testing GF2m hardening\n");
+
+ BN_CTX_start(ctx);
+ p = BN_CTX_get(ctx);
+ a = BN_CTX_get(ctx);
+ if (!TEST_ptr(b = BN_CTX_get(ctx))
+ || !TEST_true(BN_one(a))
+ || !TEST_true(BN_one(b)))
+ goto out;
+
+ /* Even pentanomial value should be rejected */
+ if (!TEST_true(BN_set_word(p, 0xf2)))
+ goto out;
+ if (!TEST_ptr_null(group1 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
+ TEST_error("Zero constant term accepted in GF2m polynomial");
+
+ /* Odd hexanomial should also be rejected */
+ if (!TEST_true(BN_set_word(p, 0xf3)))
+ goto out;
+ if (!TEST_ptr_null(group2 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
+ TEST_error("Hexanomial accepted as GF2m polynomial");
+
+ /* Excessive polynomial degree should also be rejected */
+ if (!TEST_true(BN_set_word(p, 0x71))
+ || !TEST_true(BN_set_bit(p, OPENSSL_ECC_MAX_FIELD_BITS + 1)))
+ goto out;
+ if (!TEST_ptr_null(group3 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
+ TEST_error("GF2m polynomial degree > %d accepted",
+ OPENSSL_ECC_MAX_FIELD_BITS);
+
+ ret = group1 == NULL && group2 == NULL && group3 == NULL;
+
+ out:
+ EC_GROUP_free(group1);
+ EC_GROUP_free(group2);
+ EC_GROUP_free(group3);
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+
+ return ret;
+}
+
/* test EC_GF2m_simple_method directly */
static int field_tests_ec2_simple(void)
{
TEST_info("Testing EC_GF2m_simple_method()\n");
return field_tests(EC_GF2m_simple_method(), params_b283,
sizeof(params_b283) / 3);
}
#endif
/* test default method for a named curve */
static int field_tests_default(int n)
{
BN_CTX *ctx = NULL;
EC_GROUP *group = NULL;
int nid = curves[n].nid;
int ret = 0;
TEST_info("Testing curve %s\n", OBJ_nid2sn(nid));
if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
|| !TEST_ptr(ctx = BN_CTX_new())
|| !group_field_tests(group, ctx))
goto err;
ret = 1;
err:
if (group != NULL)
EC_GROUP_free(group);
if (ctx != NULL)
BN_CTX_free(ctx);
return ret;
}
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
/*
* Tests a point known to cause an incorrect underflow in an old version of
* ecp_nist521.c
*/
static int underflow_test(void)
{
BN_CTX *ctx = NULL;
EC_GROUP *grp = NULL;
EC_POINT *P = NULL, *Q = NULL, *R = NULL;
BIGNUM *x1 = NULL, *y1 = NULL, *z1 = NULL, *x2 = NULL, *y2 = NULL;
BIGNUM *k = NULL;
int testresult = 0;
const char *x1str =
"1534f0077fffffe87e9adcfe000000000000000000003e05a21d2400002e031b1f4"
"b80000c6fafa4f3c1288798d624a247b5e2ffffffffffffffefe099241900004";
const char *p521m1 =
"1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe";
ctx = BN_CTX_new();
if (!TEST_ptr(ctx))
return 0;
BN_CTX_start(ctx);
x1 = BN_CTX_get(ctx);
y1 = BN_CTX_get(ctx);
z1 = BN_CTX_get(ctx);
x2 = BN_CTX_get(ctx);
y2 = BN_CTX_get(ctx);
k = BN_CTX_get(ctx);
if (!TEST_ptr(k))
goto err;
grp = EC_GROUP_new_by_curve_name(NID_secp521r1);
P = EC_POINT_new(grp);
Q = EC_POINT_new(grp);
R = EC_POINT_new(grp);
if (!TEST_ptr(grp) || !TEST_ptr(P) || !TEST_ptr(Q) || !TEST_ptr(R))
goto err;
if (!TEST_int_gt(BN_hex2bn(&x1, x1str), 0)
|| !TEST_int_gt(BN_hex2bn(&y1, p521m1), 0)
|| !TEST_int_gt(BN_hex2bn(&z1, p521m1), 0)
|| !TEST_int_gt(BN_hex2bn(&k, "02"), 0)
|| !TEST_true(ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(grp, P, x1,
y1, z1, ctx))
|| !TEST_true(EC_POINT_mul(grp, Q, NULL, P, k, ctx))
|| !TEST_true(EC_POINT_get_affine_coordinates(grp, Q, x1, y1, ctx))
|| !TEST_true(EC_POINT_dbl(grp, R, P, ctx))
|| !TEST_true(EC_POINT_get_affine_coordinates(grp, R, x2, y2, ctx)))
goto err;
if (!TEST_int_eq(BN_cmp(x1, x2), 0)
|| !TEST_int_eq(BN_cmp(y1, y2), 0))
goto err;
testresult = 1;
err:
BN_CTX_end(ctx);
EC_POINT_free(P);
EC_POINT_free(Q);
EC_POINT_free(R);
EC_GROUP_free(grp);
BN_CTX_free(ctx);
return testresult;
}
#endif
/*
* Tests behavior of the EC_KEY_set_private_key
*/
static int set_private_key(void)
{
EC_KEY *key = NULL, *aux_key = NULL;
int testresult = 0;
key = EC_KEY_new_by_curve_name(NID_secp224r1);
aux_key = EC_KEY_new_by_curve_name(NID_secp224r1);
if (!TEST_ptr(key)
|| !TEST_ptr(aux_key)
|| !TEST_int_eq(EC_KEY_generate_key(key), 1)
|| !TEST_int_eq(EC_KEY_generate_key(aux_key), 1))
goto err;
/* Test setting a valid private key */
if (!TEST_int_eq(EC_KEY_set_private_key(key, aux_key->priv_key), 1))
goto err;
/* Test compliance with legacy behavior for NULL private keys */
if (!TEST_int_eq(EC_KEY_set_private_key(key, NULL), 0)
|| !TEST_ptr_null(key->priv_key))
goto err;
testresult = 1;
err:
EC_KEY_free(key);
EC_KEY_free(aux_key);
return testresult;
}
/*
* Tests behavior of the decoded_from_explicit_params flag and API
*/
static int decoded_flag_test(void)
{
EC_GROUP *grp;
EC_GROUP *grp_copy = NULL;
ECPARAMETERS *ecparams = NULL;
ECPKPARAMETERS *ecpkparams = NULL;
EC_KEY *key = NULL;
unsigned char *encodedparams = NULL;
const unsigned char *encp;
int encodedlen;
int testresult = 0;
/* Test EC_GROUP_new not setting the flag */
grp = EC_GROUP_new(EC_GFp_simple_method());
if (!TEST_ptr(grp)
|| !TEST_int_eq(grp->decoded_from_explicit_params, 0))
goto err;
EC_GROUP_free(grp);
/* Test EC_GROUP_new_by_curve_name not setting the flag */
grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
if (!TEST_ptr(grp)
|| !TEST_int_eq(grp->decoded_from_explicit_params, 0))
goto err;
/* Test EC_GROUP_new_from_ecparameters not setting the flag */
if (!TEST_ptr(ecparams = EC_GROUP_get_ecparameters(grp, NULL))
|| !TEST_ptr(grp_copy = EC_GROUP_new_from_ecparameters(ecparams))
|| !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
goto err;
EC_GROUP_free(grp_copy);
grp_copy = NULL;
ECPARAMETERS_free(ecparams);
ecparams = NULL;
/* Test EC_GROUP_new_from_ecpkparameters not setting the flag */
if (!TEST_int_eq(EC_GROUP_get_asn1_flag(grp), OPENSSL_EC_NAMED_CURVE)
|| !TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
|| !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
|| !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)
|| !TEST_ptr(key = EC_KEY_new())
/* Test EC_KEY_decoded_from_explicit_params on key without a group */
|| !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), -1)
|| !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
/* Test EC_KEY_decoded_from_explicit_params negative case */
|| !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 0))
goto err;
EC_GROUP_free(grp_copy);
grp_copy = NULL;
ECPKPARAMETERS_free(ecpkparams);
ecpkparams = NULL;
/* Test d2i_ECPKParameters with named params not setting the flag */
if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
|| !TEST_ptr(encp = encodedparams)
|| !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
|| !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
goto err;
EC_GROUP_free(grp_copy);
grp_copy = NULL;
OPENSSL_free(encodedparams);
encodedparams = NULL;
/* Asn1 flag stays set to explicit with EC_GROUP_new_from_ecpkparameters */
EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_EXPLICIT_CURVE);
if (!TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
|| !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
|| !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
|| !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
goto err;
EC_GROUP_free(grp_copy);
grp_copy = NULL;
/* Test d2i_ECPKParameters with explicit params setting the flag */
if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
|| !TEST_ptr(encp = encodedparams)
|| !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
|| !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
|| !TEST_int_eq(grp_copy->decoded_from_explicit_params, 1)
|| !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
/* Test EC_KEY_decoded_from_explicit_params positive case */
|| !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 1))
goto err;
testresult = 1;
err:
EC_KEY_free(key);
EC_GROUP_free(grp);
EC_GROUP_free(grp_copy);
ECPARAMETERS_free(ecparams);
ECPKPARAMETERS_free(ecpkparams);
OPENSSL_free(encodedparams);
return testresult;
}
static
int ecpkparams_i2d2i_test(int n)
{
EC_GROUP *g1 = NULL, *g2 = NULL;
FILE *fp = NULL;
int nid = curves[n].nid;
int testresult = 0;
/* create group */
if (!TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid)))
goto end;
/* encode params to file */
if (!TEST_ptr(fp = fopen("params.der", "wb"))
|| !TEST_true(i2d_ECPKParameters_fp(fp, g1)))
goto end;
/* flush and close file */
if (!TEST_int_eq(fclose(fp), 0)) {
fp = NULL;
goto end;
}
fp = NULL;
/* decode params from file */
if (!TEST_ptr(fp = fopen("params.der", "rb"))
|| !TEST_ptr(g2 = d2i_ECPKParameters_fp(fp, NULL)))
goto end;
testresult = 1; /* PASS */
end:
if (fp != NULL)
fclose(fp);
EC_GROUP_free(g1);
EC_GROUP_free(g2);
return testresult;
}
int setup_tests(void)
{
crv_len = EC_get_builtin_curves(NULL, 0);
if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
|| !TEST_true(EC_get_builtin_curves(curves, crv_len)))
return 0;
ADD_TEST(field_tests_ecp_simple);
ADD_TEST(field_tests_ecp_mont);
#ifndef OPENSSL_NO_EC2M
+ ADD_TEST(ec2m_field_sanity);
ADD_TEST(field_tests_ec2_simple);
#endif
ADD_ALL_TESTS(field_tests_default, crv_len);
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
ADD_TEST(underflow_test);
#endif
ADD_TEST(set_private_key);
ADD_TEST(decoded_flag_test);
ADD_ALL_TESTS(ecpkparams_i2d2i_test, crv_len);
return 1;
}
void cleanup_tests(void)
{
OPENSSL_free(curves);
}
diff --git a/crypto/openssl/test/enginetest.c b/crypto/openssl/test/enginetest.c
index 8ba999b0176b..79ffb2305485 100644
--- a/crypto/openssl/test/enginetest.c
+++ b/crypto/openssl/test/enginetest.c
@@ -1,465 +1,465 @@
/*
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* We need to use some deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/e_os2.h>
# include "testutil.h"
#ifndef OPENSSL_NO_ENGINE
# include <openssl/buffer.h>
# include <openssl/crypto.h>
# include <openssl/engine.h>
# include <openssl/rsa.h>
# include <openssl/err.h>
# include <openssl/x509.h>
# include <openssl/pem.h>
static void display_engine_list(void)
{
ENGINE *h;
int loop;
loop = 0;
for (h = ENGINE_get_first(); h != NULL; h = ENGINE_get_next(h)) {
TEST_info("#%d: id = \"%s\", name = \"%s\"",
loop++, ENGINE_get_id(h), ENGINE_get_name(h));
}
/*
* ENGINE_get_first() increases the struct_ref counter, so we must call
* ENGINE_free() to decrease it again
*/
ENGINE_free(h);
}
#define NUMTOADD 512
static int test_engines(void)
{
ENGINE *block[NUMTOADD];
char *eid[NUMTOADD];
char *ename[NUMTOADD];
char buf[256];
ENGINE *ptr;
int loop;
int to_return = 0;
ENGINE *new_h1 = NULL;
ENGINE *new_h2 = NULL;
ENGINE *new_h3 = NULL;
ENGINE *new_h4 = NULL;
memset(block, 0, sizeof(block));
if (!TEST_ptr(new_h1 = ENGINE_new())
|| !TEST_true(ENGINE_set_id(new_h1, "test_id0"))
|| !TEST_true(ENGINE_set_name(new_h1, "First test item"))
|| !TEST_ptr(new_h2 = ENGINE_new())
|| !TEST_true(ENGINE_set_id(new_h2, "test_id1"))
|| !TEST_true(ENGINE_set_name(new_h2, "Second test item"))
|| !TEST_ptr(new_h3 = ENGINE_new())
|| !TEST_true(ENGINE_set_id(new_h3, "test_id2"))
|| !TEST_true(ENGINE_set_name(new_h3, "Third test item"))
|| !TEST_ptr(new_h4 = ENGINE_new())
|| !TEST_true(ENGINE_set_id(new_h4, "test_id3"))
|| !TEST_true(ENGINE_set_name(new_h4, "Fourth test item")))
goto end;
TEST_info("Engines:");
display_engine_list();
if (!TEST_true(ENGINE_add(new_h1)))
goto end;
TEST_info("Engines:");
display_engine_list();
ptr = ENGINE_get_first();
if (!TEST_true(ENGINE_remove(ptr)))
goto end;
ENGINE_free(ptr);
TEST_info("Engines:");
display_engine_list();
if (!TEST_true(ENGINE_add(new_h3))
|| !TEST_true(ENGINE_add(new_h2)))
goto end;
TEST_info("Engines:");
display_engine_list();
if (!TEST_true(ENGINE_remove(new_h2)))
goto end;
TEST_info("Engines:");
display_engine_list();
if (!TEST_true(ENGINE_add(new_h4)))
goto end;
TEST_info("Engines:");
display_engine_list();
/* Should fail. */
if (!TEST_false(ENGINE_add(new_h3)))
goto end;
ERR_clear_error();
/* Should fail. */
if (!TEST_false(ENGINE_remove(new_h2)))
goto end;
ERR_clear_error();
if (!TEST_true(ENGINE_remove(new_h3)))
goto end;
TEST_info("Engines:");
display_engine_list();
if (!TEST_true(ENGINE_remove(new_h4)))
goto end;
TEST_info("Engines:");
display_engine_list();
/*
* At this point, we should have an empty list, unless some hardware
* support engine got added. However, since we don't allow the config
* file to be loaded and don't otherwise load any built in engines,
* that is unlikely. Still, we check, if for nothing else, then to
* notify that something is a little off (and might mean that |new_h1|
* wasn't unloaded when it should have)
*/
if ((ptr = ENGINE_get_first()) != NULL) {
if (!ENGINE_remove(ptr))
TEST_info("Remove failed - probably no hardware support present");
}
ENGINE_free(ptr);
TEST_info("Engines:");
display_engine_list();
if (!TEST_true(ENGINE_add(new_h1))
|| !TEST_true(ENGINE_remove(new_h1)))
goto end;
TEST_info("About to beef up the engine-type list");
for (loop = 0; loop < NUMTOADD; loop++) {
- sprintf(buf, "id%d", loop);
+ BIO_snprintf(buf, sizeof(buf), "id%d", loop);
eid[loop] = OPENSSL_strdup(buf);
- sprintf(buf, "Fake engine type %d", loop);
+ BIO_snprintf(buf, sizeof(buf), "Fake engine type %d", loop);
ename[loop] = OPENSSL_strdup(buf);
if (!TEST_ptr(block[loop] = ENGINE_new())
|| !TEST_true(ENGINE_set_id(block[loop], eid[loop]))
|| !TEST_true(ENGINE_set_name(block[loop], ename[loop])))
goto end;
}
for (loop = 0; loop < NUMTOADD; loop++) {
if (!TEST_true(ENGINE_add(block[loop]))) {
test_note("Adding stopped at %d, (%s,%s)",
loop, ENGINE_get_id(block[loop]),
ENGINE_get_name(block[loop]));
goto cleanup_loop;
}
}
cleanup_loop:
TEST_info("About to empty the engine-type list");
while ((ptr = ENGINE_get_first()) != NULL) {
if (!TEST_true(ENGINE_remove(ptr)))
goto end;
ENGINE_free(ptr);
}
for (loop = 0; loop < NUMTOADD; loop++) {
OPENSSL_free(eid[loop]);
OPENSSL_free(ename[loop]);
}
to_return = 1;
end:
ENGINE_free(new_h1);
ENGINE_free(new_h2);
ENGINE_free(new_h3);
ENGINE_free(new_h4);
for (loop = 0; loop < NUMTOADD; loop++)
ENGINE_free(block[loop]);
return to_return;
}
/* Test EVP_PKEY method */
static EVP_PKEY_METHOD *test_rsa = NULL;
static int called_encrypt = 0;
/* Test function to check operation has been redirected */
static int test_encrypt(EVP_PKEY_CTX *ctx, unsigned char *sig,
size_t *siglen, const unsigned char *tbs, size_t tbslen)
{
called_encrypt = 1;
return 1;
}
static int test_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
const int **pnids, int nid)
{
static const int rnid = EVP_PKEY_RSA;
if (pmeth == NULL) {
*pnids = &rnid;
return 1;
}
if (nid == EVP_PKEY_RSA) {
*pmeth = test_rsa;
return 1;
}
*pmeth = NULL;
return 0;
}
/* Return a test EVP_PKEY value */
static EVP_PKEY *get_test_pkey(void)
{
static unsigned char n[] =
"\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
"\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
"\xAD\xB3\x00\xA0\x28\x5E\x53\x01\x93\x0E\x0C\x70\xFB\x68\x76\x93"
"\x9C\xE6\x16\xCE\x62\x4A\x11\xE0\x08\x6D\x34\x1E\xBC\xAC\xA0\xA1"
"\xF5";
static unsigned char e[] = "\x11";
RSA *rsa = RSA_new();
EVP_PKEY *pk = EVP_PKEY_new();
if (rsa == NULL || pk == NULL || !EVP_PKEY_assign_RSA(pk, rsa)) {
RSA_free(rsa);
EVP_PKEY_free(pk);
return NULL;
}
if (!RSA_set0_key(rsa, BN_bin2bn(n, sizeof(n)-1, NULL),
BN_bin2bn(e, sizeof(e)-1, NULL), NULL)) {
EVP_PKEY_free(pk);
return NULL;
}
return pk;
}
static int test_redirect(void)
{
const unsigned char pt[] = "Hello World\n";
unsigned char *tmp = NULL;
size_t len;
EVP_PKEY_CTX *ctx = NULL;
ENGINE *e = NULL;
EVP_PKEY *pkey = NULL;
int to_return = 0;
if (!TEST_ptr(pkey = get_test_pkey()))
goto err;
len = EVP_PKEY_get_size(pkey);
if (!TEST_ptr(tmp = OPENSSL_malloc(len)))
goto err;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)))
goto err;
TEST_info("EVP_PKEY_encrypt test: no redirection");
/* Encrypt some data: should succeed but not be redirected */
if (!TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0)
|| !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0)
|| !TEST_false(called_encrypt))
goto err;
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
/* Create a test ENGINE */
if (!TEST_ptr(e = ENGINE_new())
|| !TEST_true(ENGINE_set_id(e, "Test redirect engine"))
|| !TEST_true(ENGINE_set_name(e, "Test redirect engine")))
goto err;
/*
* Try to create a context for this engine and test key.
* Try setting test key engine. Both should fail because the
* engine has no public key methods.
*/
if (!TEST_ptr_null(ctx = EVP_PKEY_CTX_new(pkey, e))
|| !TEST_int_le(EVP_PKEY_set1_engine(pkey, e), 0))
goto err;
/* Setup an empty test EVP_PKEY_METHOD and set callback to return it */
if (!TEST_ptr(test_rsa = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0)))
goto err;
ENGINE_set_pkey_meths(e, test_pkey_meths);
/* Getting a context for test ENGINE should now succeed */
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, e)))
goto err;
/* Encrypt should fail because operation is not supported */
if (!TEST_int_le(EVP_PKEY_encrypt_init(ctx), 0))
goto err;
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
/* Add test encrypt operation to method */
EVP_PKEY_meth_set_encrypt(test_rsa, 0, test_encrypt);
TEST_info("EVP_PKEY_encrypt test: redirection via EVP_PKEY_CTX_new()");
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, e)))
goto err;
/* Encrypt some data: should succeed and be redirected */
if (!TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0)
|| !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0)
|| !TEST_true(called_encrypt))
goto err;
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
called_encrypt = 0;
/* Create context with default engine: should not be redirected */
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL))
|| !TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0)
|| !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0)
|| !TEST_false(called_encrypt))
goto err;
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
/* Set engine explicitly for test key */
if (!TEST_true(EVP_PKEY_set1_engine(pkey, e)))
goto err;
TEST_info("EVP_PKEY_encrypt test: redirection via EVP_PKEY_set1_engine()");
/* Create context with default engine: should be redirected now */
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL))
|| !TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0)
|| !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0)
|| !TEST_true(called_encrypt))
goto err;
to_return = 1;
err:
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
ENGINE_free(e);
OPENSSL_free(tmp);
return to_return;
}
static int test_x509_dup_w_engine(void)
{
ENGINE *e = NULL;
X509 *cert = NULL, *dupcert = NULL;
X509_PUBKEY *pubkey, *duppubkey = NULL;
int ret = 0;
BIO *b = NULL;
RSA_METHOD *rsameth = NULL;
if (!TEST_ptr(b = BIO_new_file(test_get_argument(0), "r"))
|| !TEST_ptr(cert = PEM_read_bio_X509(b, NULL, NULL, NULL)))
goto err;
/* Dup without an engine */
if (!TEST_ptr(dupcert = X509_dup(cert)))
goto err;
X509_free(dupcert);
dupcert = NULL;
if (!TEST_ptr(pubkey = X509_get_X509_PUBKEY(cert))
|| !TEST_ptr(duppubkey = X509_PUBKEY_dup(pubkey))
|| !TEST_ptr_ne(duppubkey, pubkey)
|| !TEST_ptr_ne(X509_PUBKEY_get0(duppubkey), X509_PUBKEY_get0(pubkey)))
goto err;
X509_PUBKEY_free(duppubkey);
duppubkey = NULL;
X509_free(cert);
cert = NULL;
/* Create a test ENGINE */
if (!TEST_ptr(e = ENGINE_new())
|| !TEST_true(ENGINE_set_id(e, "Test dummy engine"))
|| !TEST_true(ENGINE_set_name(e, "Test dummy engine")))
goto err;
if (!TEST_ptr(rsameth = RSA_meth_dup(RSA_get_default_method())))
goto err;
ENGINE_set_RSA(e, rsameth);
if (!TEST_true(ENGINE_set_default_RSA(e)))
goto err;
if (!TEST_int_ge(BIO_seek(b, 0), 0)
|| !TEST_ptr(cert = PEM_read_bio_X509(b, NULL, NULL, NULL)))
goto err;
/* Dup with an engine set on the key */
if (!TEST_ptr(dupcert = X509_dup(cert)))
goto err;
if (!TEST_ptr(pubkey = X509_get_X509_PUBKEY(cert))
|| !TEST_ptr(duppubkey = X509_PUBKEY_dup(pubkey))
|| !TEST_ptr_ne(duppubkey, pubkey)
|| !TEST_ptr_ne(X509_PUBKEY_get0(duppubkey), X509_PUBKEY_get0(pubkey)))
goto err;
ret = 1;
err:
X509_free(cert);
X509_free(dupcert);
X509_PUBKEY_free(duppubkey);
if (e != NULL) {
ENGINE_unregister_RSA(e);
ENGINE_free(e);
}
RSA_meth_free(rsameth);
BIO_free(b);
return ret;
}
#endif
int global_init(void)
{
/*
* If the config file gets loaded, the dynamic engine will be loaded,
* and that interferes with our test above.
*/
return OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL);
}
OPT_TEST_DECLARE_USAGE("certfile\n")
int setup_tests(void)
{
#ifdef OPENSSL_NO_ENGINE
TEST_note("No ENGINE support");
#else
int n;
if (!test_skip_common_options()) {
TEST_error("Error parsing test options\n");
return 0;
}
n = test_get_argument_count();
if (n == 0)
return 0;
ADD_TEST(test_engines);
ADD_TEST(test_redirect);
ADD_TEST(test_x509_dup_w_engine);
#endif
return 1;
}
diff --git a/crypto/openssl/test/evp_kdf_test.c b/crypto/openssl/test/evp_kdf_test.c
index 8f35900bdd8b..0ee1aaea6f37 100644
--- a/crypto/openssl/test/evp_kdf_test.c
+++ b/crypto/openssl/test/evp_kdf_test.c
@@ -1,1738 +1,1744 @@
/*
- * Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018-2020, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* Tests of the EVP_KDF_CTX APIs */
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/core_names.h>
#include "internal/numbers.h"
#include "testutil.h"
static EVP_KDF_CTX *get_kdfbyname_libctx(OSSL_LIB_CTX *libctx, const char *name)
{
EVP_KDF *kdf = EVP_KDF_fetch(libctx, name, NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
return kctx;
}
static EVP_KDF_CTX *get_kdfbyname(const char *name)
{
return get_kdfbyname_libctx(NULL, name);
}
static OSSL_PARAM *construct_tls1_prf_params(const char *digest, const char *secret,
const char *seed)
{
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 4);
OSSL_PARAM *p = params;
if (params == NULL)
return NULL;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)digest, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
(unsigned char *)secret,
strlen(secret));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
(unsigned char *)seed,
strlen(seed));
*p = OSSL_PARAM_construct_end();
return params;
}
static int test_kdf_tls1_prf(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[16];
OSSL_PARAM *params;
static const unsigned char expected[sizeof(out)] = {
0x8e, 0x4d, 0x93, 0x25, 0x30, 0xd7, 0x65, 0xa0,
0xaa, 0xe9, 0x74, 0xc3, 0x04, 0x73, 0x5e, 0xcc
};
params = construct_tls1_prf_params("sha256", "secret", "seed");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_tls1_prf_invalid_digest(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM *params;
params = construct_tls1_prf_params("blah", "secret", "seed");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_false(EVP_KDF_CTX_set_params(kctx, params));
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_tls1_prf_zero_output_size(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[16];
OSSL_PARAM *params;
params = construct_tls1_prf_params("sha256", "secret", "seed");
/* Negative test - derive should fail */
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
&& TEST_int_eq(EVP_KDF_derive(kctx, out, 0, NULL), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_tls1_prf_empty_secret(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[16];
OSSL_PARAM *params;
params = construct_tls1_prf_params("sha256", "", "seed");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_tls1_prf_1byte_secret(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[16];
OSSL_PARAM *params;
params = construct_tls1_prf_params("sha256", "1", "seed");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_tls1_prf_empty_seed(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[16];
OSSL_PARAM *params;
params = construct_tls1_prf_params("sha256", "secret", "");
/* Negative test - derive should fail */
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
&& TEST_int_eq(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_tls1_prf_1byte_seed(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[16];
OSSL_PARAM *params;
params = construct_tls1_prf_params("sha256", "secret", "1");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static OSSL_PARAM *construct_hkdf_params(char *digest, char *key,
size_t keylen, char *salt, char *info)
{
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 5);
OSSL_PARAM *p = params;
if (params == NULL)
return NULL;
if (digest != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
digest, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
salt, strlen(salt));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
(unsigned char *)key, keylen);
if (info != NULL)
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
info, strlen(info));
else
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE,
"EXTRACT_ONLY", 0);
*p = OSSL_PARAM_construct_end();
return params;
}
static int test_kdf_hkdf(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
static const unsigned char expected[sizeof(out)] = {
0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8, 0xde, 0x13
};
params = construct_hkdf_params("sha256", "secret", 6, "salt", "label");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int do_kdf_hkdf_gettables(int expand_only, int has_digest)
{
int ret = 0;
size_t sz = 0;
OSSL_PARAM *params;
OSSL_PARAM params_get[2];
const OSSL_PARAM *gettables, *p;
EVP_KDF_CTX *kctx = NULL;
if (!TEST_ptr(params = construct_hkdf_params(
has_digest ? "sha256" : NULL,
"secret", 6, "salt",
expand_only ? NULL : "label"))
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params)))
goto err;
/* Check OSSL_KDF_PARAM_SIZE is gettable */
if (!TEST_ptr(gettables = EVP_KDF_CTX_gettable_params(kctx))
|| !TEST_ptr(p = OSSL_PARAM_locate_const(gettables, OSSL_KDF_PARAM_SIZE)))
goto err;
/* Get OSSL_KDF_PARAM_SIZE as a size_t */
params_get[0] = OSSL_PARAM_construct_size_t(OSSL_KDF_PARAM_SIZE, &sz);
params_get[1] = OSSL_PARAM_construct_end();
if (has_digest) {
if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), 1)
|| !TEST_size_t_eq(sz, expand_only ? SHA256_DIGEST_LENGTH : SIZE_MAX))
goto err;
} else {
if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), 0))
goto err;
}
/* Get params returns -2 if an unsupported parameter is requested */
params_get[0] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), -2))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_hkdf_gettables(void)
{
return do_kdf_hkdf_gettables(0, 1);
}
static int test_kdf_hkdf_gettables_expandonly(void)
{
return do_kdf_hkdf_gettables(1, 1);
}
static int test_kdf_hkdf_gettables_no_digest(void)
{
return do_kdf_hkdf_gettables(1, 0);
}
static int test_kdf_hkdf_invalid_digest(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM *params;
params = construct_hkdf_params("blah", "secret", 6, "salt", "label");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_false(EVP_KDF_CTX_set_params(kctx, params));
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_hkdf_derive_set_params_fail(void)
{
int ret = 0, i = 0;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM params[2];
unsigned char out[10];
if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF)))
goto end;
/*
* Set the wrong type for the digest so that it causes a failure
* inside kdf_hkdf_derive() when kdf_hkdf_set_ctx_params() is called
*/
params[0] = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_DIGEST, &i);
params[1] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_KDF_derive(kctx, out, sizeof(out), params), 0))
goto end;
ret = 1;
end:
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_hkdf_set_invalid_mode(void)
{
int ret = 0, bad_mode = 100;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM params[2];
if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF)))
goto end;
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE,
"BADMODE", 0);
params[1] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_KDF_CTX_set_params(kctx, params), 0))
goto end;
params[0] = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &bad_mode);
if (!TEST_int_eq(EVP_KDF_CTX_set_params(kctx, params), 0))
goto end;
ret = 1;
end:
EVP_KDF_CTX_free(kctx);
return ret;
}
static int do_kdf_hkdf_set_invalid_param(const char *key, int type)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM params[2];
unsigned char buf[2];
if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF)))
goto end;
/* Set the wrong type for the key so that it causes a failure */
if (type == OSSL_PARAM_UTF8_STRING)
params[0] = OSSL_PARAM_construct_utf8_string(key, "BAD", 0);
else
params[0] = OSSL_PARAM_construct_octet_string(key, buf, sizeof(buf));
params[1] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_KDF_CTX_set_params(kctx, params), 0))
goto end;
ret = 1;
end:
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_hkdf_set_ctx_param_fail(void)
{
return do_kdf_hkdf_set_invalid_param(OSSL_KDF_PARAM_MODE,
OSSL_PARAM_OCTET_STRING)
&& do_kdf_hkdf_set_invalid_param(OSSL_KDF_PARAM_KEY,
OSSL_PARAM_UTF8_STRING)
&& do_kdf_hkdf_set_invalid_param(OSSL_KDF_PARAM_SALT,
OSSL_PARAM_UTF8_STRING)
&& do_kdf_hkdf_set_invalid_param(OSSL_KDF_PARAM_INFO,
OSSL_PARAM_UTF8_STRING);
}
static int test_kdf_hkdf_zero_output_size(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
params = construct_hkdf_params("sha256", "secret", 6, "salt", "label");
/* Negative test - derive should fail */
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
&& TEST_int_eq(EVP_KDF_derive(kctx, out, 0, NULL), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_hkdf_empty_key(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
params = construct_hkdf_params("sha256", "", 0, "salt", "label");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_hkdf_1byte_key(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
params = construct_hkdf_params("sha256", "1", 1, "salt", "label");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_hkdf_empty_salt(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
params = construct_hkdf_params("sha256", "secret", 6, "", "label");
ret = TEST_ptr(params)
&& TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static OSSL_PARAM *construct_pbkdf1_params(char *pass, char *digest, char *salt,
unsigned int *iter)
{
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 5);
OSSL_PARAM *p = params;
if (params == NULL)
return NULL;
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
(unsigned char *)pass, strlen(pass));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
(unsigned char *)salt, strlen(salt));
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_ITER, iter);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
digest, 0);
*p = OSSL_PARAM_construct_end();
return params;
}
static int test_kdf_pbkdf1(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 4096;
OSSL_LIB_CTX *libctx = NULL;
OSSL_PARAM *params = NULL;
OSSL_PROVIDER *legacyprov = NULL;
OSSL_PROVIDER *defprov = NULL;
const unsigned char expected[sizeof(out)] = {
0xfb, 0x83, 0x4d, 0x36, 0x6d, 0xbc, 0x53, 0x87, 0x35, 0x1b, 0x34, 0x75,
0x95, 0x88, 0x32, 0x4f, 0x3e, 0x82, 0x81, 0x01, 0x21, 0x93, 0x64, 0x00,
0xcc
};
if (!TEST_ptr(libctx = OSSL_LIB_CTX_new()))
goto err;
/* PBKDF1 only available in the legacy provider */
legacyprov = OSSL_PROVIDER_load(libctx, "legacy");
if (legacyprov == NULL) {
OSSL_LIB_CTX_free(libctx);
return TEST_skip("PBKDF1 only available in legacy provider");
}
if (!TEST_ptr(defprov = OSSL_PROVIDER_load(libctx, "default")))
goto err;
params = construct_pbkdf1_params("passwordPASSWORDpassword", "sha256",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname_libctx(libctx, OSSL_KDF_NAME_PBKDF1))
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|| !TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0)
|| !TEST_mem_eq(out, sizeof(out), expected, sizeof(expected)))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
OSSL_PROVIDER_unload(defprov);
OSSL_PROVIDER_unload(legacyprov);
OSSL_LIB_CTX_free(libctx);
return ret;
}
static int test_kdf_pbkdf1_key_too_long(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[EVP_MAX_MD_SIZE + 1];
unsigned int iterations = 4096;
OSSL_LIB_CTX *libctx = NULL;
OSSL_PARAM *params = NULL;
OSSL_PROVIDER *legacyprov = NULL;
OSSL_PROVIDER *defprov = NULL;
if (!TEST_ptr(libctx = OSSL_LIB_CTX_new()))
goto err;
/* PBKDF1 only available in the legacy provider */
legacyprov = OSSL_PROVIDER_load(libctx, "legacy");
if (legacyprov == NULL) {
OSSL_LIB_CTX_free(libctx);
return TEST_skip("PBKDF1 only available in legacy provider");
}
if (!TEST_ptr(defprov = OSSL_PROVIDER_load(libctx, "default")))
goto err;
params = construct_pbkdf1_params("passwordPASSWORDpassword", "sha256",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations);
/*
* This is the same test sequence as test_kdf_pbkdf1, but we expect
* failure here as the requested key size is longer than the digest
* can provide
*/
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname_libctx(libctx, OSSL_KDF_NAME_PBKDF1))
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|| !TEST_int_eq(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
OSSL_PROVIDER_unload(defprov);
OSSL_PROVIDER_unload(legacyprov);
OSSL_LIB_CTX_free(libctx);
return ret;
}
static OSSL_PARAM *construct_pbkdf2_params(char *pass, char *digest, char *salt,
unsigned int *iter, int *mode)
{
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 6);
OSSL_PARAM *p = params;
if (params == NULL)
return NULL;
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
(unsigned char *)pass, strlen(pass));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
(unsigned char *)salt, strlen(salt));
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_ITER, iter);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
digest, 0);
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS5, mode);
*p = OSSL_PARAM_construct_end();
return params;
}
static int test_kdf_pbkdf2(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 4096;
int mode = 0;
OSSL_PARAM *params;
const unsigned char expected[sizeof(out)] = {
0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f,
0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf,
0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18,
0x1c
};
params = construct_pbkdf2_params("passwordPASSWORDpassword", "sha256",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
|| !TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
|| !TEST_mem_eq(out, sizeof(out), expected, sizeof(expected)))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_pbkdf2_small_output(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 4096;
int mode = 0;
OSSL_PARAM *params;
params = construct_pbkdf2_params("passwordPASSWORDpassword", "sha256",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
/* A key length that is too small should fail */
|| !TEST_int_eq(EVP_KDF_derive(kctx, out, 112 / 8 - 1, NULL), 0))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_pbkdf2_large_output(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
size_t len = 0;
unsigned int iterations = 4096;
int mode = 0;
OSSL_PARAM *params;
if (sizeof(len) > 32)
len = SIZE_MAX;
params = construct_pbkdf2_params("passwordPASSWORDpassword", "sha256",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* A key length that is too large should fail */
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|| (len != 0 && !TEST_int_eq(EVP_KDF_derive(kctx, out, len, NULL), 0)))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_pbkdf2_small_salt(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned int iterations = 4096;
int mode = 0;
OSSL_PARAM *params;
params = construct_pbkdf2_params("passwordPASSWORDpassword", "sha256",
"saltSALT",
&iterations, &mode);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* A salt that is too small should fail */
|| !TEST_false(EVP_KDF_CTX_set_params(kctx, params)))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_pbkdf2_small_iterations(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned int iterations = 1;
int mode = 0;
OSSL_PARAM *params;
params = construct_pbkdf2_params("passwordPASSWORDpassword", "sha256",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* An iteration count that is too small should fail */
|| !TEST_false(EVP_KDF_CTX_set_params(kctx, params)))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_pbkdf2_small_salt_pkcs5(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 4096;
int mode = 1;
OSSL_PARAM *params;
OSSL_PARAM mode_params[2];
params = construct_pbkdf2_params("passwordPASSWORDpassword", "sha256",
"saltSALT",
&iterations, &mode);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* A salt that is too small should pass in pkcs5 mode */
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|| !TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0))
goto err;
mode = 0;
mode_params[0] = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS5, &mode);
mode_params[1] = OSSL_PARAM_construct_end();
/* If the "pkcs5" mode is disabled then the derive will now fail */
if (!TEST_true(EVP_KDF_CTX_set_params(kctx, mode_params))
|| !TEST_int_eq(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_pbkdf2_small_iterations_pkcs5(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 1;
int mode = 1;
OSSL_PARAM *params;
OSSL_PARAM mode_params[2];
params = construct_pbkdf2_params("passwordPASSWORDpassword", "sha256",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* An iteration count that is too small will pass in pkcs5 mode */
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|| !TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0))
goto err;
mode = 0;
mode_params[0] = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS5, &mode);
mode_params[1] = OSSL_PARAM_construct_end();
/* If the "pkcs5" mode is disabled then the derive will now fail */
if (!TEST_true(EVP_KDF_CTX_set_params(kctx, mode_params))
|| !TEST_int_eq(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_pbkdf2_invalid_digest(void)
{
int ret = 0;
EVP_KDF_CTX *kctx = NULL;
unsigned int iterations = 4096;
int mode = 0;
OSSL_PARAM *params;
params = construct_pbkdf2_params("passwordPASSWORDpassword", "blah",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
if (!TEST_ptr(params)
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* Unknown digest should fail */
|| !TEST_false(EVP_KDF_CTX_set_params(kctx, params)))
goto err;
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
#ifndef OPENSSL_NO_SCRYPT
static int test_kdf_scrypt(void)
{
- int ret;
+ int i, ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[7], *p = params;
unsigned char out[64];
unsigned int nu = 1024, ru = 8, pu = 16, maxmem = 16;
static const unsigned char expected[sizeof(out)] = {
0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
};
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
(char *)"password", 8);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
(char *)"NaCl", 4);
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_SCRYPT_N, &nu);
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_SCRYPT_R, &ru);
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_SCRYPT_P, &pu);
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_SCRYPT_MAXMEM, &maxmem);
*p = OSSL_PARAM_construct_end();
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_SCRYPT))
- && TEST_true(EVP_KDF_CTX_set_params(kctx, params))
- /* failure test *//*
- && TEST_int_le(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0)*/
- && TEST_true(OSSL_PARAM_set_uint(p - 1, 10 * 1024 * 1024))
- && TEST_true(EVP_KDF_CTX_set_params(kctx, p - 1))
- && TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0)
- && TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
+ ret = TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_SCRYPT));
+ for (i = 0; ret && i < 2; ++i) {
+ ret = ret
+ && TEST_true(EVP_KDF_CTX_set_params(kctx, params));
+ if (i == 0)
+ ret = ret
+ && TEST_int_le(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0)
+ && TEST_true(OSSL_PARAM_set_uint(p - 1, 10 * 1024 * 1024))
+ && TEST_true(EVP_KDF_CTX_set_params(kctx, p - 1));
+ ret = ret
+ && TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0)
+ && TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
+ if (i == 0)
+ EVP_KDF_CTX_reset(kctx);
+ }
EVP_KDF_CTX_free(kctx);
return ret;
}
#endif /* OPENSSL_NO_SCRYPT */
static int test_kdf_ss_hash(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[4], *p = params;
unsigned char out[14];
static unsigned char z[] = {
0x6d,0xbd,0xc2,0x3f,0x04,0x54,0x88,0xe4,0x06,0x27,0x57,0xb0,0x6b,0x9e,
0xba,0xe1,0x83,0xfc,0x5a,0x59,0x46,0xd8,0x0d,0xb9,0x3f,0xec,0x6f,0x62,
0xec,0x07,0xe3,0x72,0x7f,0x01,0x26,0xae,0xd1,0x2c,0xe4,0xb2,0x62,0xf4,
0x7d,0x48,0xd5,0x42,0x87,0xf8,0x1d,0x47,0x4c,0x7c,0x3b,0x18,0x50,0xe9
};
static unsigned char other[] = {
0xa1,0xb2,0xc3,0xd4,0xe5,0x43,0x41,0x56,0x53,0x69,0x64,0x3c,0x83,0x2e,
0x98,0x49,0xdc,0xdb,0xa7,0x1e,0x9a,0x31,0x39,0xe6,0x06,0xe0,0x95,0xde,
0x3c,0x26,0x4a,0x66,0xe9,0x8a,0x16,0x58,0x54,0xcd,0x07,0x98,0x9b,0x1e,
0xe0,0xec,0x3f,0x8d,0xbe
};
static const unsigned char expected[sizeof(out)] = {
0xa4,0x62,0xde,0x16,0xa8,0x9d,0xe8,0x46,0x6e,0xf5,0x46,0x0b,0x47,0xb8
};
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)"sha224", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, z, sizeof(z));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, other,
sizeof(other));
*p = OSSL_PARAM_construct_end();
ret =
TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_SSKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_x963(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[4], *p = params;
unsigned char out[1024 / 8];
/*
* Test data from https://csrc.nist.gov/CSRC/media/Projects/
* Cryptographic-Algorithm-Validation-Program/documents/components/
* 800-135testvectors/ansx963_2001.zip
*/
static unsigned char z[] = {
0x00, 0xaa, 0x5b, 0xb7, 0x9b, 0x33, 0xe3, 0x89, 0xfa, 0x58, 0xce, 0xad,
0xc0, 0x47, 0x19, 0x7f, 0x14, 0xe7, 0x37, 0x12, 0xf4, 0x52, 0xca, 0xa9,
0xfc, 0x4c, 0x9a, 0xdb, 0x36, 0x93, 0x48, 0xb8, 0x15, 0x07, 0x39, 0x2f,
0x1a, 0x86, 0xdd, 0xfd, 0xb7, 0xc4, 0xff, 0x82, 0x31, 0xc4, 0xbd, 0x0f,
0x44, 0xe4, 0x4a, 0x1b, 0x55, 0xb1, 0x40, 0x47, 0x47, 0xa9, 0xe2, 0xe7,
0x53, 0xf5, 0x5e, 0xf0, 0x5a, 0x2d
};
static unsigned char shared[] = {
0xe3, 0xb5, 0xb4, 0xc1, 0xb0, 0xd5, 0xcf, 0x1d, 0x2b, 0x3a, 0x2f, 0x99,
0x37, 0x89, 0x5d, 0x31
};
static const unsigned char expected[sizeof(out)] = {
0x44, 0x63, 0xf8, 0x69, 0xf3, 0xcc, 0x18, 0x76, 0x9b, 0x52, 0x26, 0x4b,
0x01, 0x12, 0xb5, 0x85, 0x8f, 0x7a, 0xd3, 0x2a, 0x5a, 0x2d, 0x96, 0xd8,
0xcf, 0xfa, 0xbf, 0x7f, 0xa7, 0x33, 0x63, 0x3d, 0x6e, 0x4d, 0xd2, 0xa5,
0x99, 0xac, 0xce, 0xb3, 0xea, 0x54, 0xa6, 0x21, 0x7c, 0xe0, 0xb5, 0x0e,
0xef, 0x4f, 0x6b, 0x40, 0xa5, 0xc3, 0x02, 0x50, 0xa5, 0xa8, 0xee, 0xee,
0x20, 0x80, 0x02, 0x26, 0x70, 0x89, 0xdb, 0xf3, 0x51, 0xf3, 0xf5, 0x02,
0x2a, 0xa9, 0x63, 0x8b, 0xf1, 0xee, 0x41, 0x9d, 0xea, 0x9c, 0x4f, 0xf7,
0x45, 0xa2, 0x5a, 0xc2, 0x7b, 0xda, 0x33, 0xca, 0x08, 0xbd, 0x56, 0xdd,
0x1a, 0x59, 0xb4, 0x10, 0x6c, 0xf2, 0xdb, 0xbc, 0x0a, 0xb2, 0xaa, 0x8e,
0x2e, 0xfa, 0x7b, 0x17, 0x90, 0x2d, 0x34, 0x27, 0x69, 0x51, 0xce, 0xcc,
0xab, 0x87, 0xf9, 0x66, 0x1c, 0x3e, 0x88, 0x16
};
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)"sha512", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, z, sizeof(z));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, shared,
sizeof(shared));
*p = OSSL_PARAM_construct_end();
ret =
TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_X963KDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
return ret;
}
#if !defined(OPENSSL_NO_CMAC) && !defined(OPENSSL_NO_CAMELLIA)
/*
* KBKDF test vectors from RFC 6803 (Camellia Encryption for Kerberos 5)
* section 10.
*/
static int test_kdf_kbkdf_6803_128(void)
{
int ret = 0, i, p;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[7];
static unsigned char input_key[] = {
0x57, 0xD0, 0x29, 0x72, 0x98, 0xFF, 0xD9, 0xD3,
0x5D, 0xE5, 0xA4, 0x7F, 0xB4, 0xBD, 0xE2, 0x4B,
};
static unsigned char constants[][5] = {
{ 0x00, 0x00, 0x00, 0x02, 0x99 },
{ 0x00, 0x00, 0x00, 0x02, 0xaa },
{ 0x00, 0x00, 0x00, 0x02, 0x55 },
};
static unsigned char outputs[][16] = {
{0xD1, 0x55, 0x77, 0x5A, 0x20, 0x9D, 0x05, 0xF0,
0x2B, 0x38, 0xD4, 0x2A, 0x38, 0x9E, 0x5A, 0x56},
{0x64, 0xDF, 0x83, 0xF8, 0x5A, 0x53, 0x2F, 0x17,
0x57, 0x7D, 0x8C, 0x37, 0x03, 0x57, 0x96, 0xAB},
{0x3E, 0x4F, 0xBD, 0xF3, 0x0F, 0xB8, 0x25, 0x9C,
0x42, 0x5C, 0xB6, 0xC9, 0x6F, 0x1F, 0x46, 0x35}
};
static unsigned char iv[16] = { 0 };
unsigned char result[16] = { 0 };
for (i = 0; i < 3; i++) {
p = 0;
params[p++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_CIPHER, "CAMELLIA-128-CBC", 0);
params[p++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MAC, "CMAC", 0);
params[p++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MODE, "FEEDBACK", 0);
params[p++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_KEY, input_key, sizeof(input_key));
params[p++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_SALT, constants[i], sizeof(constants[i]));
params[p++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_SEED, iv, sizeof(iv));
params[p] = OSSL_PARAM_construct_end();
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result),
params), 0)
&& TEST_mem_eq(result, sizeof(result), outputs[i],
sizeof(outputs[i]));
EVP_KDF_CTX_free(kctx);
if (ret != 1)
return ret;
}
return ret;
}
static int test_kdf_kbkdf_6803_256(void)
{
int ret = 0, i, p;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[7];
static unsigned char input_key[] = {
0xB9, 0xD6, 0x82, 0x8B, 0x20, 0x56, 0xB7, 0xBE,
0x65, 0x6D, 0x88, 0xA1, 0x23, 0xB1, 0xFA, 0xC6,
0x82, 0x14, 0xAC, 0x2B, 0x72, 0x7E, 0xCF, 0x5F,
0x69, 0xAF, 0xE0, 0xC4, 0xDF, 0x2A, 0x6D, 0x2C,
};
static unsigned char constants[][5] = {
{ 0x00, 0x00, 0x00, 0x02, 0x99 },
{ 0x00, 0x00, 0x00, 0x02, 0xaa },
{ 0x00, 0x00, 0x00, 0x02, 0x55 },
};
static unsigned char outputs[][32] = {
{0xE4, 0x67, 0xF9, 0xA9, 0x55, 0x2B, 0xC7, 0xD3,
0x15, 0x5A, 0x62, 0x20, 0xAF, 0x9C, 0x19, 0x22,
0x0E, 0xEE, 0xD4, 0xFF, 0x78, 0xB0, 0xD1, 0xE6,
0xA1, 0x54, 0x49, 0x91, 0x46, 0x1A, 0x9E, 0x50,
},
{0x41, 0x2A, 0xEF, 0xC3, 0x62, 0xA7, 0x28, 0x5F,
0xC3, 0x96, 0x6C, 0x6A, 0x51, 0x81, 0xE7, 0x60,
0x5A, 0xE6, 0x75, 0x23, 0x5B, 0x6D, 0x54, 0x9F,
0xBF, 0xC9, 0xAB, 0x66, 0x30, 0xA4, 0xC6, 0x04,
},
{0xFA, 0x62, 0x4F, 0xA0, 0xE5, 0x23, 0x99, 0x3F,
0xA3, 0x88, 0xAE, 0xFD, 0xC6, 0x7E, 0x67, 0xEB,
0xCD, 0x8C, 0x08, 0xE8, 0xA0, 0x24, 0x6B, 0x1D,
0x73, 0xB0, 0xD1, 0xDD, 0x9F, 0xC5, 0x82, 0xB0,
},
};
static unsigned char iv[16] = { 0 };
unsigned char result[32] = { 0 };
for (i = 0; i < 3; i++) {
p = 0;
params[p++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_CIPHER, "CAMELLIA-256-CBC", 0);
params[p++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MAC, "CMAC", 0);
params[p++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MODE, "FEEDBACK", 0);
params[p++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_KEY, input_key, sizeof(input_key));
params[p++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_SALT, constants[i], sizeof(constants[i]));
params[p++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_SEED, iv, sizeof(iv));
params[p] = OSSL_PARAM_construct_end();
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result),
params), 0)
&& TEST_mem_eq(result, sizeof(result), outputs[i],
sizeof(outputs[i]));
EVP_KDF_CTX_free(kctx);
if (ret != 1)
return ret;
}
return ret;
}
#endif
static OSSL_PARAM *construct_kbkdf_params(char *digest, char *mac, unsigned char *key,
size_t keylen, char *salt, char *info)
{
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 7);
OSSL_PARAM *p = params;
if (params == NULL)
return NULL;
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_DIGEST, digest, 0);
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MAC, mac, 0);
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MODE, "COUNTER", 0);
*p++ = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_KEY, key, keylen);
*p++ = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_SALT, salt, strlen(salt));
*p++ = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_INFO, info, strlen(info));
*p = OSSL_PARAM_construct_end();
return params;
}
static int test_kdf_kbkdf_invalid_digest(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM *params;
static unsigned char key[] = {0x01};
params = construct_kbkdf_params("blah", "HMAC", key, 1, "prf", "test");
if (!TEST_ptr(params))
return 0;
/* Negative test case - set_params should fail */
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_false(EVP_KDF_CTX_set_params(kctx, params));
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_kbkdf_invalid_mac(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM *params;
static unsigned char key[] = {0x01};
params = construct_kbkdf_params("sha256", "blah", key, 1, "prf", "test");
if (!TEST_ptr(params))
return 0;
/* Negative test case - set_params should fail */
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_false(EVP_KDF_CTX_set_params(kctx, params));
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_kbkdf_empty_key(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM *params;
static unsigned char key[] = {0x01};
unsigned char result[32] = { 0 };
params = construct_kbkdf_params("sha256", "HMAC", key, 0, "prf", "test");
if (!TEST_ptr(params))
return 0;
/* Negative test case - derive should fail */
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
&& TEST_int_eq(EVP_KDF_derive(kctx, result, sizeof(result), NULL), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_kbkdf_1byte_key(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM *params;
static unsigned char key[] = {0x01};
unsigned char result[32] = { 0 };
params = construct_kbkdf_params("sha256", "HMAC", key, 1, "prf", "test");
if (!TEST_ptr(params))
return 0;
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result), params), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
static int test_kdf_kbkdf_zero_output_size(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM *params;
static unsigned char key[] = {0x01};
unsigned char result[32] = { 0 };
params = construct_kbkdf_params("sha256", "HMAC", key, 1, "prf", "test");
if (!TEST_ptr(params))
return 0;
/* Negative test case - derive should fail */
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
&& TEST_int_eq(EVP_KDF_derive(kctx, result, 0, NULL), 0);
EVP_KDF_CTX_free(kctx);
OPENSSL_free(params);
return ret;
}
/* Two test vectors from RFC 8009 (AES Encryption with HMAC-SHA2 for Kerberos
* 5) appendix A. */
static int test_kdf_kbkdf_8009_prf1(void)
{
int ret, i = 0;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[6];
char *label = "prf", *digest = "sha256", *prf_input = "test",
*mac = "HMAC";
static unsigned char input_key[] = {
0x37, 0x05, 0xD9, 0x60, 0x80, 0xC1, 0x77, 0x28,
0xA0, 0xE8, 0x00, 0xEA, 0xB6, 0xE0, 0xD2, 0x3C,
};
static unsigned char output[] = {
0x9D, 0x18, 0x86, 0x16, 0xF6, 0x38, 0x52, 0xFE,
0x86, 0x91, 0x5B, 0xB8, 0x40, 0xB4, 0xA8, 0x86,
0xFF, 0x3E, 0x6B, 0xB0, 0xF8, 0x19, 0xB4, 0x9B,
0x89, 0x33, 0x93, 0xD3, 0x93, 0x85, 0x42, 0x95,
};
unsigned char result[sizeof(output)] = { 0 };
params[i++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_DIGEST, digest, 0);
params[i++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MAC, mac, 0);
params[i++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_KEY, input_key, sizeof(input_key));
params[i++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_SALT, label, strlen(label));
params[i++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_INFO, prf_input, strlen(prf_input));
params[i] = OSSL_PARAM_construct_end();
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result), params), 0)
&& TEST_mem_eq(result, sizeof(result), output, sizeof(output));
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_kbkdf_8009_prf2(void)
{
int ret, i = 0;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[6];
char *label = "prf", *digest = "sha384", *prf_input = "test",
*mac = "HMAC";
static unsigned char input_key[] = {
0x6D, 0x40, 0x4D, 0x37, 0xFA, 0xF7, 0x9F, 0x9D,
0xF0, 0xD3, 0x35, 0x68, 0xD3, 0x20, 0x66, 0x98,
0x00, 0xEB, 0x48, 0x36, 0x47, 0x2E, 0xA8, 0xA0,
0x26, 0xD1, 0x6B, 0x71, 0x82, 0x46, 0x0C, 0x52,
};
static unsigned char output[] = {
0x98, 0x01, 0xF6, 0x9A, 0x36, 0x8C, 0x2B, 0xF6,
0x75, 0xE5, 0x95, 0x21, 0xE1, 0x77, 0xD9, 0xA0,
0x7F, 0x67, 0xEF, 0xE1, 0xCF, 0xDE, 0x8D, 0x3C,
0x8D, 0x6F, 0x6A, 0x02, 0x56, 0xE3, 0xB1, 0x7D,
0xB3, 0xC1, 0xB6, 0x2A, 0xD1, 0xB8, 0x55, 0x33,
0x60, 0xD1, 0x73, 0x67, 0xEB, 0x15, 0x14, 0xD2,
};
unsigned char result[sizeof(output)] = { 0 };
params[i++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_DIGEST, digest, 0);
params[i++] = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MAC, mac, 0);
params[i++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_KEY, input_key, sizeof(input_key));
params[i++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_SALT, label, strlen(label));
params[i++] = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_INFO, prf_input, strlen(prf_input));
params[i] = OSSL_PARAM_construct_end();
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result), params), 0)
&& TEST_mem_eq(result, sizeof(result), output, sizeof(output));
EVP_KDF_CTX_free(kctx);
return ret;
}
#if !defined(OPENSSL_NO_CMAC)
/*
* Test vector taken from
* https://csrc.nist.gov/CSRC/media/Projects/
* Cryptographic-Algorithm-Validation-Program/documents/KBKDF800-108/CounterMode.zip
* Note: Only 32 bit counter is supported ([RLEN=32_BITS])
*/
static int test_kdf_kbkdf_fixedinfo(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[8], *p = params;
static char *cipher = "AES128";
static char *mac = "CMAC";
static char *mode = "COUNTER";
int use_l = 0;
int use_separator = 0;
static unsigned char input_key[] = {
0xc1, 0x0b, 0x15, 0x2e, 0x8c, 0x97, 0xb7, 0x7e,
0x18, 0x70, 0x4e, 0x0f, 0x0b, 0xd3, 0x83, 0x05,
};
static unsigned char fixed_input[] = {
0x98, 0xcd, 0x4c, 0xbb, 0xbe, 0xbe, 0x15, 0xd1,
0x7d, 0xc8, 0x6e, 0x6d, 0xba, 0xd8, 0x00, 0xa2,
0xdc, 0xbd, 0x64, 0xf7, 0xc7, 0xad, 0x0e, 0x78,
0xe9, 0xcf, 0x94, 0xff, 0xdb, 0xa8, 0x9d, 0x03,
0xe9, 0x7e, 0xad, 0xf6, 0xc4, 0xf7, 0xb8, 0x06,
0xca, 0xf5, 0x2a, 0xa3, 0x8f, 0x09, 0xd0, 0xeb,
0x71, 0xd7, 0x1f, 0x49, 0x7b, 0xcc, 0x69, 0x06,
0xb4, 0x8d, 0x36, 0xc4,
};
static unsigned char output[] = {
0x26, 0xfa, 0xf6, 0x19, 0x08, 0xad, 0x9e, 0xe8,
0x81, 0xb8, 0x30, 0x5c, 0x22, 0x1d, 0xb5, 0x3f,
};
unsigned char result[sizeof(output)] = { 0 };
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER, cipher, 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC, mac, 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE, mode, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, input_key,
sizeof(input_key));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
fixed_input, sizeof(fixed_input));
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_KBKDF_USE_L, &use_l);
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR,
&use_separator);
*p = OSSL_PARAM_construct_end();
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
&& TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result), params), 0)
&& TEST_mem_eq(result, sizeof(result), output, sizeof(output));
EVP_KDF_CTX_free(kctx);
return ret;
}
#endif /* OPENSSL_NO_CMAC */
static int test_kdf_ss_hmac(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[6], *p = params;
unsigned char out[16];
static unsigned char z[] = {
0xb7,0x4a,0x14,0x9a,0x16,0x15,0x46,0xf8,0xc2,0x0b,0x06,0xac,0x4e,0xd4
};
static unsigned char other[] = {
0x34,0x8a,0x37,0xa2,0x7e,0xf1,0x28,0x2f,0x5f,0x02,0x0d,0xcc
};
static unsigned char salt[] = {
0x36,0x38,0x27,0x1c,0xcd,0x68,0xa2,0x5d,0xc2,0x4e,0xcd,0xdd,0x39,0xef,
0x3f,0x89
};
static const unsigned char expected[sizeof(out)] = {
0x44,0xf6,0x76,0xe8,0x5c,0x1b,0x1a,0x8b,0xbc,0x3d,0x31,0x92,0x18,0x63,
0x1c,0xa3
};
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
(char *)OSSL_MAC_NAME_HMAC, 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)"sha256", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, z, sizeof(z));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, other,
sizeof(other));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, salt,
sizeof(salt));
*p = OSSL_PARAM_construct_end();
ret =
TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_SSKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_ss_kmac(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[7], *p = params;
unsigned char out[64];
size_t mac_size = 20;
static unsigned char z[] = {
0xb7,0x4a,0x14,0x9a,0x16,0x15,0x46,0xf8,0xc2,0x0b,0x06,0xac,0x4e,0xd4
};
static unsigned char other[] = {
0x34,0x8a,0x37,0xa2,0x7e,0xf1,0x28,0x2f,0x5f,0x02,0x0d,0xcc
};
static unsigned char salt[] = {
0x36,0x38,0x27,0x1c,0xcd,0x68,0xa2,0x5d,0xc2,0x4e,0xcd,0xdd,0x39,0xef,
0x3f,0x89
};
static const unsigned char expected[sizeof(out)] = {
0xe9,0xc1,0x84,0x53,0xa0,0x62,0xb5,0x3b,0xdb,0xfc,0xbb,0x5a,0x34,0xbd,
0xb8,0xe5,0xe7,0x07,0xee,0xbb,0x5d,0xd1,0x34,0x42,0x43,0xd8,0xcf,0xc2,
0xc2,0xe6,0x33,0x2f,0x91,0xbd,0xa5,0x86,0xf3,0x7d,0xe4,0x8a,0x65,0xd4,
0xc5,0x14,0xfd,0xef,0xaa,0x1e,0x67,0x54,0xf3,0x73,0xd2,0x38,0xe1,0x95,
0xae,0x15,0x7e,0x1d,0xe8,0x14,0x98,0x03
};
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
(char *)OSSL_MAC_NAME_KMAC128, 0);
/* The digest parameter is not needed here and should be ignored */
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)"SHA256", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, z, sizeof(z));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, other,
sizeof(other));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, salt,
sizeof(salt));
*p++ = OSSL_PARAM_construct_size_t(OSSL_KDF_PARAM_MAC_SIZE, &mac_size);
*p = OSSL_PARAM_construct_end();
ret =
TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_SSKDF))
&& TEST_size_t_eq(EVP_KDF_CTX_get_kdf_size(kctx), 0)
&& TEST_int_eq(EVP_KDF_CTX_set_params(kctx, params), 1)
/* The bug fix for KMAC returning SIZE_MAX was added in 3.0.8 */
&& (fips_provider_version_lt(NULL, 3, 0, 8)
|| TEST_size_t_eq(EVP_KDF_CTX_get_kdf_size(kctx), SIZE_MAX))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_sshkdf(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[6], *p = params;
char kdftype = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
unsigned char out[8];
/* Test data from NIST CAVS 14.1 test vectors */
static unsigned char key[] = {
0x00, 0x00, 0x00, 0x81, 0x00, 0x87, 0x5c, 0x55, 0x1c, 0xef, 0x52, 0x6a,
0x4a, 0x8b, 0xe1, 0xa7, 0xdf, 0x27, 0xe9, 0xed, 0x35, 0x4b, 0xac, 0x9a,
0xfb, 0x71, 0xf5, 0x3d, 0xba, 0xe9, 0x05, 0x67, 0x9d, 0x14, 0xf9, 0xfa,
0xf2, 0x46, 0x9c, 0x53, 0x45, 0x7c, 0xf8, 0x0a, 0x36, 0x6b, 0xe2, 0x78,
0x96, 0x5b, 0xa6, 0x25, 0x52, 0x76, 0xca, 0x2d, 0x9f, 0x4a, 0x97, 0xd2,
0x71, 0xf7, 0x1e, 0x50, 0xd8, 0xa9, 0xec, 0x46, 0x25, 0x3a, 0x6a, 0x90,
0x6a, 0xc2, 0xc5, 0xe4, 0xf4, 0x8b, 0x27, 0xa6, 0x3c, 0xe0, 0x8d, 0x80,
0x39, 0x0a, 0x49, 0x2a, 0xa4, 0x3b, 0xad, 0x9d, 0x88, 0x2c, 0xca, 0xc2,
0x3d, 0xac, 0x88, 0xbc, 0xad, 0xa4, 0xb4, 0xd4, 0x26, 0xa3, 0x62, 0x08,
0x3d, 0xab, 0x65, 0x69, 0xc5, 0x4c, 0x22, 0x4d, 0xd2, 0xd8, 0x76, 0x43,
0xaa, 0x22, 0x76, 0x93, 0xe1, 0x41, 0xad, 0x16, 0x30, 0xce, 0x13, 0x14,
0x4e
};
static unsigned char xcghash[] = {
0x0e, 0x68, 0x3f, 0xc8, 0xa9, 0xed, 0x7c, 0x2f, 0xf0, 0x2d, 0xef, 0x23,
0xb2, 0x74, 0x5e, 0xbc, 0x99, 0xb2, 0x67, 0xda, 0xa8, 0x6a, 0x4a, 0xa7,
0x69, 0x72, 0x39, 0x08, 0x82, 0x53, 0xf6, 0x42
};
static unsigned char sessid[] = {
0x0e, 0x68, 0x3f, 0xc8, 0xa9, 0xed, 0x7c, 0x2f, 0xf0, 0x2d, 0xef, 0x23,
0xb2, 0x74, 0x5e, 0xbc, 0x99, 0xb2, 0x67, 0xda, 0xa8, 0x6a, 0x4a, 0xa7,
0x69, 0x72, 0x39, 0x08, 0x82, 0x53, 0xf6, 0x42
};
static const unsigned char expected[sizeof(out)] = {
0x41, 0xff, 0x2e, 0xad, 0x16, 0x83, 0xf1, 0xe6
};
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)"sha256", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, key,
sizeof(key));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH,
xcghash, sizeof(xcghash));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID,
sessid, sizeof(sessid));
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE,
&kdftype, sizeof(kdftype));
*p = OSSL_PARAM_construct_end();
ret =
TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_SSHKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdfs_same( EVP_KDF *kdf1, EVP_KDF *kdf2)
{
/* Fast path in case the two are the same algorithm pointer */
if (kdf1 == kdf2)
return 1;
/*
* Compare their names and providers instead.
* This is necessary in a non-caching build (or a cache flush during fetch)
* because without the algorithm in the cache, fetching it a second time
* will result in a different pointer.
*/
return TEST_ptr_eq(EVP_KDF_get0_provider(kdf1), EVP_KDF_get0_provider(kdf2))
&& TEST_str_eq(EVP_KDF_get0_name(kdf1), EVP_KDF_get0_name(kdf2));
}
static int test_kdf_get_kdf(void)
{
EVP_KDF *kdf1 = NULL, *kdf2 = NULL;
ASN1_OBJECT *obj;
int ok = 1;
if (!TEST_ptr(obj = OBJ_nid2obj(NID_id_pbkdf2))
|| !TEST_ptr(kdf1 = EVP_KDF_fetch(NULL, OSSL_KDF_NAME_PBKDF2, NULL))
|| !TEST_ptr(kdf2 = EVP_KDF_fetch(NULL, OBJ_nid2sn(OBJ_obj2nid(obj)),
NULL))
|| !test_kdfs_same(kdf1, kdf2))
ok = 0;
EVP_KDF_free(kdf1);
kdf1 = NULL;
EVP_KDF_free(kdf2);
kdf2 = NULL;
if (!TEST_ptr(kdf1 = EVP_KDF_fetch(NULL, SN_tls1_prf, NULL))
|| !TEST_ptr(kdf2 = EVP_KDF_fetch(NULL, LN_tls1_prf, NULL))
|| !test_kdfs_same(kdf1, kdf2))
ok = 0;
/* kdf1 is re-used below, so don't free it here */
EVP_KDF_free(kdf2);
kdf2 = NULL;
if (!TEST_ptr(kdf2 = EVP_KDF_fetch(NULL, OBJ_nid2sn(NID_tls1_prf), NULL))
|| !test_kdfs_same(kdf1, kdf2))
ok = 0;
EVP_KDF_free(kdf1);
kdf1 = NULL;
EVP_KDF_free(kdf2);
kdf2 = NULL;
return ok;
}
#if !defined(OPENSSL_NO_CMS) && !defined(OPENSSL_NO_DES)
static int test_kdf_x942_asn1(void)
{
int ret;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM params[4], *p = params;
const char *cek_alg = SN_id_smime_alg_CMS3DESwrap;
unsigned char out[24];
/* RFC2631 Section 2.1.6 Test data */
static unsigned char z[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,
0x0e,0x0f,0x10,0x11,0x12,0x13
};
static const unsigned char expected[sizeof(out)] = {
0xa0,0x96,0x61,0x39,0x23,0x76,0xf7,0x04,
0x4d,0x90,0x52,0xa3,0x97,0x88,0x32,0x46,
0xb6,0x7f,0x5f,0x1e,0xf6,0x3e,0xb5,0xfb
};
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)"sha1", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, z,
sizeof(z));
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CEK_ALG,
(char *)cek_alg, 0);
*p = OSSL_PARAM_construct_end();
ret =
TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_X942KDF_ASN1))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
return ret;
}
#endif /* OPENSSL_NO_CMS */
static int test_kdf_krb5kdf(void)
{
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[4], *p = params;
unsigned char out[16];
static unsigned char key[] = {
0x42, 0x26, 0x3C, 0x6E, 0x89, 0xF4, 0xFC, 0x28,
0xB8, 0xDF, 0x68, 0xEE, 0x09, 0x79, 0x9F, 0x15
};
static unsigned char constant[] = {
0x00, 0x00, 0x00, 0x02, 0x99
};
static const unsigned char expected[sizeof(out)] = {
0x34, 0x28, 0x0A, 0x38, 0x2B, 0xC9, 0x27, 0x69,
0xB2, 0xDA, 0x2F, 0x9E, 0xF0, 0x66, 0x85, 0x4B
};
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
(char *)"AES-128-CBC", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, key,
sizeof(key));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_CONSTANT,
constant, sizeof(constant));
*p = OSSL_PARAM_construct_end();
ret =
TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_KRB5KDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);
return ret;
}
int setup_tests(void)
{
ADD_TEST(test_kdf_pbkdf1);
ADD_TEST(test_kdf_pbkdf1_key_too_long);
#if !defined(OPENSSL_NO_CMAC) && !defined(OPENSSL_NO_CAMELLIA)
ADD_TEST(test_kdf_kbkdf_6803_128);
ADD_TEST(test_kdf_kbkdf_6803_256);
#endif
ADD_TEST(test_kdf_kbkdf_invalid_digest);
ADD_TEST(test_kdf_kbkdf_invalid_mac);
ADD_TEST(test_kdf_kbkdf_zero_output_size);
ADD_TEST(test_kdf_kbkdf_empty_key);
ADD_TEST(test_kdf_kbkdf_1byte_key);
ADD_TEST(test_kdf_kbkdf_8009_prf1);
ADD_TEST(test_kdf_kbkdf_8009_prf2);
#if !defined(OPENSSL_NO_CMAC)
ADD_TEST(test_kdf_kbkdf_fixedinfo);
#endif
ADD_TEST(test_kdf_get_kdf);
ADD_TEST(test_kdf_tls1_prf);
ADD_TEST(test_kdf_tls1_prf_invalid_digest);
ADD_TEST(test_kdf_tls1_prf_zero_output_size);
ADD_TEST(test_kdf_tls1_prf_empty_secret);
ADD_TEST(test_kdf_tls1_prf_1byte_secret);
ADD_TEST(test_kdf_tls1_prf_empty_seed);
ADD_TEST(test_kdf_tls1_prf_1byte_seed);
ADD_TEST(test_kdf_hkdf);
ADD_TEST(test_kdf_hkdf_invalid_digest);
ADD_TEST(test_kdf_hkdf_zero_output_size);
ADD_TEST(test_kdf_hkdf_empty_key);
ADD_TEST(test_kdf_hkdf_1byte_key);
ADD_TEST(test_kdf_hkdf_empty_salt);
ADD_TEST(test_kdf_hkdf_gettables);
ADD_TEST(test_kdf_hkdf_gettables_expandonly);
ADD_TEST(test_kdf_hkdf_gettables_no_digest);
ADD_TEST(test_kdf_hkdf_derive_set_params_fail);
ADD_TEST(test_kdf_hkdf_set_invalid_mode);
ADD_TEST(test_kdf_hkdf_set_ctx_param_fail);
ADD_TEST(test_kdf_pbkdf2);
ADD_TEST(test_kdf_pbkdf2_small_output);
ADD_TEST(test_kdf_pbkdf2_large_output);
ADD_TEST(test_kdf_pbkdf2_small_salt);
ADD_TEST(test_kdf_pbkdf2_small_iterations);
ADD_TEST(test_kdf_pbkdf2_small_salt_pkcs5);
ADD_TEST(test_kdf_pbkdf2_small_iterations_pkcs5);
ADD_TEST(test_kdf_pbkdf2_invalid_digest);
#ifndef OPENSSL_NO_SCRYPT
ADD_TEST(test_kdf_scrypt);
#endif
ADD_TEST(test_kdf_ss_hash);
ADD_TEST(test_kdf_ss_hmac);
ADD_TEST(test_kdf_ss_kmac);
ADD_TEST(test_kdf_sshkdf);
ADD_TEST(test_kdf_x963);
#if !defined(OPENSSL_NO_CMS) && !defined(OPENSSL_NO_DES)
ADD_TEST(test_kdf_x942_asn1);
#endif
ADD_TEST(test_kdf_krb5kdf);
return 1;
}
diff --git a/crypto/openssl/test/evp_libctx_test.c b/crypto/openssl/test/evp_libctx_test.c
index 2448c35a149f..fd114a118cb2 100644
--- a/crypto/openssl/test/evp_libctx_test.c
+++ b/crypto/openssl/test/evp_libctx_test.c
@@ -1,766 +1,784 @@
/*
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 tests are setup to load null into the default library context.
* Any tests are expected to use the created 'libctx' to find algorithms.
* The framework runs the tests twice using the 'default' provider or
* 'fips' provider as inputs.
*/
/*
* DSA/DH low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <assert.h>
#include <openssl/evp.h>
#include <openssl/provider.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
#include <openssl/safestack.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/x509.h>
#include <openssl/encoder.h>
#include "testutil.h"
#include "internal/nelem.h"
#include "crypto/bn_dh.h" /* _bignum_ffdhe2048_p */
static OSSL_LIB_CTX *libctx = NULL;
static OSSL_PROVIDER *nullprov = NULL;
static OSSL_PROVIDER *libprov = NULL;
static STACK_OF(OPENSSL_STRING) *cipher_names = NULL;
typedef enum OPTION_choice {
OPT_ERR = -1,
OPT_EOF = 0,
OPT_CONFIG_FILE,
OPT_PROVIDER_NAME,
OPT_TEST_ENUM
} OPTION_CHOICE;
const OPTIONS *test_get_options(void)
{
static const OPTIONS test_options[] = {
OPT_TEST_OPTIONS_DEFAULT_USAGE,
{ "config", OPT_CONFIG_FILE, '<',
"The configuration file to use for the libctx" },
{ "provider", OPT_PROVIDER_NAME, 's',
"The provider to load (The default value is 'default')" },
{ NULL }
};
return test_options;
}
#ifndef OPENSSL_NO_DH
static const char *getname(int id)
{
const char *name[] = {"p", "q", "g" };
if (id >= 0 && id < 3)
return name[id];
return "?";
}
#endif
/*
* We're using some DH specific values in this test, so we skip compilation if
* we're in a no-dh build.
*/
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DH)
static int test_dsa_param_keygen(int tstid)
{
int ret = 0;
int expected;
EVP_PKEY_CTX *gen_ctx = NULL;
EVP_PKEY *pkey_parm = NULL;
EVP_PKEY *pkey = NULL, *dup_pk = NULL;
DSA *dsa = NULL;
int pind, qind, gind;
BIGNUM *p = NULL, *q = NULL, *g = NULL;
/*
* Just grab some fixed dh p, q, g values for testing,
* these 'safe primes' should not be used normally for dsa *.
*/
static const BIGNUM *bn[] = {
&ossl_bignum_dh2048_256_p, &ossl_bignum_dh2048_256_q,
&ossl_bignum_dh2048_256_g
};
/*
* These tests are using bad values for p, q, g by reusing the values.
* A value of 0 uses p, 1 uses q and 2 uses g.
* There are 27 different combinations, with only the 1 valid combination.
*/
pind = tstid / 9;
qind = (tstid / 3) % 3;
gind = tstid % 3;
expected = (pind == 0 && qind == 1 && gind == 2);
TEST_note("Testing with (p, q, g) = (%s, %s, %s)\n", getname(pind),
getname(qind), getname(gind));
if (!TEST_ptr(pkey_parm = EVP_PKEY_new())
|| !TEST_ptr(dsa = DSA_new())
|| !TEST_ptr(p = BN_dup(bn[pind]))
|| !TEST_ptr(q = BN_dup(bn[qind]))
|| !TEST_ptr(g = BN_dup(bn[gind]))
|| !TEST_true(DSA_set0_pqg(dsa, p, q, g)))
goto err;
p = q = g = NULL;
if (!TEST_true(EVP_PKEY_assign_DSA(pkey_parm, dsa)))
goto err;
dsa = NULL;
if (!TEST_ptr(gen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey_parm, NULL))
|| !TEST_int_gt(EVP_PKEY_keygen_init(gen_ctx), 0)
|| !TEST_int_eq(EVP_PKEY_keygen(gen_ctx, &pkey), expected))
goto err;
if (expected) {
if (!TEST_ptr(dup_pk = EVP_PKEY_dup(pkey))
|| !TEST_int_eq(EVP_PKEY_eq(pkey, dup_pk), 1))
goto err;
}
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_free(dup_pk);
EVP_PKEY_CTX_free(gen_ctx);
EVP_PKEY_free(pkey_parm);
DSA_free(dsa);
BN_free(g);
BN_free(q);
BN_free(p);
return ret;
}
#endif /* OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_DH
static int do_dh_param_keygen(int tstid, const BIGNUM **bn)
{
int ret = 0;
int expected;
EVP_PKEY_CTX *gen_ctx = NULL;
EVP_PKEY *pkey_parm = NULL;
EVP_PKEY *pkey = NULL, *dup_pk = NULL;
DH *dh = NULL;
int pind, qind, gind;
BIGNUM *p = NULL, *q = NULL, *g = NULL;
/*
* These tests are using bad values for p, q, g by reusing the values.
* A value of 0 uses p, 1 uses q and 2 uses g.
* There are 27 different combinations, with only the 1 valid combination.
*/
pind = tstid / 9;
qind = (tstid / 3) % 3;
gind = tstid % 3;
expected = (pind == 0 && qind == 1 && gind == 2);
TEST_note("Testing with (p, q, g) = (%s, %s, %s)", getname(pind),
getname(qind), getname(gind));
if (!TEST_ptr(pkey_parm = EVP_PKEY_new())
|| !TEST_ptr(dh = DH_new())
|| !TEST_ptr(p = BN_dup(bn[pind]))
|| !TEST_ptr(q = BN_dup(bn[qind]))
|| !TEST_ptr(g = BN_dup(bn[gind]))
|| !TEST_true(DH_set0_pqg(dh, p, q, g)))
goto err;
p = q = g = NULL;
if (!TEST_true(EVP_PKEY_assign_DH(pkey_parm, dh)))
goto err;
dh = NULL;
if (!TEST_ptr(gen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey_parm, NULL))
|| !TEST_int_gt(EVP_PKEY_keygen_init(gen_ctx), 0)
|| !TEST_int_eq(EVP_PKEY_keygen(gen_ctx, &pkey), expected))
goto err;
if (expected) {
if (!TEST_ptr(dup_pk = EVP_PKEY_dup(pkey))
|| !TEST_int_eq(EVP_PKEY_eq(pkey, dup_pk), 1))
goto err;
}
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_free(dup_pk);
EVP_PKEY_CTX_free(gen_ctx);
EVP_PKEY_free(pkey_parm);
DH_free(dh);
BN_free(g);
BN_free(q);
BN_free(p);
return ret;
}
/*
* Note that we get the fips186-4 path being run for most of these cases since
* the internal code will detect that the p, q, g does not match a safe prime
* group (Except for when tstid = 5, which sets the correct p, q, g)
*/
static int test_dh_safeprime_param_keygen(int tstid)
{
static const BIGNUM *bn[] = {
&ossl_bignum_ffdhe2048_p, &ossl_bignum_ffdhe2048_q,
&ossl_bignum_const_2
};
return do_dh_param_keygen(tstid, bn);
}
static int dhx_cert_load(void)
{
int ret = 0;
X509 *cert = NULL;
BIO *bio = NULL;
static const unsigned char dhx_cert[] = {
0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
0xdb,0xf5,0x4d,0x22,0xa0,0x7a,0x67,0xa6,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x44,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
0x04,0x06,0x13,0x02,0x55,0x4b,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0a,0x0c,
0x0d,0x4f,0x70,0x65,0x6e,0x53,0x53,0x4c,0x20,0x47,0x72,0x6f,0x75,0x70,0x31,0x1d,
0x30,0x1b,0x06,0x03,0x55,0x04,0x03,0x0c,0x14,0x54,0x65,0x73,0x74,0x20,0x53,0x2f,
0x4d,0x49,0x4d,0x45,0x20,0x52,0x53,0x41,0x20,0x52,0x6f,0x6f,0x74,0x30,0x1e,0x17,
0x0d,0x31,0x33,0x30,0x38,0x30,0x32,0x31,0x34,0x34,0x39,0x32,0x39,0x5a,0x17,0x0d,
0x32,0x33,0x30,0x36,0x31,0x31,0x31,0x34,0x34,0x39,0x32,0x39,0x5a,0x30,0x44,0x31,
0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x4b,0x31,0x16,0x30,0x14,
0x06,0x03,0x55,0x04,0x0a,0x0c,0x0d,0x4f,0x70,0x65,0x6e,0x53,0x53,0x4c,0x20,0x47,
0x72,0x6f,0x75,0x70,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x03,0x0c,0x14,0x54,
0x65,0x73,0x74,0x20,0x53,0x2f,0x4d,0x49,0x4d,0x45,0x20,0x45,0x45,0x20,0x44,0x48,
0x20,0x23,0x31,0x30,0x82,0x01,0xb6,0x30,0x82,0x01,0x2b,0x06,0x07,0x2a,0x86,0x48,
0xce,0x3e,0x02,0x01,0x30,0x82,0x01,0x1e,0x02,0x81,0x81,0x00,0xd4,0x0c,0x4a,0x0c,
0x04,0x72,0x71,0x19,0xdf,0x59,0x19,0xc5,0xaf,0x44,0x7f,0xca,0x8e,0x2b,0xf0,0x09,
0xf5,0xd3,0x25,0xb1,0x73,0x16,0x55,0x89,0xdf,0xfd,0x07,0xaf,0x19,0xd3,0x7f,0xd0,
0x07,0xa2,0xfe,0x3f,0x5a,0xf1,0x01,0xc6,0xf8,0x2b,0xef,0x4e,0x6d,0x03,0x38,0x42,
0xa1,0x37,0xd4,0x14,0xb4,0x00,0x4a,0xb1,0x86,0x5a,0x83,0xce,0xb9,0x08,0x0e,0xc1,
0x99,0x27,0x47,0x8d,0x0b,0x85,0xa8,0x82,0xed,0xcc,0x0d,0xb9,0xb0,0x32,0x7e,0xdf,
0xe8,0xe4,0xf6,0xf6,0xec,0xb3,0xee,0x7a,0x11,0x34,0x65,0x97,0xfc,0x1a,0xb0,0x95,
0x4b,0x19,0xb9,0xa6,0x1c,0xd9,0x01,0x32,0xf7,0x35,0x7c,0x2d,0x5d,0xfe,0xc1,0x85,
0x70,0x49,0xf8,0xcc,0x99,0xd0,0xbe,0xf1,0x5a,0x78,0xc8,0x03,0x02,0x81,0x80,0x69,
0x00,0xfd,0x66,0xf2,0xfc,0x15,0x8b,0x09,0xb8,0xdc,0x4d,0xea,0xaa,0x79,0x55,0xf9,
0xdf,0x46,0xa6,0x2f,0xca,0x2d,0x8f,0x59,0x2a,0xad,0x44,0xa3,0xc6,0x18,0x2f,0x95,
0xb6,0x16,0x20,0xe3,0xd3,0xd1,0x8f,0x03,0xce,0x71,0x7c,0xef,0x3a,0xc7,0x44,0x39,
0x0e,0xe2,0x1f,0xd8,0xd3,0x89,0x2b,0xe7,0x51,0xdc,0x12,0x48,0x4c,0x18,0x4d,0x99,
0x12,0x06,0xe4,0x17,0x02,0x03,0x8c,0x24,0x05,0x8e,0xa6,0x85,0xf2,0x69,0x1b,0xe1,
0x6a,0xdc,0xe2,0x04,0x3a,0x01,0x9d,0x64,0xbe,0xfe,0x45,0xf9,0x44,0x18,0x71,0xbd,
0x2d,0x3e,0x7a,0x6f,0x72,0x7d,0x1a,0x80,0x42,0x57,0xae,0x18,0x6f,0x91,0xd6,0x61,
0x03,0x8a,0x1c,0x89,0x73,0xc7,0x56,0x41,0x03,0xd3,0xf8,0xed,0x65,0xe2,0x85,0x02,
0x15,0x00,0x89,0x94,0xab,0x10,0x67,0x45,0x41,0xad,0x63,0xc6,0x71,0x40,0x8d,0x6b,
0x9e,0x19,0x5b,0xa4,0xc7,0xf5,0x03,0x81,0x84,0x00,0x02,0x81,0x80,0x2f,0x5b,0xde,
0x72,0x02,0x36,0x6b,0x00,0x5e,0x24,0x7f,0x14,0x2c,0x18,0x52,0x42,0x97,0x4b,0xdb,
0x6e,0x15,0x50,0x3c,0x45,0x3e,0x25,0xf3,0xb7,0xc5,0x6e,0xe5,0x52,0xe7,0xc4,0xfb,
0xf4,0xa5,0xf0,0x39,0x12,0x7f,0xbc,0x54,0x1c,0x93,0xb9,0x5e,0xee,0xe9,0x14,0xb0,
0xdf,0xfe,0xfc,0x36,0xe4,0xf2,0xaf,0xfb,0x13,0xc8,0xdf,0x18,0x94,0x1d,0x40,0xb9,
0x71,0xdd,0x4c,0x9c,0xa7,0x03,0x52,0x02,0xb5,0xed,0x71,0x80,0x3e,0x23,0xda,0x28,
0xe5,0xab,0xe7,0x6f,0xf2,0x0a,0x0e,0x00,0x5b,0x7d,0xc6,0x4b,0xd7,0xc7,0xb2,0xc3,
0xba,0x62,0x7f,0x70,0x28,0xa0,0x9d,0x71,0x13,0x70,0xd1,0x9f,0x32,0x2f,0x3e,0xd2,
0xcd,0x1b,0xa4,0xc6,0x72,0xa0,0x74,0x5d,0x71,0xef,0x03,0x43,0x6e,0xa3,0x60,0x30,
0x5e,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,
0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xe0,0x30,
0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0x0b,0x5a,0x4d,0x5f,0x7d,0x25,
0xc7,0xf2,0x9d,0xc1,0xaa,0xb7,0x63,0x82,0x2f,0xfa,0x8f,0x32,0xe7,0xc0,0x30,0x1f,
0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xdf,0x7e,0x5e,0x88,0x05,
0x24,0x33,0x08,0xdd,0x22,0x81,0x02,0x97,0xcc,0x9a,0xb7,0xb1,0x33,0x27,0x30,0x30,
0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,
0x01,0x01,0x00,0x5a,0xf2,0x63,0xef,0xd3,0x16,0xd7,0xf5,0xaa,0xdd,0x12,0x00,0x36,
0x00,0x21,0xa2,0x7b,0x08,0xd6,0x3b,0x9f,0x62,0xac,0x53,0x1f,0xed,0x4c,0xd1,0x15,
0x34,0x65,0x71,0xee,0x96,0x07,0xa6,0xef,0xb2,0xde,0xd8,0xbb,0x35,0x6e,0x2c,0xe2,
0xd1,0x26,0xef,0x7e,0x94,0xe2,0x88,0x51,0xa4,0x6c,0xaa,0x27,0x2a,0xd3,0xb6,0xc2,
0xf7,0xea,0xc3,0x0b,0xa9,0xb5,0x28,0x37,0xa2,0x63,0x08,0xe4,0x88,0xc0,0x1b,0x16,
0x1b,0xca,0xfd,0x8a,0x07,0x32,0x29,0xa7,0x53,0xb5,0x2d,0x30,0xe4,0xf5,0x16,0xc3,
0xe3,0xc2,0x4c,0x30,0x5d,0x35,0x80,0x1c,0xa2,0xdb,0xe3,0x4b,0x51,0x0d,0x4c,0x60,
0x5f,0xb9,0x46,0xac,0xa8,0x46,0xa7,0x32,0xa7,0x9c,0x76,0xf8,0xe9,0xb5,0x19,0xe2,
0x0c,0xe1,0x0f,0xc6,0x46,0xe2,0x38,0xa7,0x87,0x72,0x6d,0x6c,0xbc,0x88,0x2f,0x9d,
0x2d,0xe5,0xd0,0x7d,0x1e,0xc7,0x5d,0xf8,0x7e,0xb4,0x0b,0xa6,0xf9,0x6c,0xe3,0x7c,
0xb2,0x70,0x6e,0x75,0x9b,0x1e,0x63,0xe1,0x4d,0xb2,0x81,0xd3,0x55,0x38,0x94,0x1a,
0x7a,0xfa,0xbf,0x01,0x18,0x70,0x2d,0x35,0xd3,0xe3,0x10,0x7a,0x9a,0xa7,0x8f,0xf3,
0xbd,0x56,0x55,0x5e,0xd8,0xbd,0x4e,0x16,0x76,0xd0,0x48,0x4c,0xf9,0x51,0x54,0xdf,
0x2d,0xb0,0xc9,0xaa,0x5e,0x42,0x38,0x50,0xbf,0x0f,0xc0,0xd9,0x84,0x44,0x4b,0x42,
0x24,0xec,0x14,0xa3,0xde,0x11,0xdf,0x58,0x7f,0xc2,0x4d,0xb2,0xd5,0x42,0x78,0x6e,
0x52,0x3e,0xad,0xc3,0x5f,0x04,0xc4,0xe6,0x31,0xaa,0x81,0x06,0x8b,0x13,0x4b,0x3c,
0x0e,0x6a,0xb1
};
if (!TEST_ptr(bio = BIO_new_mem_buf(dhx_cert, sizeof(dhx_cert)))
|| !TEST_ptr(cert = X509_new_ex(libctx, NULL))
|| !TEST_ptr(d2i_X509_bio(bio, &cert)))
goto err;
ret = 1;
err:
X509_free(cert);
BIO_free(bio);
return ret;
}
#endif /* OPENSSL_NO_DH */
static int test_cipher_reinit(int test_id)
{
int ret = 0, diff, ccm, siv, no_null_key;
int out1_len = 0, out2_len = 0, out3_len = 0;
EVP_CIPHER *cipher = NULL;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char out1[256];
unsigned char out2[256];
unsigned char out3[256];
unsigned char in[16] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
};
unsigned char key[64] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x03, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
};
unsigned char iv[16] = {
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
};
const char *name = sk_OPENSSL_STRING_value(cipher_names, test_id);
if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()))
goto err;
TEST_note("Fetching %s\n", name);
if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, name, NULL)))
goto err;
/* ccm fails on the second update - this matches OpenSSL 1_1_1 behaviour */
ccm = (EVP_CIPHER_get_mode(cipher) == EVP_CIPH_CCM_MODE);
/* siv cannot be called with NULL key as the iv is irrelevant */
siv = (EVP_CIPHER_get_mode(cipher) == EVP_CIPH_SIV_MODE);
/*
* Skip init call with a null key for RC4 as the stream cipher does not
* handle reinit (1.1.1 behaviour).
*/
no_null_key = EVP_CIPHER_is_a(cipher, "RC4")
|| EVP_CIPHER_is_a(cipher, "RC4-40")
|| EVP_CIPHER_is_a(cipher, "RC4-HMAC-MD5");
/* DES3-WRAP uses random every update - so it will give a different value */
diff = EVP_CIPHER_is_a(cipher, "DES3-WRAP");
if (!TEST_true(EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv))
|| !TEST_true(EVP_EncryptUpdate(ctx, out1, &out1_len, in, sizeof(in)))
|| !TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
|| !TEST_int_eq(EVP_EncryptUpdate(ctx, out2, &out2_len, in, sizeof(in)),
ccm ? 0 : 1)
|| (!no_null_key
&& (!TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
|| !TEST_int_eq(EVP_EncryptUpdate(ctx, out3, &out3_len, in, sizeof(in)),
ccm || siv ? 0 : 1))))
goto err;
if (ccm == 0) {
if (diff) {
if (!TEST_mem_ne(out1, out1_len, out2, out2_len)
|| !TEST_mem_ne(out1, out1_len, out3, out3_len)
|| !TEST_mem_ne(out2, out2_len, out3, out3_len))
goto err;
} else {
if (!TEST_mem_eq(out1, out1_len, out2, out2_len)
|| (!siv && !no_null_key && !TEST_mem_eq(out1, out1_len, out3, out3_len)))
goto err;
}
}
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
/*
* This test only uses a partial block (half the block size) of input for each
* EVP_EncryptUpdate() in order to test that the second init/update is not using
* a leftover buffer from the first init/update.
* Note: some ciphers don't need a full block to produce output.
*/
static int test_cipher_reinit_partialupdate(int test_id)
{
int ret = 0, in_len;
int out1_len = 0, out2_len = 0, out3_len = 0;
EVP_CIPHER *cipher = NULL;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char out1[256];
unsigned char out2[256];
unsigned char out3[256];
static const unsigned char in[32] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0xba, 0xbe, 0xba, 0xbe, 0x00, 0x00, 0xba, 0xbe,
0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
};
static const unsigned char key[64] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x03, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
};
static const unsigned char iv[16] = {
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
};
const char *name = sk_OPENSSL_STRING_value(cipher_names, test_id);
if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()))
goto err;
TEST_note("Fetching %s\n", name);
if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, name, NULL)))
goto err;
in_len = EVP_CIPHER_get_block_size(cipher) / 2;
/* skip any ciphers that don't allow partial updates */
if (((EVP_CIPHER_get_flags(cipher)
& (EVP_CIPH_FLAG_CTS | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) != 0)
|| EVP_CIPHER_get_mode(cipher) == EVP_CIPH_CCM_MODE
|| EVP_CIPHER_get_mode(cipher) == EVP_CIPH_XTS_MODE
|| EVP_CIPHER_get_mode(cipher) == EVP_CIPH_WRAP_MODE) {
ret = 1;
goto err;
}
if (!TEST_true(EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv))
|| !TEST_true(EVP_EncryptUpdate(ctx, out1, &out1_len, in, in_len))
|| !TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
|| !TEST_true(EVP_EncryptUpdate(ctx, out2, &out2_len, in, in_len)))
goto err;
if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
goto err;
if (EVP_CIPHER_get_mode(cipher) != EVP_CIPH_SIV_MODE) {
if (!TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
|| !TEST_true(EVP_EncryptUpdate(ctx, out3, &out3_len, in, in_len)))
goto err;
if (!TEST_mem_eq(out1, out1_len, out3, out3_len))
goto err;
}
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
static int name_cmp(const char * const *a, const char * const *b)
{
return OPENSSL_strcasecmp(*a, *b);
}
static void collect_cipher_names(EVP_CIPHER *cipher, void *cipher_names_list)
{
STACK_OF(OPENSSL_STRING) *names = cipher_names_list;
const char *name = EVP_CIPHER_get0_name(cipher);
char *namedup = NULL;
assert(name != NULL);
/* the cipher will be freed after returning, strdup is needed */
if ((namedup = OPENSSL_strdup(name)) != NULL
&& !sk_OPENSSL_STRING_push(names, namedup))
OPENSSL_free(namedup);
}
static int rsa_keygen(int bits, EVP_PKEY **pub, EVP_PKEY **priv)
{
int ret = 0;
unsigned char *pub_der = NULL;
const unsigned char *pp = NULL;
size_t len = 0;
OSSL_ENCODER_CTX *ectx = NULL;
- if (!TEST_ptr(*priv = EVP_PKEY_Q_keygen(libctx, NULL, "RSA", bits))
+ if (!TEST_ptr(*priv = EVP_PKEY_Q_keygen(libctx, NULL, "RSA", (size_t)bits))
|| !TEST_ptr(ectx =
OSSL_ENCODER_CTX_new_for_pkey(*priv,
EVP_PKEY_PUBLIC_KEY,
"DER", "type-specific",
NULL))
|| !TEST_true(OSSL_ENCODER_to_data(ectx, &pub_der, &len)))
goto err;
pp = pub_der;
if (!TEST_ptr(d2i_PublicKey(EVP_PKEY_RSA, pub, &pp, len)))
goto err;
ret = 1;
err:
OSSL_ENCODER_CTX_free(ectx);
OPENSSL_free(pub_der);
return ret;
}
static int kem_rsa_gen_recover(void)
{
int ret = 0;
EVP_PKEY *pub = NULL;
EVP_PKEY *priv = NULL;
EVP_PKEY_CTX *sctx = NULL, *rctx = NULL, *dctx = NULL;
unsigned char secret[256] = { 0, };
unsigned char ct[256] = { 0, };
unsigned char unwrap[256] = { 0, };
size_t ctlen = 0, unwraplen = 0, secretlen = 0;
int bits = 2048;
ret = TEST_true(rsa_keygen(bits, &pub, &priv))
&& TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pub, NULL))
&& TEST_int_eq(EVP_PKEY_encapsulate_init(sctx, NULL), 1)
&& TEST_int_eq(EVP_PKEY_CTX_set_kem_op(sctx, "RSASVE"), 1)
&& TEST_ptr(dctx = EVP_PKEY_CTX_dup(sctx))
+ /* Test that providing a NULL wrappedlen fails */
+ && TEST_int_eq(EVP_PKEY_encapsulate(dctx, NULL, NULL, NULL, NULL), 0)
&& TEST_int_eq(EVP_PKEY_encapsulate(dctx, NULL, &ctlen, NULL,
&secretlen), 1)
&& TEST_int_eq(ctlen, secretlen)
&& TEST_int_eq(ctlen, bits / 8)
&& TEST_int_eq(EVP_PKEY_encapsulate(dctx, ct, &ctlen, secret,
&secretlen), 1)
&& TEST_ptr(rctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL))
&& TEST_int_eq(EVP_PKEY_decapsulate_init(rctx, NULL), 1)
&& TEST_int_eq(EVP_PKEY_CTX_set_kem_op(rctx, "RSASVE"), 1)
+ /* Test that providing a NULL unwrappedlen fails */
+ && TEST_int_eq(EVP_PKEY_decapsulate(rctx, NULL, NULL, ct, ctlen), 0)
&& TEST_int_eq(EVP_PKEY_decapsulate(rctx, NULL, &unwraplen,
ct, ctlen), 1)
&& TEST_int_eq(EVP_PKEY_decapsulate(rctx, unwrap, &unwraplen,
ct, ctlen), 1)
&& TEST_mem_eq(unwrap, unwraplen, secret, secretlen);
+
+ /* Test that providing a too short unwrapped/ctlen fails */
+ if (fips_provider_version_match(libctx, ">=3.4.0")) {
+ ctlen = 1;
+ if (!TEST_int_eq(EVP_PKEY_encapsulate(dctx, ct, &ctlen, secret,
+ &secretlen), 0))
+ ret = 0;
+ unwraplen = 1;
+ if (!TEST_int_eq(EVP_PKEY_decapsulate(rctx, unwrap, &unwraplen, ct,
+ ctlen), 0))
+ ret = 0;
+ }
+
EVP_PKEY_free(pub);
EVP_PKEY_free(priv);
EVP_PKEY_CTX_free(rctx);
EVP_PKEY_CTX_free(dctx);
EVP_PKEY_CTX_free(sctx);
return ret;
}
#ifndef OPENSSL_NO_DES
/*
* This test makes sure that EVP_CIPHER_CTX_rand_key() works correctly
* For fips mode this code would produce an error if the flag is not set.
*/
static int test_cipher_tdes_randkey(void)
{
int ret;
EVP_CIPHER_CTX *ctx = NULL;
EVP_CIPHER *tdes_cipher = NULL, *aes_cipher = NULL;
unsigned char key[24] = { 0 };
ret = TEST_ptr(aes_cipher = EVP_CIPHER_fetch(libctx, "AES-256-CBC", NULL))
&& TEST_int_eq(EVP_CIPHER_get_flags(aes_cipher) & EVP_CIPH_RAND_KEY, 0)
&& TEST_ptr(tdes_cipher = EVP_CIPHER_fetch(libctx, "DES-EDE3-CBC", NULL))
&& TEST_int_ne(EVP_CIPHER_get_flags(tdes_cipher) & EVP_CIPH_RAND_KEY, 0)
&& TEST_ptr(ctx = EVP_CIPHER_CTX_new())
&& TEST_true(EVP_CipherInit_ex(ctx, tdes_cipher, NULL, NULL, NULL, 1))
&& TEST_int_gt(EVP_CIPHER_CTX_rand_key(ctx, key), 0);
EVP_CIPHER_CTX_free(ctx);
EVP_CIPHER_free(tdes_cipher);
EVP_CIPHER_free(aes_cipher);
return ret;
}
#endif /* OPENSSL_NO_DES */
static int kem_rsa_params(void)
{
int ret = 0;
EVP_PKEY *pub = NULL;
EVP_PKEY *priv = NULL;
EVP_PKEY_CTX *pubctx = NULL, *privctx = NULL;
unsigned char secret[256] = { 0, };
unsigned char ct[256] = { 0, };
size_t ctlen = 0, secretlen = 0;
ret = TEST_true(rsa_keygen(2048, &pub, &priv))
- && TEST_ptr(pubctx = EVP_PKEY_CTX_new_from_pkey(libctx, pub, NULL))
- && TEST_ptr(privctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL))
- /* Test setting kem op before the init fails */
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, "RSASVE"), -2)
- /* Test NULL ctx passed */
- && TEST_int_eq(EVP_PKEY_encapsulate_init(NULL, NULL), 0)
- && TEST_int_eq(EVP_PKEY_encapsulate(NULL, NULL, NULL, NULL, NULL), 0)
- && TEST_int_eq(EVP_PKEY_decapsulate_init(NULL, NULL), 0)
- && TEST_int_eq(EVP_PKEY_decapsulate(NULL, NULL, NULL, NULL, 0), 0)
- /* Test Invalid operation */
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, NULL, NULL, NULL), -1)
- && TEST_int_eq(EVP_PKEY_decapsulate(privctx, NULL, NULL, NULL, 0), 0)
- /* Wrong key component - no secret should be returned on failure */
- && TEST_int_eq(EVP_PKEY_decapsulate_init(pubctx, NULL), 1)
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, "RSASVE"), 1)
- && TEST_int_eq(EVP_PKEY_decapsulate(pubctx, secret, &secretlen, ct,
- sizeof(ct)), 0)
- && TEST_uchar_eq(secret[0], 0)
- /* Test encapsulate fails if the mode is not set */
- && TEST_int_eq(EVP_PKEY_encapsulate_init(pubctx, NULL), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, &ctlen, secret, &secretlen), -2)
- /* Test setting a bad kem ops fail */
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, "RSA"), 0)
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, NULL), 0)
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(NULL, "RSASVE"), 0)
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(NULL, NULL), 0)
- /* Test secretlen is optional */
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, "RSASVE"), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, &ctlen, secret, NULL), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, &ctlen, NULL, NULL), 1)
- /* Test outlen is optional */
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, NULL, NULL, &secretlen), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, NULL, secret, &secretlen), 1)
- /* test that either len must be set if out is NULL */
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, NULL, NULL, NULL), 0)
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, &ctlen, NULL, NULL), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, NULL, NULL, &secretlen), 1)
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, &ctlen, NULL, &secretlen), 1)
- /* Secret buffer should be set if there is an output buffer */
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, &ctlen, NULL, NULL), 0)
- /* Test that lengths are optional if ct is not NULL */
- && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, NULL, secret, NULL), 1)
- /* Pass if secret or secret length are not NULL */
- && TEST_int_eq(EVP_PKEY_decapsulate_init(privctx, NULL), 1)
- && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(privctx, "RSASVE"), 1)
- && TEST_int_eq(EVP_PKEY_decapsulate(privctx, secret, NULL, ct, sizeof(ct)), 1)
- && TEST_int_eq(EVP_PKEY_decapsulate(privctx, NULL, &secretlen, ct, sizeof(ct)), 1)
- && TEST_int_eq(secretlen, 256)
- /* Fail if passed NULL arguments */
- && TEST_int_eq(EVP_PKEY_decapsulate(privctx, NULL, NULL, ct, sizeof(ct)), 0)
- && TEST_int_eq(EVP_PKEY_decapsulate(privctx, secret, &secretlen, NULL, 0), 0)
- && TEST_int_eq(EVP_PKEY_decapsulate(privctx, secret, &secretlen, NULL, sizeof(ct)), 0)
- && TEST_int_eq(EVP_PKEY_decapsulate(privctx, secret, &secretlen, ct, 0), 0);
+ && TEST_ptr(pubctx = EVP_PKEY_CTX_new_from_pkey(libctx, pub, NULL))
+ && TEST_ptr(privctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL))
+ /* Test setting kem op before the init fails */
+ && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, "RSASVE"), -2)
+ /* Test NULL ctx passed */
+ && TEST_int_eq(EVP_PKEY_encapsulate_init(NULL, NULL), 0)
+ && TEST_int_eq(EVP_PKEY_encapsulate(NULL, NULL, NULL, NULL, NULL), 0)
+ && TEST_int_eq(EVP_PKEY_decapsulate_init(NULL, NULL), 0)
+ && TEST_int_eq(EVP_PKEY_decapsulate(NULL, NULL, NULL, NULL, 0), 0)
+ /* Test Invalid operation */
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, NULL, NULL, NULL), -1)
+ && TEST_int_eq(EVP_PKEY_decapsulate(privctx, NULL, NULL, NULL, 0), 0)
+ /* Wrong key component - no secret should be returned on failure */
+ && TEST_int_eq(EVP_PKEY_decapsulate_init(pubctx, NULL), 1)
+ && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, "RSASVE"), 1)
+ && TEST_int_eq(EVP_PKEY_decapsulate(pubctx, secret, &secretlen, ct,
+ sizeof(ct)), 0)
+ && TEST_uchar_eq(secret[0], 0)
+ /* Test encapsulate fails if the mode is not set */
+ && TEST_int_eq(EVP_PKEY_encapsulate_init(pubctx, NULL), 1)
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, &ctlen, secret, &secretlen), -2)
+ /* Test setting a bad kem ops fail */
+ && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, "RSA"), 0)
+ && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, NULL), 0)
+ && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(NULL, "RSASVE"), 0)
+ && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(NULL, NULL), 0)
+ /* Test secretlen is optional */
+ && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(pubctx, "RSASVE"), 1)
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, &ctlen, NULL, NULL), 1)
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, &ctlen, secret, NULL), 1)
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, &ctlen, NULL, NULL), 1)
+ /* Test outlen is optional */
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, NULL, NULL, &secretlen), 1)
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, NULL, secret, &secretlen), 1)
+ /* test that either len must be set if out is NULL */
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, NULL, NULL, NULL), 0)
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, &ctlen, NULL, NULL), 1)
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, NULL, NULL, &secretlen), 1)
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, NULL, &ctlen, NULL, &secretlen), 1)
+ /* Secret buffer should be set if there is an output buffer */
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, &ctlen, NULL, NULL), 0)
+ /* Test that lengths are optional if ct is not NULL */
+ && TEST_int_eq(EVP_PKEY_encapsulate(pubctx, ct, NULL, secret, NULL), 1)
+ /* Pass if secret or secret length are not NULL */
+ && TEST_int_eq(EVP_PKEY_decapsulate_init(privctx, NULL), 1)
+ && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(privctx, "RSASVE"), 1)
+ && TEST_int_eq(EVP_PKEY_decapsulate(privctx, secret, NULL, ct, sizeof(ct)), 1)
+ && TEST_int_eq(EVP_PKEY_decapsulate(privctx, NULL, &secretlen, ct, sizeof(ct)), 1)
+ && TEST_int_eq(secretlen, 256)
+ /* Fail if passed NULL arguments */
+ && TEST_int_eq(EVP_PKEY_decapsulate(privctx, NULL, NULL, ct, sizeof(ct)), 0)
+ && TEST_int_eq(EVP_PKEY_decapsulate(privctx, secret, &secretlen, NULL, 0), 0)
+ && TEST_int_eq(EVP_PKEY_decapsulate(privctx, secret, &secretlen, NULL, sizeof(ct)), 0)
+ && TEST_int_eq(EVP_PKEY_decapsulate(privctx, secret, &secretlen, ct, 0), 0);
EVP_PKEY_free(pub);
EVP_PKEY_free(priv);
EVP_PKEY_CTX_free(pubctx);
EVP_PKEY_CTX_free(privctx);
return ret;
}
#ifndef OPENSSL_NO_DH
static EVP_PKEY *gen_dh_key(void)
{
EVP_PKEY_CTX *gctx = NULL;
EVP_PKEY *pkey = NULL;
OSSL_PARAM params[2];
params[0] = OSSL_PARAM_construct_utf8_string("group", "ffdhe2048", 0);
params[1] = OSSL_PARAM_construct_end();
if (!TEST_ptr(gctx = EVP_PKEY_CTX_new_from_name(libctx, "DH", NULL))
|| !TEST_int_gt(EVP_PKEY_keygen_init(gctx), 0)
|| !TEST_true(EVP_PKEY_CTX_set_params(gctx, params))
|| !TEST_true(EVP_PKEY_keygen(gctx, &pkey)))
goto err;
err:
EVP_PKEY_CTX_free(gctx);
return pkey;
}
/* Fail if we try to use a dh key */
static int kem_invalid_keytype(void)
{
int ret = 0;
EVP_PKEY *key = NULL;
EVP_PKEY_CTX *sctx = NULL;
if (!TEST_ptr(key = gen_dh_key()))
goto done;
if (!TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL)))
goto done;
if (!TEST_int_eq(EVP_PKEY_encapsulate_init(sctx, NULL), -2))
goto done;
ret = 1;
done:
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(sctx);
return ret;
}
#endif /* OPENSSL_NO_DH */
int setup_tests(void)
{
const char *prov_name = "default";
char *config_file = NULL;
OPTION_CHOICE o;
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_PROVIDER_NAME:
prov_name = opt_arg();
break;
case OPT_CONFIG_FILE:
config_file = opt_arg();
break;
case OPT_TEST_CASES:
break;
default:
case OPT_ERR:
return 0;
}
}
if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
return 0;
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DH)
ADD_ALL_TESTS(test_dsa_param_keygen, 3 * 3 * 3);
#endif
#ifndef OPENSSL_NO_DH
ADD_ALL_TESTS(test_dh_safeprime_param_keygen, 3 * 3 * 3);
ADD_TEST(dhx_cert_load);
#endif
if (!TEST_ptr(cipher_names = sk_OPENSSL_STRING_new(name_cmp)))
return 0;
EVP_CIPHER_do_all_provided(libctx, collect_cipher_names, cipher_names);
ADD_ALL_TESTS(test_cipher_reinit, sk_OPENSSL_STRING_num(cipher_names));
ADD_ALL_TESTS(test_cipher_reinit_partialupdate,
sk_OPENSSL_STRING_num(cipher_names));
ADD_TEST(kem_rsa_gen_recover);
ADD_TEST(kem_rsa_params);
#ifndef OPENSSL_NO_DH
ADD_TEST(kem_invalid_keytype);
#endif
#ifndef OPENSSL_NO_DES
ADD_TEST(test_cipher_tdes_randkey);
#endif
return 1;
}
/* Because OPENSSL_free is a macro, it can't be passed as a function pointer */
static void string_free(char *m)
{
OPENSSL_free(m);
}
void cleanup_tests(void)
{
sk_OPENSSL_STRING_pop_free(cipher_names, string_free);
OSSL_PROVIDER_unload(libprov);
OSSL_LIB_CTX_free(libctx);
OSSL_PROVIDER_unload(nullprov);
}
diff --git a/crypto/openssl/test/hmactest.c b/crypto/openssl/test/hmactest.c
index 8f5bf32f8708..0a29c58731f6 100644
--- a/crypto/openssl/test/hmactest.c
+++ b/crypto/openssl/test/hmactest.c
@@ -1,302 +1,304 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* HMAC low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "internal/nelem.h"
# include <openssl/hmac.h>
# include <openssl/sha.h>
# ifndef OPENSSL_NO_MD5
# include <openssl/md5.h>
# endif
# ifdef CHARSET_EBCDIC
# include <openssl/ebcdic.h>
# endif
#include "testutil.h"
# ifndef OPENSSL_NO_MD5
static struct test_st {
const char key[16];
int key_len;
const unsigned char data[64];
int data_len;
const char *digest;
} test[8] = {
{
"", 0, "More text test vectors to stuff up EBCDIC machines :-)", 54,
"e9139d1e6ee064ef8cf514fc7dc83e86",
},
{
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
16, "Hi There", 8,
"9294727a3638bb1c13f48ef8158bfc9d",
},
{
"Jefe", 4, "what do ya want for nothing?", 28,
"750c783e6ab0b503eaa86e310a5db738",
},
{
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
16, {
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd
}, 50, "56be34521d144c88dbb8c733f0e8b3f6",
},
{
"", 0, "My test data", 12,
"61afdecb95429ef494d61fdee15990cabf0826fc"
},
{
"", 0, "My test data", 12,
"2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776"
},
{
"123456", 6, "My test data", 12,
"bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd"
},
{
"12345", 5, "My test data again", 18,
"a12396ceddd2a85f4c656bc1e0aa50c78cffde3e"
}
};
# endif
static char *pt(unsigned char *md, unsigned int len);
# ifndef OPENSSL_NO_MD5
static int test_hmac_md5(int idx)
{
char *p;
# ifdef CHARSET_EBCDIC
ebcdic2ascii(test[0].data, test[0].data, test[0].data_len);
ebcdic2ascii(test[1].data, test[1].data, test[1].data_len);
ebcdic2ascii(test[2].key, test[2].key, test[2].key_len);
ebcdic2ascii(test[2].data, test[2].data, test[2].data_len);
# endif
p = pt(HMAC(EVP_md5(),
test[idx].key, test[idx].key_len,
test[idx].data, test[idx].data_len, NULL, NULL),
MD5_DIGEST_LENGTH);
return TEST_ptr(p) && TEST_str_eq(p, test[idx].digest);
}
# endif
static int test_hmac_bad(void)
{
HMAC_CTX *ctx = NULL;
int ret = 0;
ctx = HMAC_CTX_new();
if (!TEST_ptr(ctx)
|| !TEST_ptr_null(HMAC_CTX_get_md(ctx))
|| !TEST_false(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL))
|| !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len))
|| !TEST_false(HMAC_Init_ex(ctx, NULL, 0, EVP_sha1(), NULL))
|| !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len)))
goto err;
ret = 1;
err:
HMAC_CTX_free(ctx);
return ret;
}
static int test_hmac_run(void)
{
char *p;
HMAC_CTX *ctx = NULL;
unsigned char buf[EVP_MAX_MD_SIZE];
unsigned int len;
int ret = 0;
if (!TEST_ptr(ctx = HMAC_CTX_new()))
return 0;
HMAC_CTX_reset(ctx);
if (!TEST_ptr(ctx)
|| !TEST_ptr_null(HMAC_CTX_get_md(ctx))
|| !TEST_false(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL))
|| !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len))
|| !TEST_false(HMAC_Init_ex(ctx, test[4].key, -1, EVP_sha1(), NULL)))
goto err;
if (!TEST_true(HMAC_Init_ex(ctx, test[4].key, test[4].key_len, EVP_sha1(), NULL))
|| !TEST_true(HMAC_Update(ctx, test[4].data, test[4].data_len))
|| !TEST_true(HMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_ptr(p) || !TEST_str_eq(p, test[4].digest))
goto err;
if (!TEST_false(HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL)))
goto err;
if (!TEST_true(HMAC_Init_ex(ctx, test[5].key, test[5].key_len, EVP_sha256(), NULL))
|| !TEST_ptr_eq(HMAC_CTX_get_md(ctx), EVP_sha256())
|| !TEST_true(HMAC_Update(ctx, test[5].data, test[5].data_len))
|| !TEST_true(HMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_ptr(p) || !TEST_str_eq(p, test[5].digest))
goto err;
if (!TEST_true(HMAC_Init_ex(ctx, test[6].key, test[6].key_len, NULL, NULL))
|| !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len))
|| !TEST_true(HMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest))
goto err;
/* Test reusing a key */
if (!TEST_true(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL))
|| !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len))
|| !TEST_true(HMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest))
goto err;
/*
* Test reusing a key where the digest is provided again but is the same as
* last time
*/
if (!TEST_true(HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL))
|| !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len))
|| !TEST_true(HMAC_Final(ctx, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest))
goto err;
ret = 1;
err:
HMAC_CTX_free(ctx);
return ret;
}
static int test_hmac_single_shot(void)
{
char *p;
/* Test single-shot with NULL key. */
p = pt(HMAC(EVP_sha1(), NULL, 0, test[4].data, test[4].data_len,
NULL, NULL), SHA_DIGEST_LENGTH);
if (!TEST_ptr(p) || !TEST_str_eq(p, test[4].digest))
return 0;
return 1;
}
static int test_hmac_copy(void)
{
char *p;
HMAC_CTX *ctx = NULL, *ctx2 = NULL;
unsigned char buf[EVP_MAX_MD_SIZE];
unsigned int len;
int ret = 0;
ctx = HMAC_CTX_new();
ctx2 = HMAC_CTX_new();
if (!TEST_ptr(ctx) || !TEST_ptr(ctx2))
goto err;
if (!TEST_true(HMAC_Init_ex(ctx, test[7].key, test[7].key_len, EVP_sha1(), NULL))
|| !TEST_true(HMAC_Update(ctx, test[7].data, test[7].data_len))
|| !TEST_true(HMAC_CTX_copy(ctx2, ctx))
|| !TEST_true(HMAC_Final(ctx2, buf, &len)))
goto err;
p = pt(buf, len);
if (!TEST_ptr(p) || !TEST_str_eq(p, test[7].digest))
goto err;
ret = 1;
err:
HMAC_CTX_free(ctx2);
HMAC_CTX_free(ctx);
return ret;
}
static int test_hmac_copy_uninited(void)
{
const unsigned char key[24] = {0};
const unsigned char ct[166] = {0};
EVP_PKEY *pkey = NULL;
EVP_MD_CTX *ctx = NULL;
EVP_MD_CTX *ctx_tmp = NULL;
int res = 0;
if (!TEST_ptr(ctx = EVP_MD_CTX_new())
|| !TEST_ptr(pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
key, sizeof(key)))
|| !TEST_true(EVP_DigestSignInit(ctx, NULL, EVP_sha1(), NULL, pkey))
|| !TEST_ptr(ctx_tmp = EVP_MD_CTX_new())
|| !TEST_true(EVP_MD_CTX_copy(ctx_tmp, ctx)))
goto err;
EVP_MD_CTX_free(ctx);
ctx = ctx_tmp;
ctx_tmp = NULL;
if (!TEST_true(EVP_DigestSignUpdate(ctx, ct, sizeof(ct))))
goto err;
res = 1;
err:
EVP_MD_CTX_free(ctx);
EVP_MD_CTX_free(ctx_tmp);
EVP_PKEY_free(pkey);
return res;
}
-# ifndef OPENSSL_NO_MD5
+#ifndef OPENSSL_NO_MD5
+# define OSSL_HEX_CHARS_PER_BYTE 2
static char *pt(unsigned char *md, unsigned int len)
{
unsigned int i;
- static char buf[80];
+ static char buf[201];
if (md == NULL)
return NULL;
- for (i = 0; i < len; i++)
- sprintf(&(buf[i * 2]), "%02x", md[i]);
+ for (i = 0; i < len && (i + 1) * OSSL_HEX_CHARS_PER_BYTE < sizeof(buf); i++)
+ BIO_snprintf(buf + i * OSSL_HEX_CHARS_PER_BYTE,
+ OSSL_HEX_CHARS_PER_BYTE + 1, "%02x", md[i]);
return buf;
}
-# endif
+#endif
int setup_tests(void)
{
ADD_ALL_TESTS(test_hmac_md5, 4);
ADD_TEST(test_hmac_single_shot);
ADD_TEST(test_hmac_bad);
ADD_TEST(test_hmac_run);
ADD_TEST(test_hmac_copy);
ADD_TEST(test_hmac_copy_uninited);
return 1;
}
diff --git a/crypto/openssl/test/memleaktest.c b/crypto/openssl/test/memleaktest.c
index 97827b8e9cd3..876168677398 100644
--- a/crypto/openssl/test/memleaktest.c
+++ b/crypto/openssl/test/memleaktest.c
@@ -1,62 +1,62 @@
/*
- * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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/bio.h>
#include <openssl/crypto.h>
#include "testutil.h"
/* __has_feature is a clang-ism, while __SANITIZE_ADDRESS__ is a gcc-ism */
#if defined(__has_feature)
# if __has_feature(address_sanitizer)
# define __SANITIZE_ADDRESS__ 1
# endif
#endif
/* If __SANITIZE_ADDRESS__ isn't defined, define it to be false */
/* Leak detection is not yet supported with MSVC on Windows, so */
/* set __SANITIZE_ADDRESS__ to false in this case as well. */
#if !defined(__SANITIZE_ADDRESS__) || defined(_MSC_VER)
# undef __SANITIZE_ADDRESS__
# define __SANITIZE_ADDRESS__ 0
#endif
/*
* We use a proper main function here instead of the custom main from the
* test framework to avoid CRYPTO_mem_leaks stuff.
*/
int main(int argc, char *argv[])
{
#if __SANITIZE_ADDRESS__
int exitcode = EXIT_SUCCESS;
#else
/*
* When we don't sanitize, we set the exit code to what we would expect
* to get when we are sanitizing. This makes it easy for wrapper scripts
* to detect that we get the result we expect.
*/
int exitcode = EXIT_FAILURE;
#endif
- char *lost;
+ char *volatile lost;
lost = OPENSSL_malloc(3);
if (!TEST_ptr(lost))
return EXIT_FAILURE;
strcpy(lost, "ab");
if (argv[1] && strcmp(argv[1], "freeit") == 0) {
OPENSSL_free(lost);
exitcode = EXIT_SUCCESS;
}
lost = NULL;
return exitcode;
}
diff --git a/crypto/openssl/test/p_test.c b/crypto/openssl/test/p_test.c
index 80f0784dd9d5..46f990113fb6 100644
--- a/crypto/openssl/test/p_test.c
+++ b/crypto/openssl/test/p_test.c
@@ -1,320 +1,346 @@
/*
- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 is a very simple provider that does absolutely nothing except respond
* to provider global parameter requests. It does this by simply echoing back
* a parameter request it makes to the loading library.
*/
#include <string.h>
#include <stdio.h>
+#include <stdarg.h>
+
/*
* When built as an object file to link the application with, we get the
* init function name through the macro PROVIDER_INIT_FUNCTION_NAME. If
* not defined, we use the standard init function name for the shared
* object form.
*/
#ifdef PROVIDER_INIT_FUNCTION_NAME
# define OSSL_provider_init PROVIDER_INIT_FUNCTION_NAME
#endif
#include "e_os.h"
#include <openssl/core.h>
#include <openssl/core_dispatch.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/provider.h>
typedef struct p_test_ctx {
char *thisfile;
char *thisfunc;
const OSSL_CORE_HANDLE *handle;
OSSL_LIB_CTX *libctx;
} P_TEST_CTX;
static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL;
static OSSL_FUNC_core_get_params_fn *c_get_params = NULL;
static OSSL_FUNC_core_new_error_fn *c_new_error;
static OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug;
static OSSL_FUNC_core_vset_error_fn *c_vset_error;
+static OSSL_FUNC_BIO_vsnprintf_fn *c_BIO_vsnprintf;
/* Tell the core what params we provide and what type they are */
static const OSSL_PARAM p_param_types[] = {
{ "greeting", OSSL_PARAM_UTF8_STRING, NULL, 0, 0 },
{ "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
{ NULL, 0, NULL, 0, 0 }
};
/* This is a trick to ensure we define the provider functions correctly */
static OSSL_FUNC_provider_gettable_params_fn p_gettable_params;
static OSSL_FUNC_provider_get_params_fn p_get_params;
static OSSL_FUNC_provider_get_reason_strings_fn p_get_reason_strings;
static OSSL_FUNC_provider_teardown_fn p_teardown;
+static int local_snprintf(char *buf, size_t n, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = (*c_BIO_vsnprintf)(buf, n, format, args);
+ va_end(args);
+ return ret;
+}
+
static void p_set_error(int lib, int reason, const char *file, int line,
const char *func, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
c_new_error(NULL);
c_set_error_debug(NULL, file, line, func);
c_vset_error(NULL, ERR_PACK(lib, 0, reason), fmt, ap);
va_end(ap);
}
static const OSSL_PARAM *p_gettable_params(void *_)
{
return p_param_types;
}
static int p_get_params(void *provctx, OSSL_PARAM params[])
{
P_TEST_CTX *ctx = (P_TEST_CTX *)provctx;
const OSSL_CORE_HANDLE *hand = ctx->handle;
OSSL_PARAM *p = params;
int ok = 1;
for (; ok && p->key != NULL; p++) {
if (strcmp(p->key, "greeting") == 0) {
static char *opensslv;
static char *provname;
static char *greeting;
static OSSL_PARAM counter_request[] = {
/* Known libcrypto provided parameters */
{ "openssl-version", OSSL_PARAM_UTF8_PTR,
&opensslv, sizeof(&opensslv), 0 },
{ "provider-name", OSSL_PARAM_UTF8_PTR,
&provname, sizeof(&provname), 0},
/* This might be present, if there's such a configuration */
{ "greeting", OSSL_PARAM_UTF8_PTR,
&greeting, sizeof(&greeting), 0 },
{ NULL, 0, NULL, 0, 0 }
};
char buf[256];
size_t buf_l;
opensslv = provname = greeting = NULL;
if (c_get_params(hand, counter_request)) {
if (greeting) {
strcpy(buf, greeting);
} else {
const char *versionp = *(void **)counter_request[0].data;
const char *namep = *(void **)counter_request[1].data;
- sprintf(buf, "Hello OpenSSL %.20s, greetings from %s!",
- versionp, namep);
+ local_snprintf(buf, sizeof(buf), "Hello OpenSSL %.20s, greetings from %s!",
+ versionp, namep);
}
} else {
- sprintf(buf, "Howdy stranger...");
+ local_snprintf(buf, sizeof(buf), "Howdy stranger...");
}
p->return_size = buf_l = strlen(buf) + 1;
if (p->data_size >= buf_l)
strcpy(p->data, buf);
else
ok = 0;
} else if (strcmp(p->key, "digest-check") == 0) {
unsigned int digestsuccess = 0;
/*
* Test we can use an algorithm from another provider. We're using
* legacy to check that legacy is actually available and we haven't
* just fallen back to default.
*/
#ifdef PROVIDER_INIT_FUNCTION_NAME
EVP_MD *md4 = EVP_MD_fetch(ctx->libctx, "MD4", NULL);
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
const char *msg = "Hello world";
unsigned char out[16];
OSSL_PROVIDER *deflt;
/*
* "default" has not been loaded into the parent libctx. We should be able
* to explicitly load it as a non-child provider.
*/
deflt = OSSL_PROVIDER_load(ctx->libctx, "default");
if (deflt == NULL
|| !OSSL_PROVIDER_available(ctx->libctx, "default")) {
/* We set error "3" for a failure to load the default provider */
p_set_error(ERR_LIB_PROV, 3, ctx->thisfile, OPENSSL_LINE,
ctx->thisfunc, NULL);
ok = 0;
}
/*
* We should have the default provider available that we loaded
* ourselves, and the base and legacy providers which we inherit
* from the parent libctx. We should also have "this" provider
* available.
*/
if (ok
&& OSSL_PROVIDER_available(ctx->libctx, "default")
&& OSSL_PROVIDER_available(ctx->libctx, "base")
&& OSSL_PROVIDER_available(ctx->libctx, "legacy")
&& OSSL_PROVIDER_available(ctx->libctx, "p_test")
&& md4 != NULL
&& mdctx != NULL) {
if (EVP_DigestInit_ex(mdctx, md4, NULL)
&& EVP_DigestUpdate(mdctx, (const unsigned char *)msg,
strlen(msg))
&& EVP_DigestFinal(mdctx, out, NULL))
digestsuccess = 1;
}
EVP_MD_CTX_free(mdctx);
EVP_MD_free(md4);
OSSL_PROVIDER_unload(deflt);
#endif
if (p->data_size >= sizeof(digestsuccess)) {
*(unsigned int *)p->data = digestsuccess;
p->return_size = sizeof(digestsuccess);
} else {
ok = 0;
}
} else if (strcmp(p->key, "stop-property-mirror") == 0) {
/*
* Setting the default properties explicitly should stop mirroring
* of properties from the parent libctx.
*/
unsigned int stopsuccess = 0;
#ifdef PROVIDER_INIT_FUNCTION_NAME
stopsuccess = EVP_set_default_properties(ctx->libctx, NULL);
#endif
if (p->data_size >= sizeof(stopsuccess)) {
*(unsigned int *)p->data = stopsuccess;
p->return_size = sizeof(stopsuccess);
} else {
ok = 0;
}
}
}
return ok;
}
static const OSSL_ITEM *p_get_reason_strings(void *_)
{
static const OSSL_ITEM reason_strings[] = {
{1, "dummy reason string"},
{2, "Can't create child library context"},
{3, "Can't load default provider"},
{0, NULL}
};
return reason_strings;
}
+static const OSSL_ALGORITHM *p_query(OSSL_PROVIDER *prov,
+ int operation_id,
+ int *no_cache)
+{
+ *no_cache = 1;
+ return NULL;
+}
+
static const OSSL_DISPATCH p_test_table[] = {
{ OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))p_gettable_params },
{ OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))p_get_params },
{ OSSL_FUNC_PROVIDER_GET_REASON_STRINGS,
(void (*)(void))p_get_reason_strings},
{ OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))p_teardown },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))p_query },
{ 0, NULL }
};
int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *oin,
const OSSL_DISPATCH **out,
void **provctx)
{
P_TEST_CTX *ctx;
const OSSL_DISPATCH *in = oin;
for (; in->function_id != 0; in++) {
switch (in->function_id) {
case OSSL_FUNC_CORE_GETTABLE_PARAMS:
c_gettable_params = OSSL_FUNC_core_gettable_params(in);
break;
case OSSL_FUNC_CORE_GET_PARAMS:
c_get_params = OSSL_FUNC_core_get_params(in);
break;
case OSSL_FUNC_CORE_NEW_ERROR:
c_new_error = OSSL_FUNC_core_new_error(in);
break;
case OSSL_FUNC_CORE_SET_ERROR_DEBUG:
c_set_error_debug = OSSL_FUNC_core_set_error_debug(in);
break;
case OSSL_FUNC_CORE_VSET_ERROR:
c_vset_error = OSSL_FUNC_core_vset_error(in);
break;
+ case OSSL_FUNC_BIO_VSNPRINTF:
+ c_BIO_vsnprintf = OSSL_FUNC_BIO_vsnprintf(in);
+ break;
default:
/* Just ignore anything we don't understand */
break;
}
}
/*
* We want to test that libcrypto doesn't use the file and func pointers
* that we provide to it via c_set_error_debug beyond the time that they
* are valid for. Therefore we dynamically allocate these strings now and
* free them again when the provider is torn down. If anything tries to
* use those strings after that point there will be a use-after-free and
* asan will complain (and hence the tests will fail).
* This file isn't linked against libcrypto, so we use malloc and strdup
* instead of OPENSSL_malloc and OPENSSL_strdup
*/
ctx = malloc(sizeof(*ctx));
if (ctx == NULL)
return 0;
ctx->thisfile = strdup(OPENSSL_FILE);
ctx->thisfunc = strdup(OPENSSL_FUNC);
ctx->handle = handle;
#ifdef PROVIDER_INIT_FUNCTION_NAME
/* We only do this if we are linked with libcrypto */
ctx->libctx = OSSL_LIB_CTX_new_child(handle, oin);
if (ctx->libctx == NULL) {
/* We set error "2" for a failure to create the child libctx*/
p_set_error(ERR_LIB_PROV, 2, ctx->thisfile, OPENSSL_LINE, ctx->thisfunc,
NULL);
p_teardown(ctx);
return 0;
}
/*
* The default provider is loaded - but the default properties should not
* allow its use.
*/
{
EVP_MD *sha256 = EVP_MD_fetch(ctx->libctx, "SHA2-256", NULL);
if (sha256 != NULL) {
EVP_MD_free(sha256);
p_teardown(ctx);
return 0;
}
}
#endif
/*
* Set a spurious error to check error handling works correctly. This will
* be ignored
*/
p_set_error(ERR_LIB_PROV, 1, ctx->thisfile, OPENSSL_LINE, ctx->thisfunc, NULL);
*provctx = (void *)ctx;
*out = p_test_table;
return 1;
}
static void p_teardown(void *provctx)
{
P_TEST_CTX *ctx = (P_TEST_CTX *)provctx;
#ifdef PROVIDER_INIT_FUNCTION_NAME
OSSL_LIB_CTX_free(ctx->libctx);
#endif
free(ctx->thisfile);
free(ctx->thisfunc);
free(ctx);
}
diff --git a/crypto/openssl/test/pkcs12_format_test.c b/crypto/openssl/test/pkcs12_format_test.c
index c142093f72bb..f7ecd7c1e635 100644
--- a/crypto/openssl/test/pkcs12_format_test.c
+++ b/crypto/openssl/test/pkcs12_format_test.c
@@ -1,961 +1,964 @@
/*
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "internal/nelem.h"
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include "testutil.h"
#include "helpers/pkcs12.h"
static int default_libctx = 1;
static OSSL_LIB_CTX *testctx = NULL;
static OSSL_PROVIDER *nullprov = NULL;
static OSSL_PROVIDER *deflprov = NULL;
static OSSL_PROVIDER *lgcyprov = NULL;
/* --------------------------------------------------------------------------
* PKCS12 component test data
*/
static const unsigned char CERT1[] =
{
0x30, 0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x56, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
0x8b, 0x4b, 0x5e, 0x6c, 0x03, 0x28, 0x4e, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x0e, 0x50, 0x31, 0x32, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x52, 0x6f, 0x6f, 0x74,
0x2d, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x39, 0x33, 0x30, 0x30, 0x30, 0x34, 0x36,
0x35, 0x36, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x39, 0x32, 0x37, 0x30, 0x30, 0x34, 0x36, 0x35,
0x36, 0x5a, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x50,
0x31, 0x32, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, 0x31, 0x30,
0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbc, 0xdc, 0x6f, 0x8c,
0x7a, 0x2a, 0x4b, 0xea, 0x66, 0x66, 0x04, 0xa9, 0x05, 0x92, 0x53, 0xd7, 0x13, 0x3c, 0x49, 0xe1,
0xc8, 0xbb, 0xdf, 0x3d, 0xcb, 0x88, 0x31, 0x07, 0x20, 0x59, 0x93, 0x24, 0x7f, 0x7d, 0xc6, 0x84,
0x81, 0x16, 0x64, 0x4a, 0x52, 0xa6, 0x30, 0x44, 0xdc, 0x1a, 0x30, 0xde, 0xae, 0x29, 0x18, 0xcf,
0xc7, 0xf3, 0xcf, 0x0c, 0xb7, 0x8e, 0x2b, 0x1e, 0x21, 0x01, 0x0b, 0xfb, 0xe5, 0xe6, 0xcf, 0x2b,
0x84, 0xe1, 0x33, 0xf8, 0xba, 0x02, 0xfc, 0x30, 0xfa, 0xc4, 0x33, 0xc7, 0x37, 0xc6, 0x7f, 0x72,
0x31, 0x92, 0x1d, 0x8f, 0xa0, 0xfb, 0xe5, 0x4a, 0x08, 0x31, 0x78, 0x80, 0x9c, 0x23, 0xb4, 0xe9,
0x19, 0x56, 0x04, 0xfa, 0x0d, 0x07, 0x04, 0xb7, 0x43, 0xac, 0x4c, 0x49, 0x7c, 0xc2, 0xa1, 0x44,
0xc1, 0x48, 0x7d, 0x28, 0xe5, 0x23, 0x66, 0x07, 0x22, 0xd5, 0xf0, 0xf1, 0x02, 0x03, 0x01, 0x00,
0x01, 0xa3, 0x3b, 0x30, 0x39, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
0x80, 0x14, 0xdb, 0xbb, 0xb8, 0x92, 0x4e, 0x24, 0x0b, 0x1b, 0xbb, 0x78, 0x33, 0xf9, 0x01, 0x02,
0x23, 0x0d, 0x96, 0x18, 0x30, 0x47, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30,
0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x04, 0xf0, 0x30, 0x0d,
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x81, 0x81,
0x00, 0x1c, 0x13, 0xdc, 0x02, 0xf1, 0x44, 0x36, 0x65, 0xa9, 0xbe, 0x30, 0x1c, 0x66, 0x14, 0x20,
0x86, 0x5a, 0xa8, 0x69, 0x25, 0xf8, 0x1a, 0xb6, 0x9e, 0x5e, 0xe9, 0x89, 0xb8, 0x67, 0x70, 0x19,
0x87, 0x60, 0xeb, 0x4b, 0x11, 0x71, 0x85, 0xf8, 0xe9, 0xa7, 0x3e, 0x20, 0x42, 0xec, 0x43, 0x25,
0x01, 0x03, 0xe5, 0x4d, 0x83, 0x22, 0xf5, 0x8e, 0x3a, 0x1a, 0x1b, 0xd4, 0x1c, 0xda, 0x6b, 0x9d,
0x10, 0x1b, 0xee, 0x67, 0x4e, 0x1f, 0x69, 0xab, 0xbc, 0xaa, 0x62, 0x8e, 0x9e, 0xc6, 0xee, 0xd6,
0x09, 0xc0, 0xca, 0xe0, 0xaa, 0x9f, 0x07, 0xb2, 0xc2, 0xbb, 0x31, 0x96, 0xa2, 0x04, 0x62, 0xd3,
0x13, 0x32, 0x29, 0x67, 0x6e, 0xad, 0x2e, 0x0b, 0xea, 0x04, 0x7c, 0x8c, 0x5a, 0x5d, 0xac, 0x14,
0xaa, 0x61, 0x7f, 0x28, 0x6c, 0x2d, 0x64, 0x2d, 0xc3, 0xaf, 0x77, 0x52, 0x90, 0xb4, 0x37, 0xc0,
0x30,
};
static const unsigned char CERT2[] =
{
0x30, 0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x56, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
0x8b, 0x4b, 0x5e, 0x6c, 0x03, 0x28, 0x4e, 0xe7, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x0e, 0x50, 0x31, 0x32, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x52, 0x6f, 0x6f, 0x74,
0x2d, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x39, 0x33, 0x30, 0x30, 0x30, 0x34, 0x36,
0x35, 0x36, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x39, 0x32, 0x37, 0x30, 0x30, 0x34, 0x36, 0x35,
0x36, 0x5a, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x50,
0x31, 0x32, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x31, 0x30,
0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa8, 0x6e, 0x40, 0x86,
0x9f, 0x98, 0x59, 0xfb, 0x57, 0xbf, 0xc1, 0x55, 0x12, 0x38, 0xeb, 0xb3, 0x46, 0x34, 0xc9, 0x35,
0x4d, 0xfd, 0x03, 0xe9, 0x3a, 0x88, 0x9e, 0x97, 0x8f, 0xf4, 0xec, 0x36, 0x7b, 0x3f, 0xba, 0xb8,
0xa5, 0x96, 0x30, 0x03, 0xc5, 0xc6, 0xd9, 0xa8, 0x4e, 0xbc, 0x23, 0x51, 0xa1, 0x96, 0xd2, 0x03,
0x98, 0x73, 0xb6, 0x17, 0x9c, 0x77, 0xd4, 0x95, 0x1e, 0x1b, 0xb3, 0x1b, 0xc8, 0x71, 0xd1, 0x2e,
0x31, 0xc7, 0x6a, 0x75, 0x57, 0x08, 0x7f, 0xba, 0x70, 0x76, 0xf7, 0x67, 0xf4, 0x4e, 0xbe, 0xfc,
0x70, 0x61, 0x41, 0x07, 0x2b, 0x7c, 0x3c, 0x3b, 0xb3, 0xbc, 0xd5, 0xa8, 0xbd, 0x28, 0xd8, 0x49,
0xd3, 0xe1, 0x78, 0xc8, 0xc1, 0x42, 0x5e, 0x18, 0x36, 0xa8, 0x41, 0xf7, 0xc8, 0xaa, 0x35, 0xfe,
0x2d, 0xd1, 0xb4, 0xcc, 0x00, 0x67, 0xae, 0x79, 0xd3, 0x28, 0xd5, 0x5b, 0x02, 0x03, 0x01, 0x00,
0x01, 0xa3, 0x3b, 0x30, 0x39, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
0x80, 0x14, 0xdb, 0xbb, 0xb8, 0x92, 0x4e, 0x24, 0x0b, 0x1b, 0xbb, 0x78, 0x33, 0xf9, 0x01, 0x02,
0x23, 0x0d, 0x96, 0x18, 0x30, 0x47, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30,
0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x04, 0xf0, 0x30, 0x0d,
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x81, 0x81,
0x00, 0x3b, 0xa6, 0x73, 0xbe, 0xe0, 0x28, 0xed, 0x1f, 0x29, 0x78, 0x4c, 0xc0, 0x1f, 0xe9, 0x85,
0xc6, 0x8f, 0xe3, 0x87, 0x7c, 0xd9, 0xe7, 0x0a, 0x37, 0xe8, 0xaa, 0xb5, 0xd2, 0x7f, 0xf8, 0x90,
0x20, 0x80, 0x35, 0xa7, 0x79, 0x2b, 0x04, 0xa7, 0xbf, 0xe6, 0x7b, 0x58, 0xcb, 0xec, 0x0e, 0x58,
0xef, 0x2a, 0x70, 0x8a, 0x56, 0x8a, 0xcf, 0x6b, 0x7a, 0x74, 0x0c, 0xf4, 0x15, 0x37, 0x93, 0xcd,
0xe6, 0xb2, 0xa1, 0x83, 0x09, 0xdb, 0x9e, 0x4f, 0xff, 0x6a, 0x17, 0x4f, 0x33, 0xc9, 0xcc, 0x90,
0x2a, 0x67, 0xff, 0x16, 0x78, 0xa8, 0x2c, 0x10, 0xe0, 0x52, 0x8c, 0xe6, 0xe9, 0x90, 0x8d, 0xe0,
0x62, 0x04, 0x9a, 0x0f, 0x44, 0x01, 0x82, 0x14, 0x92, 0x44, 0x25, 0x69, 0x22, 0xb7, 0xb8, 0xc5,
0x94, 0x4c, 0x4b, 0x1c, 0x9b, 0x92, 0x60, 0x66, 0x90, 0x4e, 0xb9, 0xa8, 0x4c, 0x89, 0xbb, 0x0f,
0x0b,
};
static const unsigned char KEY1[] =
{
0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xbc, 0xdc, 0x6f, 0x8c, 0x7a,
0x2a, 0x4b, 0xea, 0x66, 0x66, 0x04, 0xa9, 0x05, 0x92, 0x53, 0xd7, 0x13, 0x3c, 0x49, 0xe1, 0xc8,
0xbb, 0xdf, 0x3d, 0xcb, 0x88, 0x31, 0x07, 0x20, 0x59, 0x93, 0x24, 0x7f, 0x7d, 0xc6, 0x84, 0x81,
0x16, 0x64, 0x4a, 0x52, 0xa6, 0x30, 0x44, 0xdc, 0x1a, 0x30, 0xde, 0xae, 0x29, 0x18, 0xcf, 0xc7,
0xf3, 0xcf, 0x0c, 0xb7, 0x8e, 0x2b, 0x1e, 0x21, 0x01, 0x0b, 0xfb, 0xe5, 0xe6, 0xcf, 0x2b, 0x84,
0xe1, 0x33, 0xf8, 0xba, 0x02, 0xfc, 0x30, 0xfa, 0xc4, 0x33, 0xc7, 0x37, 0xc6, 0x7f, 0x72, 0x31,
0x92, 0x1d, 0x8f, 0xa0, 0xfb, 0xe5, 0x4a, 0x08, 0x31, 0x78, 0x80, 0x9c, 0x23, 0xb4, 0xe9, 0x19,
0x56, 0x04, 0xfa, 0x0d, 0x07, 0x04, 0xb7, 0x43, 0xac, 0x4c, 0x49, 0x7c, 0xc2, 0xa1, 0x44, 0xc1,
0x48, 0x7d, 0x28, 0xe5, 0x23, 0x66, 0x07, 0x22, 0xd5, 0xf0, 0xf1, 0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x81, 0x81, 0x00, 0xa5, 0x6d, 0xf9, 0x8f, 0xf5, 0x5a, 0xa3, 0x50, 0xd9, 0x0d, 0x37, 0xbb,
0xce, 0x13, 0x94, 0xb8, 0xea, 0x32, 0x7f, 0x0c, 0xf5, 0x46, 0x0b, 0x90, 0x17, 0x7e, 0x5e, 0x63,
0xbd, 0xa4, 0x78, 0xcd, 0x19, 0x97, 0xd4, 0x92, 0x30, 0x78, 0xaa, 0xb4, 0xa7, 0x9c, 0xc6, 0xdf,
0x2a, 0x65, 0x0e, 0xb5, 0x9f, 0x9c, 0x84, 0x0d, 0x4d, 0x3a, 0x74, 0xfc, 0xd0, 0xb4, 0x09, 0x74,
0xc4, 0xb8, 0x24, 0x03, 0xa8, 0xf0, 0xf8, 0x0d, 0x5c, 0x8e, 0xdf, 0x4b, 0xe1, 0x0a, 0x8f, 0x4f,
0xd5, 0xc7, 0x9b, 0x54, 0x55, 0x8f, 0x00, 0x5c, 0xea, 0x4c, 0x73, 0xf9, 0x1b, 0xbf, 0xb8, 0x93,
0x33, 0x20, 0xce, 0x45, 0xd9, 0x03, 0x02, 0xb2, 0x36, 0xc5, 0x0a, 0x30, 0x50, 0x78, 0x80, 0x66,
0x00, 0x22, 0x38, 0x86, 0xcf, 0x63, 0x4a, 0x5c, 0xbf, 0x2b, 0xd9, 0x6e, 0xe6, 0xf0, 0x39, 0xad,
0x12, 0x25, 0x41, 0xb9, 0x02, 0x41, 0x00, 0xf3, 0x7c, 0x07, 0x99, 0x64, 0x3a, 0x28, 0x8c, 0x8d,
0x05, 0xfe, 0x32, 0xb5, 0x4c, 0x8c, 0x6d, 0xde, 0x3d, 0x16, 0x08, 0xa0, 0x01, 0x61, 0x4f, 0x8e,
0xa0, 0xf7, 0x26, 0x26, 0xb5, 0x8e, 0xc0, 0x7a, 0xce, 0x86, 0x34, 0xde, 0xb8, 0xef, 0x86, 0x01,
0xbe, 0x24, 0xaa, 0x9b, 0x36, 0x93, 0x72, 0x9b, 0xf9, 0xc6, 0xcb, 0x76, 0x84, 0x67, 0x06, 0x06,
0x30, 0x50, 0xdf, 0x42, 0x17, 0xe0, 0xa7, 0x02, 0x41, 0x00, 0xc6, 0x91, 0xa0, 0x41, 0x34, 0x11,
0x67, 0x4b, 0x08, 0x0f, 0xda, 0xa7, 0x99, 0xec, 0x58, 0x11, 0xa5, 0x82, 0xdb, 0x50, 0xfe, 0x77,
0xe2, 0xd1, 0x53, 0x9c, 0x7d, 0xe8, 0xbf, 0xe7, 0x7c, 0xa9, 0x01, 0xb1, 0x87, 0xc3, 0x52, 0x79,
0x9e, 0x2c, 0xa7, 0x6f, 0x02, 0x37, 0x32, 0xef, 0x24, 0x31, 0x21, 0x0b, 0x86, 0x05, 0x32, 0x4a,
0x2e, 0x0b, 0x65, 0x05, 0xd3, 0xd6, 0x30, 0xb2, 0xfc, 0xa7, 0x02, 0x41, 0x00, 0xc2, 0xed, 0x31,
0xdc, 0x40, 0x9c, 0x3a, 0xe8, 0x42, 0xe2, 0x60, 0x5e, 0x52, 0x3c, 0xc5, 0x54, 0x14, 0x0e, 0x8d,
0x7c, 0x3c, 0x34, 0xbe, 0xa6, 0x05, 0x86, 0xa2, 0x36, 0x5d, 0xd9, 0x0e, 0x3e, 0xd4, 0x52, 0x50,
0xa9, 0x35, 0x01, 0x93, 0x68, 0x92, 0x2e, 0x9a, 0x86, 0x27, 0x1a, 0xab, 0x32, 0x9e, 0xe2, 0x79,
0x9f, 0x5b, 0xf3, 0xa5, 0xd2, 0xf1, 0xd3, 0x6e, 0x7b, 0x3e, 0x1b, 0x85, 0x93, 0x02, 0x40, 0x68,
0xb8, 0xb6, 0x7e, 0x8c, 0xba, 0x3c, 0xf2, 0x8a, 0x2e, 0xea, 0x4f, 0x07, 0xd3, 0x68, 0x62, 0xee,
0x1a, 0x04, 0x16, 0x44, 0x0d, 0xef, 0xf6, 0x1b, 0x95, 0x65, 0xa5, 0xd1, 0x47, 0x81, 0x2c, 0x14,
0xb3, 0x8e, 0xf9, 0x08, 0xcf, 0x11, 0x07, 0x55, 0xca, 0x2a, 0xad, 0xf7, 0xd3, 0xbd, 0x0f, 0x97,
0xf0, 0xde, 0xde, 0x70, 0xb6, 0x44, 0x70, 0x47, 0xf7, 0xf9, 0xcf, 0x75, 0x61, 0x7f, 0xf3, 0x02,
0x40, 0x38, 0x4a, 0x67, 0xaf, 0xae, 0xb6, 0xb2, 0x6a, 0x00, 0x25, 0x5a, 0xa4, 0x65, 0x20, 0xb1,
0x13, 0xbd, 0x83, 0xff, 0xb4, 0xbc, 0xf4, 0xdd, 0xa1, 0xbb, 0x1c, 0x96, 0x37, 0x35, 0xf4, 0xbf,
0xed, 0x4c, 0xed, 0x92, 0xe8, 0xac, 0xc9, 0xc1, 0xa5, 0xa3, 0x23, 0x66, 0x40, 0x8a, 0xa1, 0xe6,
0xe3, 0x95, 0xfe, 0xc4, 0x53, 0xf5, 0x7d, 0x6e, 0xca, 0x45, 0x42, 0xe4, 0xc2, 0x9f, 0xe5, 0x1e,
0xb5,
};
static const unsigned char KEY2[] =
{
0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xa8, 0x6e, 0x40, 0x86, 0x9f,
0x98, 0x59, 0xfb, 0x57, 0xbf, 0xc1, 0x55, 0x12, 0x38, 0xeb, 0xb3, 0x46, 0x34, 0xc9, 0x35, 0x4d,
0xfd, 0x03, 0xe9, 0x3a, 0x88, 0x9e, 0x97, 0x8f, 0xf4, 0xec, 0x36, 0x7b, 0x3f, 0xba, 0xb8, 0xa5,
0x96, 0x30, 0x03, 0xc5, 0xc6, 0xd9, 0xa8, 0x4e, 0xbc, 0x23, 0x51, 0xa1, 0x96, 0xd2, 0x03, 0x98,
0x73, 0xb6, 0x17, 0x9c, 0x77, 0xd4, 0x95, 0x1e, 0x1b, 0xb3, 0x1b, 0xc8, 0x71, 0xd1, 0x2e, 0x31,
0xc7, 0x6a, 0x75, 0x57, 0x08, 0x7f, 0xba, 0x70, 0x76, 0xf7, 0x67, 0xf4, 0x4e, 0xbe, 0xfc, 0x70,
0x61, 0x41, 0x07, 0x2b, 0x7c, 0x3c, 0x3b, 0xb3, 0xbc, 0xd5, 0xa8, 0xbd, 0x28, 0xd8, 0x49, 0xd3,
0xe1, 0x78, 0xc8, 0xc1, 0x42, 0x5e, 0x18, 0x36, 0xa8, 0x41, 0xf7, 0xc8, 0xaa, 0x35, 0xfe, 0x2d,
0xd1, 0xb4, 0xcc, 0x00, 0x67, 0xae, 0x79, 0xd3, 0x28, 0xd5, 0x5b, 0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x81, 0x81, 0x00, 0xa6, 0x00, 0x83, 0xf8, 0x2b, 0x33, 0xac, 0xfb, 0xdb, 0xf0, 0x52, 0x4b,
0xd6, 0x39, 0xe3, 0x94, 0x3d, 0x8d, 0xa9, 0x01, 0xb0, 0x6b, 0xbe, 0x7f, 0x10, 0x01, 0xb6, 0xcd,
0x0a, 0x45, 0x0a, 0xca, 0x67, 0x8e, 0xd8, 0x29, 0x44, 0x8a, 0x51, 0xa8, 0x66, 0x35, 0x26, 0x30,
0x8b, 0xe9, 0x41, 0xa6, 0x22, 0xec, 0xd2, 0xf0, 0x58, 0x41, 0x33, 0x26, 0xf2, 0x3f, 0xe8, 0x75,
0x4f, 0xc7, 0x5d, 0x2e, 0x5a, 0xa8, 0x7a, 0xd2, 0xbf, 0x59, 0xa0, 0x86, 0x79, 0x0b, 0x92, 0x6c,
0x95, 0x5d, 0x87, 0x63, 0x5c, 0xd6, 0x1a, 0xc0, 0xf6, 0x7a, 0x15, 0x8d, 0xc7, 0x3c, 0xb6, 0x9e,
0xa6, 0x58, 0x46, 0x9b, 0xbf, 0x3e, 0x28, 0x8c, 0xdf, 0x1a, 0x87, 0xaa, 0x7e, 0xf5, 0xf2, 0xcb,
0x5e, 0x84, 0x2d, 0xf6, 0x82, 0x7e, 0x89, 0x4e, 0xf5, 0xe6, 0x3c, 0x92, 0x80, 0x1e, 0x98, 0x1c,
0x6a, 0x7b, 0x57, 0x01, 0x02, 0x41, 0x00, 0xdd, 0x60, 0x95, 0xd7, 0xa1, 0x9d, 0x0c, 0xa1, 0x84,
0xc5, 0x39, 0xca, 0x67, 0x4c, 0x1c, 0x06, 0x71, 0x5b, 0x5c, 0x2d, 0x8d, 0xce, 0xcd, 0xe2, 0x79,
0xc8, 0x33, 0xbe, 0x50, 0x37, 0x60, 0x9f, 0x3b, 0xb9, 0x59, 0x55, 0x22, 0x1f, 0xa5, 0x4b, 0x1d,
0xca, 0x38, 0xa0, 0xab, 0x87, 0x9c, 0x86, 0x0e, 0xdb, 0x1c, 0x4f, 0x4f, 0x07, 0xed, 0x18, 0x3f,
0x05, 0x3c, 0xec, 0x78, 0x11, 0xf6, 0x99, 0x02, 0x41, 0x00, 0xc2, 0xc5, 0xcf, 0xbe, 0x95, 0x91,
0xeb, 0xcf, 0x47, 0xf3, 0x33, 0x32, 0xc7, 0x7e, 0x93, 0x56, 0xf7, 0xd8, 0xf9, 0xd4, 0xb6, 0xd6,
0x20, 0xac, 0xba, 0x8a, 0x20, 0x19, 0x14, 0xab, 0xc5, 0x5d, 0xb2, 0x08, 0xcc, 0x77, 0x7c, 0x65,
0xa8, 0xdb, 0x66, 0x97, 0x36, 0x44, 0x2c, 0x63, 0xc0, 0x6a, 0x7e, 0xb0, 0x0b, 0x5c, 0x90, 0x12,
0x50, 0xb4, 0x36, 0x60, 0xc3, 0x1f, 0x22, 0x0c, 0xc8, 0x13, 0x02, 0x40, 0x33, 0xc8, 0x7e, 0x04,
0x7c, 0x97, 0x61, 0xf6, 0xfe, 0x39, 0xac, 0x34, 0xfe, 0x48, 0xbd, 0x5d, 0x7c, 0x72, 0xa4, 0x73,
0x3b, 0x72, 0x9e, 0x92, 0x55, 0x6e, 0x51, 0x3c, 0x39, 0x43, 0x5a, 0xe4, 0xa4, 0x71, 0xcc, 0xc5,
0xaf, 0x3f, 0xbb, 0xc8, 0x80, 0x65, 0x67, 0x2d, 0x9e, 0x32, 0x10, 0x99, 0x03, 0x2c, 0x99, 0xc8,
0xab, 0x71, 0xed, 0x31, 0xf8, 0xbb, 0xde, 0xee, 0x69, 0x7f, 0xba, 0x31, 0x02, 0x40, 0x7e, 0xbc,
0x60, 0x55, 0x4e, 0xd5, 0xc8, 0x6e, 0xf4, 0x0e, 0x57, 0xbe, 0x2e, 0xf9, 0x39, 0xbe, 0x59, 0x3f,
0xa2, 0x30, 0xbb, 0x57, 0xd1, 0xa3, 0x13, 0x2e, 0x55, 0x7c, 0x7c, 0x6a, 0xd8, 0xde, 0x02, 0xbe,
0x9e, 0xed, 0x10, 0xd0, 0xc5, 0x73, 0x1d, 0xea, 0x3e, 0xb1, 0x55, 0x81, 0x02, 0xef, 0x48, 0xc8,
0x1c, 0x5c, 0x7a, 0x92, 0xb0, 0x58, 0xd3, 0x19, 0x5b, 0x5d, 0xa2, 0xb6, 0x56, 0x69, 0x02, 0x40,
0x1e, 0x00, 0x6a, 0x9f, 0xba, 0xee, 0x46, 0x5a, 0xc5, 0xb5, 0x9f, 0x91, 0x33, 0xdd, 0xc9, 0x96,
0x75, 0xb7, 0x87, 0xcf, 0x18, 0x1c, 0xb7, 0xb9, 0x3f, 0x04, 0x10, 0xb8, 0x75, 0xa9, 0xb8, 0xa0,
0x31, 0x35, 0x03, 0x30, 0x89, 0xc8, 0x37, 0x68, 0x20, 0x30, 0x99, 0x39, 0x96, 0xd6, 0x2b, 0x3d,
0x5e, 0x45, 0x84, 0xf7, 0xd2, 0x61, 0x50, 0xc9, 0x50, 0xba, 0x8d, 0x08, 0xaa, 0xd0, 0x08, 0x1e,
};
static const PKCS12_ATTR ATTRS1[] = {
{ "friendlyName", "george" },
{ "localKeyID", "1234567890" },
{ "1.2.3.4.5", "MyCustomAttribute" },
{ NULL, NULL }
};
static const PKCS12_ATTR ATTRS2[] = {
{ "friendlyName", "janet" },
{ "localKeyID", "987654321" },
{ "1.2.3.5.8.13", "AnotherCustomAttribute" },
{ NULL, NULL }
};
static const PKCS12_ENC enc_default = {
#ifndef OPENSSL_NO_DES
NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
#else
NID_aes_128_cbc,
#endif
"Password1",
1000
};
static const PKCS12_ENC mac_default = {
NID_sha1,
"Password1",
1000
};
static const int enc_nids_all[] = {
/* NOTE: To use PBES2 we pass the desired cipher NID instead of NID_pbes2 */
NID_aes_128_cbc,
NID_aes_256_cbc,
#ifndef OPENSSL_NO_DES
NID_des_ede3_cbc,
NID_des_cbc,
#endif
#ifndef OPENSSL_NO_RC5
NID_rc5_cbc,
#endif
#ifndef OPENSSL_NO_RC4
NID_rc4,
#endif
#ifndef OPENSSL_NO_RC2
NID_rc2_cbc,
#endif
#ifndef OPENSSL_NO_MD2
# ifndef OPENSSL_NO_DES
NID_pbeWithMD2AndDES_CBC,
# endif
# ifndef OPENSSL_NO_RC2
NID_pbeWithMD2AndRC2_CBC,
# endif
#endif
#ifndef OPENSSL_NO_MD5
# ifndef OPENSSL_NO_DES
NID_pbeWithMD5AndDES_CBC,
# endif
# ifndef OPENSSL_NO_RC2
NID_pbeWithMD5AndRC2_CBC,
# endif
#endif
#ifndef OPENSSL_NO_DES
NID_pbeWithSHA1AndDES_CBC,
#endif
#ifndef OPENSSL_NO_RC2
NID_pbe_WithSHA1And128BitRC2_CBC,
NID_pbe_WithSHA1And40BitRC2_CBC,
NID_pbeWithSHA1AndRC2_CBC,
#endif
#ifndef OPENSSL_NO_RC4
NID_pbe_WithSHA1And128BitRC4,
NID_pbe_WithSHA1And40BitRC4,
#endif
#ifndef OPENSSL_NO_DES
NID_pbe_WithSHA1And2_Key_TripleDES_CBC,
NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
#endif
};
static const int enc_nids_no_legacy[] = {
/* NOTE: To use PBES2 we pass the desired cipher NID instead of NID_pbes2 */
NID_aes_128_cbc,
NID_aes_256_cbc,
#ifndef OPENSSL_NO_DES
NID_des_ede3_cbc,
NID_pbe_WithSHA1And2_Key_TripleDES_CBC,
NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
#endif
};
static const int mac_nids[] = {
NID_sha1,
NID_md5,
NID_sha256,
NID_sha512,
NID_sha3_256,
NID_sha3_512
};
static const int iters[] = {
1,
1000
};
static const char *passwords[] = {
"Password1",
"",
};
/* --------------------------------------------------------------------------
* Local functions
*/
static int get_custom_oid(void)
{
static int sec_nid = -1;
if (sec_nid != -1)
return sec_nid;
if (!TEST_true(OBJ_create("1.3.5.7.9", "CustomSecretOID", "My custom secret OID")))
return -1;
return sec_nid = OBJ_txt2nid("CustomSecretOID");
}
/* --------------------------------------------------------------------------
* PKCS12 format tests
*/
static int test_single_cert_no_attrs(void)
{
PKCS12_BUILDER *pb = new_pkcs12_builder("1cert.p12");
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_certbag(pb, CERT1, sizeof(CERT1), NULL);
end_contentinfo(pb);
end_pkcs12(pb);
/* Read/decode */
start_check_pkcs12(pb);
start_check_contentinfo(pb);
check_certbag(pb, CERT1, sizeof(CERT1), NULL);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_single_key(PKCS12_ENC *enc)
{
char fname[80];
PKCS12_BUILDER *pb;
- sprintf(fname, "1key_ciph-%s_iter-%d.p12", OBJ_nid2sn(enc->nid), enc->iter);
+ BIO_snprintf(fname, sizeof(fname), "1key_ciph-%s_iter-%d.p12",
+ OBJ_nid2sn(enc->nid), enc->iter);
pb = new_pkcs12_builder(fname);
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_keybag(pb, KEY1, sizeof(KEY1), NULL, enc);
end_contentinfo(pb);
end_pkcs12(pb);
/* Read/decode */
start_check_pkcs12(pb);
start_check_contentinfo(pb);
check_keybag(pb, KEY1, sizeof(KEY1), NULL, enc);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_single_key_enc_alg(int z)
{
PKCS12_ENC enc;
if (lgcyprov == NULL)
enc.nid = enc_nids_no_legacy[z];
else
enc.nid = enc_nids_all[z];
enc.pass = enc_default.pass;
enc.iter = enc_default.iter;
return test_single_key(&enc);
}
static int test_single_key_enc_pass(int z)
{
PKCS12_ENC enc;
enc.nid = enc_default.nid;
enc.pass = passwords[z];
enc.iter = enc_default.iter;
return test_single_key(&enc);
}
static int test_single_key_enc_iter(int z)
{
PKCS12_ENC enc;
enc.nid = enc_default.nid;
enc.pass = enc_default.pass;
enc.iter = iters[z];
return test_single_key(&enc);
}
static int test_single_key_with_attrs(void)
{
PKCS12_BUILDER *pb = new_pkcs12_builder("1keyattrs.p12");
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_keybag(pb, KEY1, sizeof(KEY1), ATTRS1, &enc_default);
end_contentinfo(pb);
end_pkcs12(pb);
/* Read/decode */
start_check_pkcs12(pb);
start_check_contentinfo(pb);
check_keybag(pb, KEY1, sizeof(KEY1), ATTRS1, &enc_default);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_single_cert_mac(PKCS12_ENC *mac)
{
char fname[80];
PKCS12_BUILDER *pb;
- sprintf(fname, "1cert_mac-%s_iter-%d.p12", OBJ_nid2sn(mac->nid), mac->iter);
+ BIO_snprintf(fname, sizeof(fname), "1cert_mac-%s_iter-%d.p12",
+ OBJ_nid2sn(mac->nid), mac->iter);
pb = new_pkcs12_builder(fname);
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_certbag(pb, CERT1, sizeof(CERT1), NULL);
end_contentinfo(pb);
end_pkcs12_with_mac(pb, mac);
/* Read/decode */
start_check_pkcs12_with_mac(pb, mac);
start_check_contentinfo(pb);
check_certbag(pb, CERT1, sizeof(CERT1), NULL);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_single_cert_mac_alg(int z)
{
PKCS12_ENC mac;
mac.nid = mac_nids[z];
mac.pass = mac_default.pass;
mac.iter = mac_default.iter;
return test_single_cert_mac(&mac);
}
static int test_single_cert_mac_pass(int z)
{
PKCS12_ENC mac;
mac.nid = mac_default.nid;
mac.pass = passwords[z];
mac.iter = mac_default.iter;
return test_single_cert_mac(&mac);
}
static int test_single_cert_mac_iter(int z)
{
PKCS12_ENC mac;
mac.nid = mac_default.nid;
mac.pass = mac_default.pass;
mac.iter = iters[z];
return test_single_cert_mac(&mac);
}
static int test_cert_key_with_attrs_and_mac(void)
{
PKCS12_BUILDER *pb = new_pkcs12_builder("1cert1key.p12");
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_certbag(pb, CERT1, sizeof(CERT1), ATTRS1);
add_keybag(pb, KEY1, sizeof(KEY1), ATTRS1, &enc_default);
end_contentinfo(pb);
end_pkcs12_with_mac(pb, &mac_default);
/* Read/decode */
start_check_pkcs12_with_mac(pb, &mac_default);
start_check_contentinfo(pb);
check_certbag(pb, CERT1, sizeof(CERT1), ATTRS1);
check_keybag(pb, KEY1, sizeof(KEY1), ATTRS1, &enc_default);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_cert_key_encrypted_content(void)
{
PKCS12_BUILDER *pb = new_pkcs12_builder("1cert1key_enc.p12");
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_certbag(pb, CERT1, sizeof(CERT1), ATTRS1);
add_keybag(pb, KEY1, sizeof(KEY1), ATTRS1, &enc_default);
end_contentinfo_encrypted(pb, &enc_default);
end_pkcs12_with_mac(pb, &mac_default);
/* Read/decode */
start_check_pkcs12_with_mac(pb, &mac_default);
start_check_contentinfo_encrypted(pb, &enc_default);
check_certbag(pb, CERT1, sizeof(CERT1), ATTRS1);
check_keybag(pb, KEY1, sizeof(KEY1), ATTRS1, &enc_default);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_single_secret_encrypted_content(void)
{
PKCS12_BUILDER *pb = new_pkcs12_builder("1secret.p12");
int custom_nid = get_custom_oid();
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_secretbag(pb, custom_nid, "VerySecretMessage", ATTRS1);
end_contentinfo_encrypted(pb, &enc_default);
end_pkcs12_with_mac(pb, &mac_default);
/* Read/decode */
start_check_pkcs12_with_mac(pb, &mac_default);
start_check_contentinfo_encrypted(pb, &enc_default);
check_secretbag(pb, custom_nid, "VerySecretMessage", ATTRS1);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_single_secret(PKCS12_ENC *enc)
{
int custom_nid;
char fname[80];
PKCS12_BUILDER *pb;
- sprintf(fname, "1secret_ciph-%s_iter-%d.p12", OBJ_nid2sn(enc->nid), enc->iter);
+ BIO_snprintf(fname, sizeof(fname), "1secret_ciph-%s_iter-%d.p12",
+ OBJ_nid2sn(enc->nid), enc->iter);
pb = new_pkcs12_builder(fname);
custom_nid = get_custom_oid();
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_secretbag(pb, custom_nid, "VerySecretMessage", ATTRS1);
end_contentinfo_encrypted(pb, enc);
end_pkcs12_with_mac(pb, &mac_default);
/* Read/decode */
start_check_pkcs12_with_mac(pb, &mac_default);
start_check_contentinfo_encrypted(pb, enc);
check_secretbag(pb, custom_nid, "VerySecretMessage", ATTRS1);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_single_secret_enc_alg(int z)
{
PKCS12_ENC enc;
if (lgcyprov == NULL)
enc.nid = enc_nids_no_legacy[z];
else
enc.nid = enc_nids_all[z];
enc.pass = enc_default.pass;
enc.iter = enc_default.iter;
return test_single_secret(&enc);
}
static int test_multiple_contents(void)
{
PKCS12_BUILDER *pb = new_pkcs12_builder("multi_contents.p12");
int custom_nid = get_custom_oid();
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_certbag(pb, CERT1, sizeof(CERT1), ATTRS1);
add_certbag(pb, CERT2, sizeof(CERT2), ATTRS2);
add_keybag(pb, KEY1, sizeof(KEY1), ATTRS1, &enc_default);
add_keybag(pb, KEY2, sizeof(KEY2), ATTRS2, &enc_default);
end_contentinfo(pb);
start_contentinfo(pb);
add_secretbag(pb, custom_nid, "VeryVerySecretMessage", ATTRS1);
end_contentinfo_encrypted(pb, &enc_default);
end_pkcs12_with_mac(pb, &mac_default);
/* Read/decode */
start_check_pkcs12_with_mac(pb, &mac_default);
start_check_contentinfo(pb);
check_certbag(pb, CERT1, sizeof(CERT1), ATTRS1);
check_certbag(pb, CERT2, sizeof(CERT2), ATTRS2);
check_keybag(pb, KEY1, sizeof(KEY1), ATTRS1, &enc_default);
check_keybag(pb, KEY2, sizeof(KEY2), ATTRS2, &enc_default);
end_check_contentinfo(pb);
start_check_contentinfo_encrypted(pb, &enc_default);
check_secretbag(pb, custom_nid, "VeryVerySecretMessage", ATTRS1);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
#ifndef OPENSSL_NO_DES
static int pkcs12_create_test(void)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
PKCS12 *p12 = NULL;
const unsigned char *p;
static const unsigned char rsa_key[] = {
0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xbb,
0x24, 0x7a, 0x09, 0x7e, 0x0e, 0xb2, 0x37, 0x32, 0xcc, 0x39, 0x67, 0xad,
0xf1, 0x9e, 0x3d, 0x6b, 0x82, 0x83, 0xd1, 0xd0, 0xac, 0xa4, 0xc0, 0x18,
0xbe, 0x8d, 0x98, 0x00, 0xc0, 0x7b, 0xff, 0x07, 0x44, 0xc9, 0xca, 0x1c,
0xba, 0x36, 0xe1, 0x27, 0x69, 0xff, 0xb1, 0xe3, 0x8d, 0x8b, 0xee, 0x57,
0xa9, 0x3a, 0xaa, 0x16, 0x43, 0x39, 0x54, 0x19, 0x7c, 0xae, 0x69, 0x24,
0x14, 0xf6, 0x64, 0xff, 0xbc, 0x74, 0xc6, 0x67, 0x6c, 0x4c, 0xf1, 0x02,
0x49, 0x69, 0xc7, 0x2b, 0xe1, 0xe1, 0xa1, 0xa3, 0x43, 0x14, 0xf4, 0x77,
0x8f, 0xc8, 0xd0, 0x85, 0x5a, 0x35, 0x95, 0xac, 0x62, 0xa9, 0xc1, 0x21,
0x00, 0x77, 0xa0, 0x8b, 0x97, 0x30, 0xb4, 0x5a, 0x2c, 0xb8, 0x90, 0x2f,
0x48, 0xa0, 0x05, 0x28, 0x4b, 0xf2, 0x0f, 0x8d, 0xec, 0x8b, 0x4d, 0x03,
0x42, 0x75, 0xd6, 0xad, 0x81, 0xc0, 0x11, 0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x81, 0x80, 0x00, 0xfc, 0xb9, 0x4a, 0x26, 0x07, 0x89, 0x51, 0x2b,
0x53, 0x72, 0x91, 0xe0, 0x18, 0x3e, 0xa6, 0x5e, 0x31, 0xef, 0x9c, 0x0c,
0x16, 0x24, 0x42, 0xd0, 0x28, 0x33, 0xf9, 0xfa, 0xd0, 0x3c, 0x54, 0x04,
0x06, 0xc0, 0x15, 0xf5, 0x1b, 0x9a, 0xb3, 0x24, 0x31, 0xab, 0x3c, 0x6b,
0x47, 0x43, 0xb0, 0xd2, 0xa9, 0xdc, 0x05, 0xe1, 0x81, 0x59, 0xb6, 0x04,
0xe9, 0x66, 0x61, 0xaa, 0xd7, 0x0b, 0x00, 0x8f, 0x3d, 0xe5, 0xbf, 0xa2,
0xf8, 0x5e, 0x25, 0x6c, 0x1e, 0x22, 0x0f, 0xb4, 0xfd, 0x41, 0xe2, 0x03,
0x31, 0x5f, 0xda, 0x20, 0xc5, 0xc0, 0xf3, 0x55, 0x0e, 0xe1, 0xc9, 0xec,
0xd7, 0x3e, 0x2a, 0x0c, 0x01, 0xca, 0x7b, 0x22, 0xcb, 0xac, 0xf4, 0x2b,
0x27, 0xf0, 0x78, 0x5f, 0xb5, 0xc2, 0xf9, 0xe8, 0x14, 0x5a, 0x6e, 0x7e,
0x86, 0xbd, 0x6a, 0x9b, 0x20, 0x0c, 0xba, 0xcc, 0x97, 0x20, 0x11, 0x02,
0x41, 0x00, 0xc9, 0x59, 0x9f, 0x29, 0x8a, 0x5b, 0x9f, 0xe3, 0x2a, 0xd8,
0x7e, 0xc2, 0x40, 0x9f, 0xa8, 0x45, 0xe5, 0x3e, 0x11, 0x8d, 0x3c, 0xed,
0x6e, 0xab, 0xce, 0xd0, 0x65, 0x46, 0xd8, 0xc7, 0x07, 0x63, 0xb5, 0x23,
0x34, 0xf4, 0x9f, 0x7e, 0x1c, 0xc7, 0xc7, 0xf9, 0x65, 0xd1, 0xf4, 0x04,
0x42, 0x38, 0xbe, 0x3a, 0x0c, 0x9d, 0x08, 0x25, 0xfc, 0xa3, 0x71, 0xd9,
0xae, 0x0c, 0x39, 0x61, 0xf4, 0x89, 0x02, 0x41, 0x00, 0xed, 0xef, 0xab,
0xa9, 0xd5, 0x39, 0x9c, 0xee, 0x59, 0x1b, 0xff, 0xcf, 0x48, 0x44, 0x1b,
0xb6, 0x32, 0xe7, 0x46, 0x24, 0xf3, 0x04, 0x7f, 0xde, 0x95, 0x08, 0x6d,
0x75, 0x9e, 0x67, 0x17, 0xba, 0x5c, 0xa4, 0xd4, 0xe2, 0xe2, 0x4d, 0x77,
0xce, 0xeb, 0x66, 0x29, 0xc5, 0x96, 0xe0, 0x62, 0xbb, 0xe5, 0xac, 0xdc,
0x44, 0x62, 0x54, 0x86, 0xed, 0x64, 0x0c, 0xce, 0xd0, 0x60, 0x03, 0x9d,
0x49, 0x02, 0x40, 0x54, 0xd9, 0x18, 0x72, 0x27, 0xe4, 0xbe, 0x76, 0xbb,
0x1a, 0x6a, 0x28, 0x2f, 0x95, 0x58, 0x12, 0xc4, 0x2c, 0xa8, 0xb6, 0xcc,
0xe2, 0xfd, 0x0d, 0x17, 0x64, 0xc8, 0x18, 0xd7, 0xc6, 0xdf, 0x3d, 0x4c,
0x1a, 0x9e, 0xf9, 0x2a, 0xb0, 0xb9, 0x2e, 0x12, 0xfd, 0xec, 0xc3, 0x51,
0xc1, 0xed, 0xa9, 0xfd, 0xb7, 0x76, 0x93, 0x41, 0xd8, 0xc8, 0x22, 0x94,
0x1a, 0x77, 0xf6, 0x9c, 0xc3, 0xc3, 0x89, 0x02, 0x41, 0x00, 0x8e, 0xf9,
0xa7, 0x08, 0xad, 0xb5, 0x2a, 0x04, 0xdb, 0x8d, 0x04, 0xa1, 0xb5, 0x06,
0x20, 0x34, 0xd2, 0xcf, 0xc0, 0x89, 0xb1, 0x72, 0x31, 0xb8, 0x39, 0x8b,
0xcf, 0xe2, 0x8e, 0xa5, 0xda, 0x4f, 0x45, 0x1e, 0x53, 0x42, 0x66, 0xc4,
0x30, 0x4b, 0x29, 0x8e, 0xc1, 0x69, 0x17, 0x29, 0x8c, 0x8a, 0xe6, 0x0f,
0x82, 0x68, 0xa1, 0x41, 0xb3, 0xb6, 0x70, 0x99, 0x75, 0xa9, 0x27, 0x18,
0xe4, 0xe9, 0x02, 0x41, 0x00, 0x89, 0xea, 0x6e, 0x6d, 0x70, 0xdf, 0x25,
0x5f, 0x18, 0x3f, 0x48, 0xda, 0x63, 0x10, 0x8b, 0xfe, 0xa8, 0x0c, 0x94,
0x0f, 0xde, 0x97, 0x56, 0x53, 0x89, 0x94, 0xe2, 0x1e, 0x2c, 0x74, 0x3c,
0x91, 0x81, 0x34, 0x0b, 0xa6, 0x40, 0xf8, 0xcb, 0x2a, 0x60, 0x8c, 0xe0,
0x02, 0xb7, 0x89, 0x93, 0xcf, 0x18, 0x9f, 0x49, 0x54, 0xfd, 0x7d, 0x3f,
0x9a, 0xef, 0xd4, 0xa4, 0x4f, 0xc1, 0x45, 0x99, 0x91,
};
p = rsa_key;
if (!TEST_ptr(pkey = d2i_PrivateKey_ex(EVP_PKEY_RSA, NULL, &p,
sizeof(rsa_key), NULL, NULL)))
goto err;
if (!TEST_int_eq(ERR_peek_error(), 0))
goto err;
p12 = PKCS12_create(NULL, NULL, pkey, NULL, NULL,
NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 2, 1, 0);
if (!TEST_ptr(p12))
goto err;
if (!TEST_int_eq(ERR_peek_error(), 0))
goto err;
ret = 1;
err:
PKCS12_free(p12);
EVP_PKEY_free(pkey);
return ret;
}
#endif
static int pkcs12_recreate_test(void)
{
int ret = 0;
X509 *cert = NULL;
X509 *cert_parsed = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY *pkey_parsed = NULL;
PKCS12 *p12 = NULL;
PKCS12 *p12_parsed = NULL;
PKCS12 *p12_recreated = NULL;
const unsigned char *cert_bytes = CERT1;
const unsigned char *key_bytes = KEY1;
BIO *bio = NULL;
cert = d2i_X509(NULL, &cert_bytes, sizeof(CERT1));
if (!TEST_ptr(cert))
goto err;
pkey = d2i_AutoPrivateKey(NULL, &key_bytes, sizeof(KEY1));
if (!TEST_ptr(pkey))
goto err;
p12 = PKCS12_create("pass", NULL, pkey, cert, NULL, NID_aes_256_cbc,
NID_aes_256_cbc, 2, 1, 0);
if (!TEST_ptr(p12))
goto err;
if (!TEST_int_eq(ERR_peek_error(), 0))
goto err;
bio = BIO_new(BIO_s_mem());
if (!TEST_ptr(bio))
goto err;
if (!TEST_int_eq(i2d_PKCS12_bio(bio, p12), 1))
goto err;
p12_parsed = PKCS12_init_ex(NID_pkcs7_data, testctx, NULL);
if (!TEST_ptr(p12_parsed))
goto err;
p12_parsed = d2i_PKCS12_bio(bio, &p12_parsed);
if (!TEST_ptr(p12_parsed))
goto err;
if (!TEST_int_eq(PKCS12_parse(p12_parsed, "pass", &pkey_parsed,
&cert_parsed, NULL), 1))
goto err;
/* cert_parsed also contains auxiliary data */
p12_recreated = PKCS12_create("new_pass", NULL, pkey_parsed, cert_parsed,
NULL, NID_aes_256_cbc, NID_aes_256_cbc,
2, 1, 0);
if (!TEST_ptr(p12_recreated))
goto err;
if (!TEST_int_eq(ERR_peek_error(), 0))
goto err;
ret = 1;
err:
BIO_free(bio);
PKCS12_free(p12);
PKCS12_free(p12_parsed);
PKCS12_free(p12_recreated);
EVP_PKEY_free(pkey);
EVP_PKEY_free(pkey_parsed);
X509_free(cert);
X509_free(cert_parsed);
return ret;
}
typedef enum OPTION_choice {
OPT_ERR = -1,
OPT_EOF = 0,
OPT_WRITE,
OPT_LEGACY,
OPT_CONTEXT,
OPT_TEST_ENUM
} OPTION_CHOICE;
const OPTIONS *test_get_options(void)
{
static const OPTIONS options[] = {
OPT_TEST_OPTIONS_DEFAULT_USAGE,
{ "write", OPT_WRITE, '-', "Write PKCS12 objects to file" },
{ "legacy", OPT_LEGACY, '-', "Test the legacy APIs" },
{ "context", OPT_CONTEXT, '-', "Explicitly use a non-default library context" },
{ NULL }
};
return options;
}
int setup_tests(void)
{
OPTION_CHOICE o;
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_WRITE:
PKCS12_helper_set_write_files(1);
break;
case OPT_LEGACY:
PKCS12_helper_set_legacy(1);
break;
case OPT_CONTEXT:
default_libctx = 0;
break;
case OPT_TEST_CASES:
break;
default:
return 0;
}
}
if (!default_libctx) {
testctx = OSSL_LIB_CTX_new();
if (!TEST_ptr(testctx))
return 0;
nullprov = OSSL_PROVIDER_load(NULL, "null");
if (!TEST_ptr(nullprov))
return 0;
}
deflprov = OSSL_PROVIDER_load(testctx, "default");
if (!TEST_ptr(deflprov))
return 0;
lgcyprov = OSSL_PROVIDER_load(testctx, "legacy");
PKCS12_helper_set_libctx(testctx);
/*
* Verify that the default and fips providers in the default libctx are not
* available if we are using a standalone context
*/
if (!default_libctx) {
if (!TEST_false(OSSL_PROVIDER_available(NULL, "default"))
|| !TEST_false(OSSL_PROVIDER_available(NULL, "fips")))
return 0;
}
ADD_TEST(test_single_cert_no_attrs);
if (lgcyprov == NULL) {
ADD_ALL_TESTS(test_single_key_enc_alg, OSSL_NELEM(enc_nids_no_legacy));
ADD_ALL_TESTS(test_single_secret_enc_alg, OSSL_NELEM(enc_nids_no_legacy));
} else {
ADD_ALL_TESTS(test_single_key_enc_alg, OSSL_NELEM(enc_nids_all));
ADD_ALL_TESTS(test_single_secret_enc_alg, OSSL_NELEM(enc_nids_all));
}
#ifndef OPENSSL_NO_DES
if (default_libctx)
ADD_TEST(pkcs12_create_test);
#endif
if (default_libctx)
ADD_TEST(pkcs12_recreate_test);
ADD_ALL_TESTS(test_single_key_enc_pass, OSSL_NELEM(passwords));
ADD_ALL_TESTS(test_single_key_enc_iter, OSSL_NELEM(iters));
ADD_TEST(test_single_key_with_attrs);
ADD_ALL_TESTS(test_single_cert_mac_alg, OSSL_NELEM(mac_nids));
ADD_ALL_TESTS(test_single_cert_mac_pass, OSSL_NELEM(passwords));
ADD_ALL_TESTS(test_single_cert_mac_iter, OSSL_NELEM(iters));
ADD_TEST(test_cert_key_with_attrs_and_mac);
ADD_TEST(test_cert_key_encrypted_content);
ADD_TEST(test_single_secret_encrypted_content);
ADD_TEST(test_multiple_contents);
return 1;
}
void cleanup_tests(void)
{
OSSL_PROVIDER_unload(nullprov);
OSSL_PROVIDER_unload(deflprov);
OSSL_PROVIDER_unload(lgcyprov);
OSSL_LIB_CTX_free(testctx);
}
diff --git a/crypto/openssl/test/property_test.c b/crypto/openssl/test/property_test.c
index 88c5342c538e..1f1171ad90a6 100644
--- a/crypto/openssl/test/property_test.c
+++ b/crypto/openssl/test/property_test.c
@@ -1,676 +1,683 @@
/*
- * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 <stdarg.h>
#include <openssl/evp.h>
#include "testutil.h"
#include "internal/nelem.h"
#include "internal/property.h"
#include "../crypto/property/property_local.h"
/*
* We make our OSSL_PROVIDER for testing purposes. All we really need is
* a pointer. We know that as long as we don't try to use the method
* cache flush functions, the provider pointer is merely a pointer being
* passed around, and used as a tag of sorts.
*/
struct ossl_provider_st {
int x;
};
static int add_property_names(const char *n, ...)
{
va_list args;
int res = 1;
va_start(args, n);
do {
if (!TEST_int_ne(ossl_property_name(NULL, n, 1), 0))
res = 0;
} while ((n = va_arg(args, const char *)) != NULL);
va_end(args);
return res;
}
static int up_ref(void *p)
{
return 1;
}
static void down_ref(void *p)
{
}
static int test_property_string(void)
{
- OSSL_METHOD_STORE *store;
+ OSSL_LIB_CTX *ctx;
+ OSSL_METHOD_STORE *store = NULL;
int res = 0;
OSSL_PROPERTY_IDX i, j;
- if (TEST_ptr(store = ossl_method_store_new(NULL))
- && TEST_int_eq(ossl_property_name(NULL, "fnord", 0), 0)
- && TEST_int_ne(ossl_property_name(NULL, "fnord", 1), 0)
- && TEST_int_ne(ossl_property_name(NULL, "name", 1), 0)
+ /*-
+ * Use our own library context because we depend on ordering from a
+ * pristine state.
+ */
+ if (TEST_ptr(ctx = OSSL_LIB_CTX_new())
+ && TEST_ptr(store = ossl_method_store_new(ctx))
+ && TEST_int_eq(ossl_property_name(ctx, "fnord", 0), 0)
+ && TEST_int_ne(ossl_property_name(ctx, "fnord", 1), 0)
+ && TEST_int_ne(ossl_property_name(ctx, "name", 1), 0)
/* Property value checks */
- && TEST_int_eq(ossl_property_value(NULL, "fnord", 0), 0)
- && TEST_int_ne(i = ossl_property_value(NULL, "no", 0), 0)
- && TEST_int_ne(j = ossl_property_value(NULL, "yes", 0), 0)
+ && TEST_int_eq(ossl_property_value(ctx, "fnord", 0), 0)
+ && TEST_int_ne(i = ossl_property_value(ctx, "no", 0), 0)
+ && TEST_int_ne(j = ossl_property_value(ctx, "yes", 0), 0)
&& TEST_int_ne(i, j)
- && TEST_int_eq(ossl_property_value(NULL, "yes", 1), j)
- && TEST_int_eq(ossl_property_value(NULL, "no", 1), i)
- && TEST_int_ne(i = ossl_property_value(NULL, "illuminati", 1), 0)
- && TEST_int_eq(j = ossl_property_value(NULL, "fnord", 1), i + 1)
- && TEST_int_eq(ossl_property_value(NULL, "fnord", 1), j)
+ && TEST_int_eq(ossl_property_value(ctx, "yes", 1), j)
+ && TEST_int_eq(ossl_property_value(ctx, "no", 1), i)
+ && TEST_int_ne(i = ossl_property_value(ctx, "illuminati", 1), 0)
+ && TEST_int_eq(j = ossl_property_value(ctx, "fnord", 1), i + 1)
+ && TEST_int_eq(ossl_property_value(ctx, "fnord", 1), j)
/* Check name and values are distinct */
- && TEST_int_eq(ossl_property_value(NULL, "cold", 0), 0)
- && TEST_int_ne(ossl_property_name(NULL, "fnord", 0),
- ossl_property_value(NULL, "fnord", 0)))
+ && TEST_int_eq(ossl_property_value(ctx, "cold", 0), 0)
+ && TEST_int_ne(ossl_property_name(ctx, "fnord", 0),
+ ossl_property_value(ctx, "fnord", 0)))
res = 1;
ossl_method_store_free(store);
+ OSSL_LIB_CTX_free(ctx);
return res;
}
static const struct {
const char *defn;
const char *query;
int e;
} parser_tests[] = {
{ "", "sky=blue", -1 },
{ "", "sky!=blue", 1 },
{ "groan", "", 0 },
{ "cold=yes", "cold=yes", 1 },
{ "cold=yes", "cold", 1 },
{ "cold=yes", "cold!=no", 1 },
{ "groan", "groan=yes", 1 },
{ "groan", "groan=no", -1 },
{ "groan", "groan!=yes", -1 },
{ "cold=no", "cold", -1 },
{ "cold=no", "?cold", 0 },
{ "cold=no", "cold=no", 1 },
{ "groan", "cold", -1 },
{ "groan", "cold=no", 1 },
{ "groan", "cold!=yes", 1 },
{ "groan=blue", "groan=yellow", -1 },
{ "groan=blue", "?groan=yellow", 0 },
{ "groan=blue", "groan!=yellow", 1 },
{ "groan=blue", "?groan!=yellow", 1 },
{ "today=monday, tomorrow=3", "today!=2", 1 },
{ "today=monday, tomorrow=3", "today!='monday'", -1 },
{ "today=monday, tomorrow=3", "tomorrow=3", 1 },
{ "n=0x3", "n=3", 1 },
{ "n=0x3", "n=-3", -1 },
{ "n=0x33", "n=51", 1 },
{ "n=0x123456789abcdef", "n=0x123456789abcdef", 1 },
{ "n=0x7fffffffffffffff", "n=0x7fffffffffffffff", 1 }, /* INT64_MAX */
{ "n=9223372036854775807", "n=9223372036854775807", 1 }, /* INT64_MAX */
{ "n=0777777777777777777777", "n=0777777777777777777777", 1 }, /* INT64_MAX */
{ "n=033", "n=27", 1 },
{ "n=0", "n=00", 1 },
{ "n=0x0", "n=0", 1 },
{ "n=0, sky=blue", "?n=0, sky=blue", 2 },
{ "n=1, sky=blue", "?n=0, sky=blue", 1 },
};
static int test_property_parse(int n)
{
OSSL_METHOD_STORE *store;
OSSL_PROPERTY_LIST *p = NULL, *q = NULL;
int r = 0;
if (TEST_ptr(store = ossl_method_store_new(NULL))
&& add_property_names("sky", "groan", "cold", "today", "tomorrow", "n",
NULL)
&& TEST_ptr(p = ossl_parse_property(NULL, parser_tests[n].defn))
&& TEST_ptr(q = ossl_parse_query(NULL, parser_tests[n].query, 0))
&& TEST_int_eq(ossl_property_match_count(q, p), parser_tests[n].e))
r = 1;
ossl_property_free(p);
ossl_property_free(q);
ossl_method_store_free(store);
return r;
}
static int test_property_query_value_create(void)
{
OSSL_METHOD_STORE *store;
OSSL_PROPERTY_LIST *p = NULL, *q = NULL, *o = NULL;
int r = 0;
/* The property value used here must not be used in other test cases */
if (TEST_ptr(store = ossl_method_store_new(NULL))
&& add_property_names("wood", NULL)
&& TEST_ptr(p = ossl_parse_query(NULL, "wood=oak", 0)) /* undefined */
&& TEST_ptr(q = ossl_parse_query(NULL, "wood=oak", 1)) /* creates */
&& TEST_ptr(o = ossl_parse_query(NULL, "wood=oak", 0)) /* defined */
&& TEST_int_eq(ossl_property_match_count(q, p), -1)
&& TEST_int_eq(ossl_property_match_count(q, o), 1))
r = 1;
ossl_property_free(o);
ossl_property_free(p);
ossl_property_free(q);
ossl_method_store_free(store);
return r;
}
static const struct {
int query;
const char *ps;
} parse_error_tests[] = {
{ 0, "n=1, n=1" }, /* duplicate name */
{ 0, "n=1, a=hi, n=1" }, /* duplicate name */
{ 1, "n=1, a=bye, ?n=0" }, /* duplicate name */
{ 0, "a=abc,#@!, n=1" }, /* non-ASCII character located */
{ 1, "a='Hello" }, /* Unterminated string */
{ 0, "a=\"World" }, /* Unterminated string */
{ 0, "a=_abd_" }, /* Unquoted string not starting with alphabetic */
{ 1, "a=2, n=012345678" }, /* Bad octal digit */
{ 0, "n=0x28FG, a=3" }, /* Bad hex digit */
{ 0, "n=145d, a=2" }, /* Bad decimal digit */
{ 0, "n=0x8000000000000000, a=3" }, /* Hex overflow */
{ 0, "n=922337203000000000d, a=2" }, /* Decimal overflow */
{ 0, "a=2, n=1000000000000000000000" }, /* Octal overflow */
{ 1, "@='hello'" }, /* Invalid name */
{ 1, "n0123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789=yes" }, /* Name too long */
{ 0, ".n=3" }, /* Invalid name */
{ 1, "fnord.fnord.=3" } /* Invalid name */
};
static int test_property_parse_error(int n)
{
OSSL_METHOD_STORE *store;
OSSL_PROPERTY_LIST *p = NULL;
int r = 0;
const char *ps;
if (!TEST_ptr(store = ossl_method_store_new(NULL))
|| !add_property_names("a", "n", NULL))
goto err;
ps = parse_error_tests[n].ps;
if (parse_error_tests[n].query) {
if (!TEST_ptr_null(p = ossl_parse_query(NULL, ps, 1)))
goto err;
} else if (!TEST_ptr_null(p = ossl_parse_property(NULL, ps))) {
goto err;
}
r = 1;
err:
ossl_property_free(p);
ossl_method_store_free(store);
return r;
}
static const struct {
const char *q_global;
const char *q_local;
const char *prop;
} merge_tests[] = {
{ "", "colour=blue", "colour=blue" },
{ "colour=blue", "", "colour=blue" },
{ "colour=red", "colour=blue", "colour=blue" },
{ "clouds=pink, urn=red", "urn=blue, colour=green",
"urn=blue, colour=green, clouds=pink" },
{ "pot=gold", "urn=blue", "pot=gold, urn=blue" },
{ "night", "day", "day=yes, night=yes" },
{ "day", "night", "day=yes, night=yes" },
{ "", "", "" },
/*
* The following four leave 'day' unspecified in the query, and will match
* any definition
*/
{ "day=yes", "-day", "day=no" },
{ "day=yes", "-day", "day=yes" },
{ "day=yes", "-day", "day=arglebargle" },
{ "day=yes", "-day", "pot=sesquioxidizing" },
{ "day, night", "-night, day", "day=yes, night=no" },
{ "-day", "day=yes", "day=yes" },
};
static int test_property_merge(int n)
{
OSSL_METHOD_STORE *store;
OSSL_PROPERTY_LIST *q_global = NULL, *q_local = NULL;
OSSL_PROPERTY_LIST *q_combined = NULL, *prop = NULL;
int r = 0;
if (TEST_ptr(store = ossl_method_store_new(NULL))
&& add_property_names("colour", "urn", "clouds", "pot", "day", "night",
NULL)
&& TEST_ptr(prop = ossl_parse_property(NULL, merge_tests[n].prop))
&& TEST_ptr(q_global = ossl_parse_query(NULL, merge_tests[n].q_global,
0))
&& TEST_ptr(q_local = ossl_parse_query(NULL, merge_tests[n].q_local, 0))
&& TEST_ptr(q_combined = ossl_property_merge(q_local, q_global))
&& TEST_int_ge(ossl_property_match_count(q_combined, prop), 0))
r = 1;
ossl_property_free(q_global);
ossl_property_free(q_local);
ossl_property_free(q_combined);
ossl_property_free(prop);
ossl_method_store_free(store);
return r;
}
static int test_property_defn_cache(void)
{
OSSL_METHOD_STORE *store;
OSSL_PROPERTY_LIST *red = NULL, *blue = NULL, *blue2 = NULL;
int r;
r = TEST_ptr(store = ossl_method_store_new(NULL))
&& add_property_names("red", "blue", NULL)
&& TEST_ptr(red = ossl_parse_property(NULL, "red"))
&& TEST_ptr(blue = ossl_parse_property(NULL, "blue"))
&& TEST_ptr_ne(red, blue)
&& TEST_true(ossl_prop_defn_set(NULL, "red", &red));
if (!r) {
ossl_property_free(red);
red = NULL;
ossl_property_free(blue);
blue = NULL;
}
r = r && TEST_true(ossl_prop_defn_set(NULL, "blue", &blue));
if (!r) {
ossl_property_free(blue);
blue = NULL;
}
r = r && TEST_ptr_eq(ossl_prop_defn_get(NULL, "red"), red)
&& TEST_ptr_eq(ossl_prop_defn_get(NULL, "blue"), blue)
&& TEST_ptr(blue2 = ossl_parse_property(NULL, "blue"))
&& TEST_ptr_ne(blue2, blue)
&& TEST_true(ossl_prop_defn_set(NULL, "blue", &blue2));
if (!r) {
ossl_property_free(blue2);
blue2 = NULL;
}
r = r && TEST_ptr_eq(blue2, blue)
&& TEST_ptr_eq(ossl_prop_defn_get(NULL, "blue"), blue);
ossl_method_store_free(store);
return r;
}
static const struct {
const char *defn;
const char *query;
int e;
} definition_tests[] = {
{ "alpha", "alpha=yes", 1 },
{ "alpha=no", "alpha", -1 },
{ "alpha=1", "alpha=1", 1 },
{ "alpha=2", "alpha=1",-1 },
{ "alpha", "omega", -1 },
{ "alpha", "?omega", 0 },
{ "alpha", "?omega=1", 0 },
{ "alpha", "?omega=no", 1 },
{ "alpha", "?omega=yes", 0 },
{ "alpha, omega", "?omega=yes", 1 },
{ "alpha, omega", "?omega=no", 0 }
};
static int test_definition_compares(int n)
{
OSSL_METHOD_STORE *store;
OSSL_PROPERTY_LIST *d = NULL, *q = NULL;
int r;
r = TEST_ptr(store = ossl_method_store_new(NULL))
&& add_property_names("alpha", "omega", NULL)
&& TEST_ptr(d = ossl_parse_property(NULL, definition_tests[n].defn))
&& TEST_ptr(q = ossl_parse_query(NULL, definition_tests[n].query, 0))
&& TEST_int_eq(ossl_property_match_count(q, d), definition_tests[n].e);
ossl_property_free(d);
ossl_property_free(q);
ossl_method_store_free(store);
return r;
}
static int test_register_deregister(void)
{
static const struct {
int nid;
const char *prop;
char *impl;
} impls[] = {
{ 6, "position=1", "a" },
{ 6, "position=2", "b" },
{ 6, "position=3", "c" },
{ 6, "position=4", "d" },
};
size_t i;
int ret = 0;
OSSL_METHOD_STORE *store;
OSSL_PROVIDER prov = { 1 };
if (!TEST_ptr(store = ossl_method_store_new(NULL))
|| !add_property_names("position", NULL))
goto err;
for (i = 0; i < OSSL_NELEM(impls); i++)
if (!TEST_true(ossl_method_store_add(store, &prov, impls[i].nid,
impls[i].prop, impls[i].impl,
&up_ref, &down_ref))) {
TEST_note("iteration %zd", i + 1);
goto err;
}
/* Deregister in a different order to registration */
for (i = 0; i < OSSL_NELEM(impls); i++) {
const size_t j = (1 + i * 3) % OSSL_NELEM(impls);
int nid = impls[j].nid;
void *impl = impls[j].impl;
if (!TEST_true(ossl_method_store_remove(store, nid, impl))
|| !TEST_false(ossl_method_store_remove(store, nid, impl))) {
TEST_note("iteration %zd, position %zd", i + 1, j + 1);
goto err;
}
}
if (TEST_false(ossl_method_store_remove(store, impls[0].nid, impls[0].impl)))
ret = 1;
err:
ossl_method_store_free(store);
return ret;
}
static int test_property(void)
{
static OSSL_PROVIDER fake_provider1 = { 1 };
static OSSL_PROVIDER fake_provider2 = { 2 };
static const OSSL_PROVIDER *fake_prov1 = &fake_provider1;
static const OSSL_PROVIDER *fake_prov2 = &fake_provider2;
static const struct {
const OSSL_PROVIDER **prov;
int nid;
const char *prop;
char *impl;
} impls[] = {
{ &fake_prov1, 1, "fast=no, colour=green", "a" },
{ &fake_prov1, 1, "fast, colour=blue", "b" },
{ &fake_prov1, 1, "", "-" },
{ &fake_prov2, 9, "sky=blue, furry", "c" },
{ &fake_prov2, 3, NULL, "d" },
{ &fake_prov2, 6, "sky.colour=blue, sky=green, old.data", "e" },
};
static struct {
const OSSL_PROVIDER **prov;
int nid;
const char *prop;
char *expected;
} queries[] = {
{ &fake_prov1, 1, "fast", "b" },
{ &fake_prov1, 1, "fast=yes", "b" },
{ &fake_prov1, 1, "fast=no, colour=green", "a" },
{ &fake_prov1, 1, "colour=blue, fast", "b" },
{ &fake_prov1, 1, "colour=blue", "b" },
{ &fake_prov2, 9, "furry", "c" },
{ &fake_prov2, 6, "sky.colour=blue", "e" },
{ &fake_prov2, 6, "old.data", "e" },
{ &fake_prov2, 9, "furry=yes, sky=blue", "c" },
{ &fake_prov1, 1, "", "a" },
{ &fake_prov2, 3, "", "d" },
};
OSSL_METHOD_STORE *store;
size_t i;
int ret = 0;
void *result;
if (!TEST_ptr(store = ossl_method_store_new(NULL))
|| !add_property_names("fast", "colour", "sky", "furry", NULL))
goto err;
for (i = 0; i < OSSL_NELEM(impls); i++)
if (!TEST_true(ossl_method_store_add(store, *impls[i].prov,
impls[i].nid, impls[i].prop,
impls[i].impl,
&up_ref, &down_ref))) {
TEST_note("iteration %zd", i + 1);
goto err;
}
/*
* The first check of queries is with NULL given as provider. All
* queries are expected to succeed.
*/
for (i = 0; i < OSSL_NELEM(queries); i++) {
const OSSL_PROVIDER *nullprov = NULL;
OSSL_PROPERTY_LIST *pq = NULL;
if (!TEST_true(ossl_method_store_fetch(store,
queries[i].nid, queries[i].prop,
&nullprov, &result))
|| !TEST_str_eq((char *)result, queries[i].expected)) {
TEST_note("iteration %zd", i + 1);
ossl_property_free(pq);
goto err;
}
ossl_property_free(pq);
}
/*
* The second check of queries is with &address1 given as provider.
*/
for (i = 0; i < OSSL_NELEM(queries); i++) {
OSSL_PROPERTY_LIST *pq = NULL;
result = NULL;
if (queries[i].prov == &fake_prov1) {
if (!TEST_true(ossl_method_store_fetch(store,
queries[i].nid,
queries[i].prop,
&fake_prov1, &result))
|| !TEST_ptr_eq(fake_prov1, &fake_provider1)
|| !TEST_str_eq((char *)result, queries[i].expected)) {
TEST_note("iteration %zd", i + 1);
ossl_property_free(pq);
goto err;
}
} else {
if (!TEST_false(ossl_method_store_fetch(store,
queries[i].nid,
queries[i].prop,
&fake_prov1, &result))
|| !TEST_ptr_eq(fake_prov1, &fake_provider1)
|| !TEST_ptr_null(result)) {
TEST_note("iteration %zd", i + 1);
ossl_property_free(pq);
goto err;
}
}
ossl_property_free(pq);
}
/*
* The third check of queries is with &address2 given as provider.
*/
for (i = 0; i < OSSL_NELEM(queries); i++) {
OSSL_PROPERTY_LIST *pq = NULL;
result = NULL;
if (queries[i].prov == &fake_prov2) {
if (!TEST_true(ossl_method_store_fetch(store,
queries[i].nid,
queries[i].prop,
&fake_prov2, &result))
|| !TEST_ptr_eq(fake_prov2, &fake_provider2)
|| !TEST_str_eq((char *)result, queries[i].expected)) {
TEST_note("iteration %zd", i + 1);
ossl_property_free(pq);
goto err;
}
} else {
if (!TEST_false(ossl_method_store_fetch(store,
queries[i].nid,
queries[i].prop,
&fake_prov2, &result))
|| !TEST_ptr_eq(fake_prov2, &fake_provider2)
|| !TEST_ptr_null(result)) {
TEST_note("iteration %zd", i + 1);
ossl_property_free(pq);
goto err;
}
}
ossl_property_free(pq);
}
ret = 1;
err:
ossl_method_store_free(store);
return ret;
}
static int test_query_cache_stochastic(void)
{
const int max = 10000, tail = 10;
OSSL_METHOD_STORE *store;
int i, res = 0;
char buf[50];
void *result;
int errors = 0;
int v[10001];
OSSL_PROVIDER prov = { 1 };
if (!TEST_ptr(store = ossl_method_store_new(NULL))
|| !add_property_names("n", NULL))
goto err;
for (i = 1; i <= max; i++) {
v[i] = 2 * i;
BIO_snprintf(buf, sizeof(buf), "n=%d\n", i);
if (!TEST_true(ossl_method_store_add(store, &prov, i, buf, "abc",
&up_ref, &down_ref))
|| !TEST_true(ossl_method_store_cache_set(store, &prov, i,
buf, v + i,
&up_ref, &down_ref))
|| !TEST_true(ossl_method_store_cache_set(store, &prov, i,
"n=1234", "miss",
&up_ref, &down_ref))) {
TEST_note("iteration %d", i);
goto err;
}
}
for (i = 1; i <= max; i++) {
BIO_snprintf(buf, sizeof(buf), "n=%d\n", i);
if (!ossl_method_store_cache_get(store, NULL, i, buf, &result)
|| result != v + i)
errors++;
}
/* There is a tiny probability that this will fail when it shouldn't */
res = TEST_int_gt(errors, tail) && TEST_int_lt(errors, max - tail);
err:
ossl_method_store_free(store);
return res;
}
static int test_fips_mode(void)
{
int ret = 0;
OSSL_LIB_CTX *ctx = NULL;
if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()))
goto err;
ret = TEST_true(EVP_set_default_properties(ctx, "default=yes,fips=yes"))
&& TEST_true(EVP_default_properties_is_fips_enabled(ctx))
&& TEST_true(EVP_set_default_properties(ctx, "fips=no,default=yes"))
&& TEST_false(EVP_default_properties_is_fips_enabled(ctx))
&& TEST_true(EVP_set_default_properties(ctx, "fips=no"))
&& TEST_false(EVP_default_properties_is_fips_enabled(ctx))
&& TEST_true(EVP_set_default_properties(ctx, "fips!=no"))
&& TEST_true(EVP_default_properties_is_fips_enabled(ctx))
&& TEST_true(EVP_set_default_properties(ctx, "fips=no"))
&& TEST_false(EVP_default_properties_is_fips_enabled(ctx))
&& TEST_true(EVP_set_default_properties(ctx, "fips=no,default=yes"))
&& TEST_true(EVP_default_properties_enable_fips(ctx, 1))
&& TEST_true(EVP_default_properties_is_fips_enabled(ctx))
&& TEST_true(EVP_default_properties_enable_fips(ctx, 0))
&& TEST_false(EVP_default_properties_is_fips_enabled(ctx));
err:
OSSL_LIB_CTX_free(ctx);
return ret;
}
static struct {
const char *in;
const char *out;
} to_string_tests[] = {
{ "fips=yes", "fips=yes" },
{ "fips!=yes", "fips!=yes" },
{ "fips = yes", "fips=yes" },
{ "fips", "fips=yes" },
{ "fips=no", "fips=no" },
{ "-fips", "-fips" },
{ "?fips=yes", "?fips=yes" },
{ "fips=yes,provider=fips", "fips=yes,provider=fips" },
{ "fips = yes , provider = fips", "fips=yes,provider=fips" },
{ "fips=yes,provider!=fips", "fips=yes,provider!=fips" },
{ "fips=yes,?provider=fips", "fips=yes,?provider=fips" },
{ "fips=yes,-provider", "fips=yes,-provider" },
/* foo is an unknown internal name */
{ "foo=yes,fips=yes", "fips=yes"},
{ "", "" },
{ "fips=3", "fips=3" },
{ "fips=-3", "fips=-3" },
{ "provider='foo bar'", "provider='foo bar'" },
{ "provider=\"foo bar'\"", "provider=\"foo bar'\"" },
{ "provider=abc***", "provider='abc***'" },
{ NULL, "" }
};
static int test_property_list_to_string(int i)
{
OSSL_PROPERTY_LIST *pl = NULL;
int ret = 0;
size_t bufsize;
char *buf = NULL;
if (to_string_tests[i].in != NULL
&& !TEST_ptr(pl = ossl_parse_query(NULL, to_string_tests[i].in, 1)))
goto err;
bufsize = ossl_property_list_to_string(NULL, pl, NULL, 0);
if (!TEST_size_t_gt(bufsize, 0))
goto err;
buf = OPENSSL_malloc(bufsize);
if (!TEST_ptr(buf)
|| !TEST_size_t_eq(ossl_property_list_to_string(NULL, pl, buf,
bufsize),
bufsize)
|| !TEST_str_eq(to_string_tests[i].out, buf)
|| !TEST_size_t_eq(bufsize, strlen(to_string_tests[i].out) + 1))
goto err;
ret = 1;
err:
OPENSSL_free(buf);
ossl_property_free(pl);
return ret;
}
int setup_tests(void)
{
ADD_TEST(test_property_string);
ADD_TEST(test_property_query_value_create);
ADD_ALL_TESTS(test_property_parse, OSSL_NELEM(parser_tests));
ADD_ALL_TESTS(test_property_parse_error, OSSL_NELEM(parse_error_tests));
ADD_ALL_TESTS(test_property_merge, OSSL_NELEM(merge_tests));
ADD_TEST(test_property_defn_cache);
ADD_ALL_TESTS(test_definition_compares, OSSL_NELEM(definition_tests));
ADD_TEST(test_register_deregister);
ADD_TEST(test_property);
ADD_TEST(test_query_cache_stochastic);
ADD_TEST(test_fips_mode);
ADD_ALL_TESTS(test_property_list_to_string, OSSL_NELEM(to_string_tests));
return 1;
}
diff --git a/crypto/openssl/test/recipes/03-test_fipsinstall.t b/crypto/openssl/test/recipes/03-test_fipsinstall.t
index 5f514e231b59..c243b5646d37 100644
--- a/crypto/openssl/test/recipes/03-test_fipsinstall.t
+++ b/crypto/openssl/test/recipes/03-test_fipsinstall.t
@@ -1,316 +1,320 @@
#! /usr/bin/env perl
# Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
use strict;
use warnings;
use File::Spec::Functions qw(:DEFAULT abs2rel);
use File::Copy;
use OpenSSL::Glob;
use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/;
use OpenSSL::Test::Utils;
BEGIN {
setup("test_fipsinstall");
}
use lib srctop_dir('Configurations');
use lib bldtop_dir('.');
use platform;
plan skip_all => "Test only supported in a fips build" if disabled("fips");
plan tests => 29;
my $infile = bldtop_file('providers', platform->dso('fips'));
my $fipskey = $ENV{FIPSKEY} // config('FIPSKEY') // '00';
my $provconf = srctop_file("test", "fips-and-base.cnf");
run(test(["fips_version_test", "-config", $provconf, "<3.4.0"]),
capture => 1, statusvar => \my $indicatorpost);
# Read in a text $infile and replace the regular expression in $srch with the
# value in $repl and output to a new file $outfile.
sub replace_line_file_internal {
my ($infile, $srch, $repl, $outfile) = @_;
my $msg;
open(my $in, "<", $infile) or return 0;
read($in, $msg, 1024);
close $in;
$msg =~ s/$srch/$repl/;
open(my $fh, ">", $outfile) or return 0;
print $fh $msg;
close $fh;
return 1;
}
# Read in the text input file 'fips.cnf'
# and replace a single Key = Value line with a new value in $value.
# OR remove the Key = Value line if the passed in $value is empty.
# and then output a new file $outfile.
# $key is the Key to find
sub replace_line_file {
my ($key, $value, $outfile) = @_;
my $srch = qr/$key\s*=\s*\S*\n/;
my $rep;
if ($value eq "") {
$rep = "";
} else {
$rep = "$key = $value\n";
}
return replace_line_file_internal('fips.cnf', $srch, $rep, $outfile);
}
# Read in the text input file 'test/fips.cnf'
# and replace the .cnf file used in
# .include fipsmodule.cnf with a new value in $value.
# and then output a new file $outfile.
# $key is the Key to find
sub replace_parent_line_file {
my ($value, $outfile) = @_;
my $srch = qr/fipsmodule.cnf/;
my $rep = "$value";
return replace_line_file_internal(srctop_file("test", 'fips.cnf'),
$srch, $rep, $outfile);
}
# fail if no module name
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module',
'-provider_name', 'fips',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect'])),
"fipsinstall fail");
# fail to verify if the configuration file is missing
ok(!run(app(['openssl', 'fipsinstall', '-in', 'dummy.tmp', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail");
# output a fips.cnf file containing mac data
ok(run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect'])),
"fipsinstall");
# verify the fips.cnf file
ok(run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify");
ok(replace_line_file('module-mac', '', 'fips_no_module_mac.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-in', 'fips_no_module_mac.cnf',
'-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail no module mac");
ok(replace_line_file('install-mac', '', 'fips_no_install_mac.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-in', 'fips_no_install_mac.cnf',
'-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail no install indicator mac");
ok(replace_line_file('module-mac', '00:00:00:00:00:00',
'fips_bad_module_mac.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-in', 'fips_bad_module_mac.cnf',
'-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail if invalid module integrity value");
ok(replace_line_file('install-mac', '00:00:00:00:00:00',
'fips_bad_install_mac.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-in', 'fips_bad_install_mac.cnf',
'-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail if invalid install indicator integrity value");
ok(replace_line_file('install-status', 'INCORRECT_STATUS_STRING',
'fips_bad_indicator.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-in', 'fips_bad_indicator.cnf',
'-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail if invalid install indicator status");
# fail to verify the fips.cnf file if a different key is used
ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail bad key");
# fail to verify the fips.cnf file if a different mac digest is used
ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA512', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail incorrect digest");
# corrupt the module hmac
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-corrupt_desc', 'HMAC'])),
"fipsinstall fails when the module integrity is corrupted");
# corrupt the first digest
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-corrupt_desc', 'SHA2'])),
"fipsinstall fails when the digest result is corrupted");
# corrupt another digest
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-corrupt_desc', 'SHA3'])),
"fipsinstall fails when the digest result is corrupted");
# corrupt cipher encrypt test
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-corrupt_desc', 'AES_GCM'])),
"fipsinstall fails when the AES_GCM result is corrupted");
# corrupt cipher decrypt test
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-corrupt_desc', 'AES_ECB_Decrypt'])),
"fipsinstall fails when the AES_ECB result is corrupted");
# corrupt DRBG
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect', '-corrupt_desc', 'CTR'])),
"fipsinstall fails when the DRBG CTR result is corrupted");
# corrupt a KAS test
SKIP: {
skip "Skipping KAS DH corruption test because of no dh in this build", 1
if disabled("dh");
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect',
'-corrupt_desc', 'DH',
'-corrupt_type', 'KAT_KA'])),
"fipsinstall fails when the kas result is corrupted");
}
# corrupt a Signature test
SKIP: {
skip "Skipping Signature DSA corruption test because of no dsa in this build", 1
if disabled("dsa");
run(test(["fips_version_test", "-config", $provconf, "<3.1.0"]),
capture => 1, statusvar => \my $exit);
skip "FIPS provider version is too new for PCT DSA signature test", 1
if !$exit;
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
'-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
'-section_name', 'fips_sect',
'-corrupt_desc', 'DSA',
'-corrupt_type', 'PCT_Signature'])),
"fipsinstall fails when the signature result is corrupted");
}
# corrupt an Asymmetric cipher test
SKIP: {
skip "Skipping Asymmetric RSA corruption test because of no rsa in this build", 1
if disabled("rsa");
+ run(test(["fips_version_test", "-config", $provconf, "<3.5.0"]),
+ capture => 1, statusvar => \my $exit);
+ skip "FIPS provider version is too new for Asymmetric RSA corruption test", 1
+ if !$exit;
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
'-corrupt_desc', 'RSA_Encrypt',
'-corrupt_type', 'KAT_AsymmetricCipher'])),
"fipsinstall fails when the asymmetric cipher result is corrupted");
}
# 'local' ensures that this change is only done in this file.
local $ENV{OPENSSL_CONF_INCLUDE} = abs2rel(curdir());
ok(replace_parent_line_file('fips.cnf', 'fips_parent.cnf')
&& run(app(['openssl', 'fipsinstall', '-config', 'fips_parent.cnf'])),
"verify fips provider loads from a configuration file");
ok(replace_parent_line_file('fips_no_module_mac.cnf',
'fips_parent_no_module_mac.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-config', 'fips_parent_no_module_mac.cnf'])),
"verify load config fail no module mac");
SKIP: {
skip "Newer FIPS provider version does not support this feature", 3
if !$indicatorpost;
ok(replace_parent_line_file('fips_no_install_mac.cnf',
'fips_parent_no_install_mac.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-config', 'fips_parent_no_install_mac.cnf'])),
"verify load config fail no install mac");
ok(replace_parent_line_file('fips_bad_indicator.cnf',
'fips_parent_bad_indicator.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-config', 'fips_parent_bad_indicator.cnf'])),
"verify load config fail bad indicator");
ok(replace_parent_line_file('fips_bad_install_mac.cnf',
'fips_parent_bad_install_mac.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-config', 'fips_parent_bad_install_mac.cnf'])),
"verify load config fail bad install mac");
}
ok(replace_parent_line_file('fips_bad_module_mac.cnf',
'fips_parent_bad_module_mac.cnf')
&& !run(app(['openssl', 'fipsinstall',
'-config', 'fips_parent_bad_module_mac.cnf'])),
"verify load config fail bad module mac");
my $stconf = "fipsmodule_selftest.cnf";
ok(run(app(['openssl', 'fipsinstall', '-out', $stconf,
'-module', $infile, '-self_test_onload'])),
"fipsinstall config saved without self test indicator");
ok(!run(app(['openssl', 'fipsinstall', '-in', $stconf,
'-module', $infile, '-verify'])),
"fipsinstall config verify fails without self test indicator");
ok(run(app(['openssl', 'fipsinstall', '-in', $stconf,
'-module', $infile, '-self_test_onload', '-verify'])),
"fipsinstall config verify passes when self test indicator is not present");
diff --git a/crypto/openssl/test/recipes/04-test_encoder_decoder.t b/crypto/openssl/test/recipes/04-test_encoder_decoder.t
index 19541610a9a9..d5d79f3a5754 100644
--- a/crypto/openssl/test/recipes/04-test_encoder_decoder.t
+++ b/crypto/openssl/test/recipes/04-test_encoder_decoder.t
@@ -1,51 +1,76 @@
#! /usr/bin/env perl
# Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
use strict;
use warnings;
use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/;
use OpenSSL::Test::Utils;
BEGIN {
setup("test_encoder_decoder");
}
use lib srctop_dir('Configurations');
use lib bldtop_dir('.');
use platform;
my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
my $rsa_key = srctop_file("test", "certs", "ee-key.pem");
my $pss_key = srctop_file("test", "certs", "ca-pss-key.pem");
-plan tests => ($no_fips ? 0 : 1) + 2; # FIPS install test + test
+plan tests => ($no_fips ? 0 : 3) + 2; # FIPS install test + test
my $conf = srctop_file("test", "default.cnf");
+
+# Check if the specified pattern occurs in the given file
+# Returns 1 if the pattern is found and 0 if not
+sub find_line_file {
+ my ($key, $file) = @_;
+
+ open(my $in, $file) or return -1;
+ while (my $line = <$in>) {
+ if ($line =~ /$key/) {
+ close($in);
+ return 1;
+ }
+ }
+ close($in);
+ return 0;
+}
+
ok(run(test(["endecode_test", "-rsa", $rsa_key,
"-pss", $pss_key,
"-config", $conf,
"-provider", "default"])));
# Run with non-default library context
ok(run(test(["endecode_test", "-rsa", $rsa_key,
"-pss", $pss_key,
"-context",
"-config", $conf,
"-provider", "default"])));
unless ($no_fips) {
# Run with fips library context
my $conf = srctop_file("test", "fips-and-base.cnf");
ok(run(test(["endecode_test", "-rsa", $rsa_key,
"-pss", $pss_key,
"-config", $conf,
"-provider", "fips"])));
+SKIP: {
+ skip "EC disabled", 2 if disabled("ec");
+ ok(run(app([ 'openssl', 'genpkey', '-algorithm', 'EC',
+ '-pkeyopt', 'group:P-256', '-text',
+ '-config', $conf, '-provider', 'fips', '-out', 'ec.txt' ])),
+ 'Print a FIPS provider EC private key');
+ ok(find_line_file('NIST CURVE: P-256', 'ec.txt') == 1,
+ 'Printing an FIPS provider EC private key');
+}
}
-
diff --git a/crypto/openssl/test/recipes/25-test_verify.t b/crypto/openssl/test/recipes/25-test_verify.t
index 818c9ac50dd3..7fa14d9daa8b 100644
--- a/crypto/openssl/test/recipes/25-test_verify.t
+++ b/crypto/openssl/test/recipes/25-test_verify.t
@@ -1,529 +1,529 @@
#! /usr/bin/env perl
# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
use strict;
use warnings;
use File::Spec::Functions qw/canonpath/;
use File::Copy;
use OpenSSL::Test qw/:DEFAULT srctop_file bldtop_dir ok_nofips with/;
use OpenSSL::Test::Utils;
setup("test_verify");
sub verify {
my ($cert, $purpose, $trusted, $untrusted, @opts) = @_;
my @path = qw(test certs);
my @args = qw(openssl verify -auth_level 1);
push(@args, "-purpose", $purpose) if $purpose ne "";
push(@args, @opts);
for (@$trusted) { push(@args, "-trusted", srctop_file(@path, "$_.pem")) }
for (@$untrusted) { push(@args, "-untrusted", srctop_file(@path, "$_.pem")) }
push(@args, srctop_file(@path, "$cert.pem"));
run(app([@args]));
}
plan tests => 166;
# Canonical success
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]),
"accept compat trust");
# Root CA variants
ok(!verify("ee-cert", "sslserver", [qw(root-nonca)], [qw(ca-cert)]),
"fail trusted non-ca root");
ok(!verify("ee-cert", "sslserver", [qw(nroot+serverAuth)], [qw(ca-cert)]),
"fail server trust non-ca root");
ok(!verify("ee-cert", "sslserver", [qw(nroot+anyEKU)], [qw(ca-cert)]),
"fail wildcard trust non-ca root");
ok(!verify("ee-cert", "sslserver", [qw(root-cert2)], [qw(ca-cert)]),
"fail wrong root key");
ok(!verify("ee-cert", "sslserver", [qw(root-name2)], [qw(ca-cert)]),
"fail wrong root DN");
# Critical extensions
ok(verify("ee-cert-noncrit-unknown-ext", "", ["root-cert"], ["ca-cert"]),
"accept non-critical unknown extension");
ok(!verify("ee-cert-crit-unknown-ext", "", ["root-cert"], ["ca-cert"]),
"reject critical unknown extension");
ok(verify("ee-cert-ocsp-nocheck", "", ["root-cert"], ["ca-cert"]),
"accept critical OCSP No Check");
# Explicit trust/purpose combinations
#
ok(verify("ee-cert", "sslserver", [qw(sroot-cert)], [qw(ca-cert)]),
"accept server purpose");
ok(!verify("ee-cert", "sslserver", [qw(croot-cert)], [qw(ca-cert)]),
- "fail client purpose");
+ "fail client purpose"); # beware, questionable non-standard EKU check on trust anchor
ok(verify("ee-cert", "sslserver", [qw(root+serverAuth)], [qw(ca-cert)]),
"accept server trust");
ok(verify("ee-cert", "sslserver", [qw(sroot+serverAuth)], [qw(ca-cert)]),
"accept server trust with server purpose");
ok(verify("ee-cert", "sslserver", [qw(croot+serverAuth)], [qw(ca-cert)]),
"accept server trust with client purpose");
# Wildcard trust
ok(verify("ee-cert", "sslserver", [qw(root+anyEKU)], [qw(ca-cert)]),
"accept wildcard trust");
ok(verify("ee-cert", "sslserver", [qw(sroot+anyEKU)], [qw(ca-cert)]),
"accept wildcard trust with server purpose");
ok(verify("ee-cert", "sslserver", [qw(croot+anyEKU)], [qw(ca-cert)]),
"accept wildcard trust with client purpose");
# Inapplicable mistrust
ok(verify("ee-cert", "sslserver", [qw(root-clientAuth)], [qw(ca-cert)]),
"accept client mistrust");
ok(verify("ee-cert", "sslserver", [qw(sroot-clientAuth)], [qw(ca-cert)]),
"accept client mistrust with server purpose");
ok(!verify("ee-cert", "sslserver", [qw(croot-clientAuth)], [qw(ca-cert)]),
- "fail client mistrust with client purpose");
+ "fail client mistrust with client purpose"); # beware, questionable non-standard EKU check on trust anchor
# Inapplicable trust
ok(!verify("ee-cert", "sslserver", [qw(root+clientAuth)], [qw(ca-cert)]),
"fail client trust");
ok(!verify("ee-cert", "sslserver", [qw(sroot+clientAuth)], [qw(ca-cert)]),
"fail client trust with server purpose");
ok(!verify("ee-cert", "sslserver", [qw(croot+clientAuth)], [qw(ca-cert)]),
"fail client trust with client purpose");
# Server mistrust
ok(!verify("ee-cert", "sslserver", [qw(root-serverAuth)], [qw(ca-cert)]),
"fail rejected EKU");
ok(!verify("ee-cert", "sslserver", [qw(sroot-serverAuth)], [qw(ca-cert)]),
"fail server mistrust with server purpose");
ok(!verify("ee-cert", "sslserver", [qw(croot-serverAuth)], [qw(ca-cert)]),
"fail server mistrust with client purpose");
# Wildcard mistrust
ok(!verify("ee-cert", "sslserver", [qw(root-anyEKU)], [qw(ca-cert)]),
"fail wildcard mistrust");
ok(!verify("ee-cert", "sslserver", [qw(sroot-anyEKU)], [qw(ca-cert)]),
"fail wildcard mistrust with server purpose");
ok(!verify("ee-cert", "sslserver", [qw(croot-anyEKU)], [qw(ca-cert)]),
"fail wildcard mistrust with client purpose");
# Check that trusted-first is on by setting up paths to different roots
# depending on whether the intermediate is the trusted or untrusted one.
#
ok(verify("ee-cert", "sslserver", [qw(root-serverAuth root-cert2 ca-root2)],
[qw(ca-cert)]),
"accept trusted-first path");
ok(verify("ee-cert", "sslserver", [qw(root-cert root2+serverAuth ca-root2)],
[qw(ca-cert)]),
"accept trusted-first path with server trust");
ok(!verify("ee-cert", "sslserver", [qw(root-cert root2-serverAuth ca-root2)],
[qw(ca-cert)]),
"fail trusted-first path with server mistrust");
ok(!verify("ee-cert", "sslserver", [qw(root-cert root2+clientAuth ca-root2)],
[qw(ca-cert)]),
"fail trusted-first path with client trust");
# CA variants
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-nonca)]),
"fail non-CA untrusted intermediate");
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-nonbc)]),
"fail non-CA untrusted intermediate");
ok(!verify("ee-cert", "sslserver", [qw(root-cert ca-nonca)], []),
"fail non-CA trust-store intermediate");
ok(!verify("ee-cert", "sslserver", [qw(root-cert ca-nonbc)], []),
"fail non-CA trust-store intermediate");
ok(!verify("ee-cert", "sslserver", [qw(root-cert nca+serverAuth)], []),
"fail non-CA server trust intermediate");
ok(!verify("ee-cert", "sslserver", [qw(root-cert nca+anyEKU)], []),
"fail non-CA wildcard trust intermediate");
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-cert2)]),
"fail wrong intermediate CA key");
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-name2)]),
"fail wrong intermediate CA DN");
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-root2)]),
"fail wrong intermediate CA issuer");
ok(!verify("ee-cert", "sslserver", [], [qw(ca-cert)], "-partial_chain"),
"fail untrusted partial chain");
ok(verify("ee-cert", "sslserver", [qw(ca-cert)], [], "-partial_chain"),
"accept trusted partial chain");
ok(!verify("ee-cert", "sslserver", [qw(ca-expired)], [], "-partial_chain"),
"reject expired trusted partial chain"); # this check is beyond RFC 5280
ok(!verify("ee-cert", "sslserver", [qw(root-expired)], [qw(ca-cert)]),
"reject expired trusted root"); # this check is beyond RFC 5280
ok(verify("ee-cert", "sslserver", [qw(sca-cert)], [], "-partial_chain"),
"accept partial chain with server purpose");
ok(!verify("ee-cert", "sslserver", [qw(cca-cert)], [], "-partial_chain"),
- "fail partial chain with client purpose");
+ "fail partial chain with client purpose"); # beware, questionable non-standard EKU check on trust anchor
ok(verify("ee-cert", "sslserver", [qw(ca+serverAuth)], [], "-partial_chain"),
"accept server trust partial chain");
ok(verify("ee-cert", "sslserver", [qw(cca+serverAuth)], [], "-partial_chain"),
"accept server trust client purpose partial chain");
ok(verify("ee-cert", "sslserver", [qw(ca-clientAuth)], [], "-partial_chain"),
"accept client mistrust partial chain");
ok(verify("ee-cert", "sslserver", [qw(ca+anyEKU)], [], "-partial_chain"),
"accept wildcard trust partial chain");
ok(!verify("ee-cert", "sslserver", [], [qw(ca+serverAuth)], "-partial_chain"),
"fail untrusted partial issuer with ignored server trust");
ok(!verify("ee-cert", "sslserver", [qw(ca-serverAuth)], [], "-partial_chain"),
"fail server mistrust partial chain");
ok(!verify("ee-cert", "sslserver", [qw(ca+clientAuth)], [], "-partial_chain"),
"fail client trust partial chain");
ok(!verify("ee-cert", "sslserver", [qw(ca-anyEKU)], [], "-partial_chain"),
"fail wildcard mistrust partial chain");
# We now test auxiliary trust even for intermediate trusted certs without
# -partial_chain. Note that "-trusted_first" is now always on and cannot
# be disabled.
ok(verify("ee-cert", "sslserver", [qw(root-cert ca+serverAuth)], [qw(ca-cert)]),
"accept server trust");
ok(verify("ee-cert", "sslserver", [qw(root-cert ca+anyEKU)], [qw(ca-cert)]),
"accept wildcard trust");
ok(verify("ee-cert", "sslserver", [qw(root-cert sca-cert)], [qw(ca-cert)]),
"accept server purpose");
ok(verify("ee-cert", "sslserver", [qw(root-cert sca+serverAuth)], [qw(ca-cert)]),
"accept server trust and purpose");
ok(verify("ee-cert", "sslserver", [qw(root-cert sca+anyEKU)], [qw(ca-cert)]),
"accept wildcard trust and server purpose");
ok(verify("ee-cert", "sslserver", [qw(root-cert sca-clientAuth)], [qw(ca-cert)]),
"accept client mistrust and server purpose");
ok(verify("ee-cert", "sslserver", [qw(root-cert cca+serverAuth)], [qw(ca-cert)]),
"accept server trust and client purpose");
ok(verify("ee-cert", "sslserver", [qw(root-cert cca+anyEKU)], [qw(ca-cert)]),
"accept wildcard trust and client purpose");
ok(!verify("ee-cert", "sslserver", [qw(root-cert cca-cert)], [qw(ca-cert)]),
- "fail client purpose");
+ "fail client purpose intermediate trusted"); # beware, questionable non-standard EKU check on trust anchor
ok(!verify("ee-cert", "sslserver", [qw(root-cert ca-anyEKU)], [qw(ca-cert)]),
"fail wildcard mistrust");
ok(!verify("ee-cert", "sslserver", [qw(root-cert ca-serverAuth)], [qw(ca-cert)]),
"fail server mistrust");
ok(!verify("ee-cert", "sslserver", [qw(root-cert ca+clientAuth)], [qw(ca-cert)]),
"fail client trust");
ok(!verify("ee-cert", "sslserver", [qw(root-cert sca+clientAuth)], [qw(ca-cert)]),
"fail client trust and server purpose");
ok(!verify("ee-cert", "sslserver", [qw(root-cert cca+clientAuth)], [qw(ca-cert)]),
"fail client trust and client purpose");
ok(!verify("ee-cert", "sslserver", [qw(root-cert cca-serverAuth)], [qw(ca-cert)]),
"fail server mistrust and client purpose");
ok(!verify("ee-cert", "sslserver", [qw(root-cert cca-clientAuth)], [qw(ca-cert)]),
"fail client mistrust and client purpose");
ok(!verify("ee-cert", "sslserver", [qw(root-cert sca-serverAuth)], [qw(ca-cert)]),
"fail server mistrust and server purpose");
ok(!verify("ee-cert", "sslserver", [qw(root-cert sca-anyEKU)], [qw(ca-cert)]),
"fail wildcard mistrust and server purpose");
ok(!verify("ee-cert", "sslserver", [qw(root-cert cca-anyEKU)], [qw(ca-cert)]),
"fail wildcard mistrust and client purpose");
# EE variants
ok(verify("ee-client", "sslclient", [qw(root-cert)], [qw(ca-cert)]),
"accept client chain");
ok(!verify("ee-client", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
"fail server leaf purpose");
ok(!verify("ee-cert", "sslclient", [qw(root-cert)], [qw(ca-cert)]),
"fail client leaf purpose");
ok(!verify("ee-cert2", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
"fail wrong intermediate CA key");
ok(!verify("ee-name2", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
"fail wrong intermediate CA DN");
ok(!verify("ee-expired", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
"fail expired leaf");
ok(verify("ee-cert", "sslserver", [qw(ee-cert)], [], "-partial_chain"),
"accept last-resort direct leaf match");
ok(verify("ee-client", "sslclient", [qw(ee-client)], [], "-partial_chain"),
"accept last-resort direct leaf match");
ok(!verify("ee-cert", "sslserver", [qw(ee-client)], [], "-partial_chain"),
"fail last-resort direct leaf non-match");
ok(verify("ee-cert", "sslserver", [qw(ee+serverAuth)], [], "-partial_chain"),
"accept direct match with server trust");
ok(!verify("ee-cert", "sslserver", [qw(ee-serverAuth)], [], "-partial_chain"),
"fail direct match with server mistrust");
ok(verify("ee-client", "sslclient", [qw(ee+clientAuth)], [], "-partial_chain"),
"accept direct match with client trust");
ok(!verify("ee-client", "sslclient", [qw(ee-clientAuth)], [], "-partial_chain"),
"reject direct match with client mistrust");
ok(verify("ee-pathlen", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
"accept non-ca with pathlen:0 by default");
ok(!verify("ee-pathlen", "sslserver", [qw(root-cert)], [qw(ca-cert)], "-x509_strict"),
"reject non-ca with pathlen:0 with strict flag");
# Proxy certificates
ok(!verify("pc1-cert", "sslclient", [qw(root-cert)], [qw(ee-client ca-cert)]),
"fail to accept proxy cert without -allow_proxy_certs");
ok(verify("pc1-cert", "sslclient", [qw(root-cert)], [qw(ee-client ca-cert)],
"-allow_proxy_certs"),
"accept proxy cert 1");
ok(verify("pc2-cert", "sslclient", [qw(root-cert)], [qw(pc1-cert ee-client ca-cert)],
"-allow_proxy_certs"),
"accept proxy cert 2");
ok(!verify("bad-pc3-cert", "sslclient", [qw(root-cert)], [qw(pc1-cert ee-client ca-cert)],
"-allow_proxy_certs"),
"fail proxy cert with incorrect subject");
ok(!verify("bad-pc4-cert", "sslclient", [qw(root-cert)], [qw(pc1-cert ee-client ca-cert)],
"-allow_proxy_certs"),
"fail proxy cert with incorrect pathlen");
ok(verify("pc5-cert", "sslclient", [qw(root-cert)], [qw(pc1-cert ee-client ca-cert)],
"-allow_proxy_certs"),
"accept proxy cert missing proxy policy");
ok(!verify("pc6-cert", "sslclient", [qw(root-cert)], [qw(pc1-cert ee-client ca-cert)],
"-allow_proxy_certs"),
"failed proxy cert where last CN was added as a multivalue RDN component");
# Security level tests
ok(verify("ee-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
"accept RSA 2048 chain at auth level 2");
ok(!verify("ee-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "3"),
"reject RSA 2048 root at auth level 3");
ok(verify("ee-cert", "", ["root-cert-768"], ["ca-cert-768i"], "-auth_level", "0"),
"accept RSA 768 root at auth level 0");
ok(!verify("ee-cert", "", ["root-cert-768"], ["ca-cert-768i"]),
"reject RSA 768 root at auth level 1");
ok(verify("ee-cert-768i", "", ["root-cert"], ["ca-cert-768"], "-auth_level", "0"),
"accept RSA 768 intermediate at auth level 0");
ok(!verify("ee-cert-768i", "", ["root-cert"], ["ca-cert-768"]),
"reject RSA 768 intermediate at auth level 1");
ok(verify("ee-cert-768", "", ["root-cert"], ["ca-cert"], "-auth_level", "0"),
"accept RSA 768 leaf at auth level 0");
ok(!verify("ee-cert-768", "", ["root-cert"], ["ca-cert"]),
"reject RSA 768 leaf at auth level 1");
#
ok(verify("ee-cert", "", ["root-cert-md5"], ["ca-cert"], "-auth_level", "2"),
"accept md5 self-signed TA at auth level 2");
ok(verify("ee-cert", "", ["ca-cert-md5-any"], [], "-auth_level", "2"),
"accept md5 intermediate TA at auth level 2");
ok(verify("ee-cert", "", ["root-cert"], ["ca-cert-md5"], "-auth_level", "0"),
"accept md5 intermediate at auth level 0");
ok(!verify("ee-cert", "", ["root-cert"], ["ca-cert-md5"]),
"reject md5 intermediate at auth level 1");
ok(verify("ee-cert-md5", "", ["root-cert"], ["ca-cert"], "-auth_level", "0"),
"accept md5 leaf at auth level 0");
ok(!verify("ee-cert-md5", "", ["root-cert"], ["ca-cert"]),
"reject md5 leaf at auth level 1");
# Explicit vs named curve tests
SKIP: {
skip "EC is not supported by this OpenSSL build", 3
if disabled("ec");
ok(!verify("ee-cert-ec-explicit", "", ["root-cert"],
["ca-cert-ec-named"]),
"reject explicit curve leaf with named curve intermediate");
ok(!verify("ee-cert-ec-named-explicit", "", ["root-cert"],
["ca-cert-ec-explicit"]),
"reject named curve leaf with explicit curve intermediate");
ok(verify("ee-cert-ec-named-named", "", ["root-cert"],
["ca-cert-ec-named"]),
"accept named curve leaf with named curve intermediate");
}
# Same as above but with base provider used for decoding
SKIP: {
my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
my $provconf = srctop_file("test", "fips-and-base.cnf");
my $provpath = bldtop_dir("providers");
my @prov = ("-provider-path", $provpath);
skip "EC is not supported or FIPS is disabled", 3
if disabled("ec") || $no_fips;
run(test(["fips_version_test", "-config", $provconf, ">3.0.0"]),
capture => 1, statusvar => \my $exit);
skip "FIPS provider version is too old", 3
if !$exit;
$ENV{OPENSSL_CONF} = $provconf;
ok(!verify("ee-cert-ec-explicit", "", ["root-cert"],
["ca-cert-ec-named"], @prov),
"reject explicit curve leaf with named curve intermediate w/fips");
ok(!verify("ee-cert-ec-named-explicit", "", ["root-cert"],
["ca-cert-ec-explicit"], @prov),
"reject named curve leaf with explicit curve intermediate w/fips");
ok(verify("ee-cert-ec-named-named", "", ["root-cert"],
["ca-cert-ec-named"], @prov),
"accept named curve leaf with named curve intermediate w/fips");
delete $ENV{OPENSSL_CONF};
}
# Depth tests, note the depth limit bounds the number of CA certificates
# between the trust-anchor and the leaf, so, for example, with a root->ca->leaf
# chain, depth = 1 is sufficient, but depth == 0 is not.
#
ok(verify("ee-cert", "", ["root-cert"], ["ca-cert"], "-verify_depth", "2"),
"accept chain with verify_depth 2");
ok(verify("ee-cert", "", ["root-cert"], ["ca-cert"], "-verify_depth", "1"),
"accept chain with verify_depth 1");
ok(!verify("ee-cert", "", ["root-cert"], ["ca-cert"], "-verify_depth", "0"),
"reject chain with verify_depth 0");
ok(verify("ee-cert", "", ["ca-cert-md5-any"], [], "-verify_depth", "0"),
"accept md5 intermediate TA with verify_depth 0");
# Name Constraints tests.
ok(verify("alt1-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints everything permitted");
ok(verify("alt2-cert", "", ["root-cert"], ["ncca2-cert"], ),
"Name Constraints nothing excluded");
ok(verify("alt3-cert", "", ["root-cert"], ["ncca1-cert", "ncca3-cert"], ),
"Name Constraints nested test all permitted");
ok(verify("goodcn1-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints CNs permitted");
ok(verify("goodcn2-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints CNs permitted - no SAN extension");
ok(!verify("badcn1-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints CNs not permitted");
ok(!verify("badalt1-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints hostname not permitted");
ok(!verify("badalt2-cert", "", ["root-cert"], ["ncca2-cert"], ),
"Name Constraints hostname excluded");
ok(!verify("badalt3-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints email address not permitted");
ok(!verify("badalt4-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints subject email address not permitted");
ok(!verify("badalt5-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints IP address not permitted");
ok(!verify("badalt6-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints CN hostname not permitted");
ok(!verify("badalt7-cert", "", ["root-cert"], ["ncca1-cert"], ),
"Name Constraints CN BMPSTRING hostname not permitted");
ok(!verify("badalt8-cert", "", ["root-cert"], ["ncca1-cert", "ncca3-cert"], ),
"Name constraints nested DNS name not permitted 1");
ok(!verify("badalt9-cert", "", ["root-cert"], ["ncca1-cert", "ncca3-cert"], ),
"Name constraints nested DNS name not permitted 2");
ok(!verify("badalt10-cert", "", ["root-cert"], ["ncca1-cert", "ncca3-cert"], ),
"Name constraints nested DNS name excluded");
ok(!verify("bad-othername-cert", "", ["root-cert"], ["nccaothername-cert"], ),
"CVE-2022-4203 type confusion test");
#Check that we get the expected failure return code
with({ exit_checker => sub { return shift == 2; } },
sub {
ok(verify("bad-othername-namec", "", ["bad-othername-namec-inter"], [],
"-partial_chain", "-attime", "1623060000"),
"Name constraints bad othername name constraint");
});
ok(verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "0"),
"Accept PSS signature using SHA1 at auth level 0");
ok(verify("ee-pss-sha256-cert", "", ["root-cert"], ["ca-cert"], ),
"CA with PSS signature using SHA256");
ok(!verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "1"),
"Reject PSS signature using SHA1 and auth level 1");
ok(verify("ee-pss-sha256-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
"PSS signature using SHA256 and auth level 2");
ok(verify("ee-pss-cert", "", ["root-cert"], ["ca-pss-cert"], ),
"CA PSS signature");
ok(!verify("ee-pss-wrong1.5-cert", "", ["root-cert"], ["ca-pss-cert"], ),
"CA producing regular PKCS#1 v1.5 signature with PSA-PSS key");
ok(!verify("many-names1", "", ["many-constraints"], ["many-constraints"], ),
"Too many names and constraints to check (1)");
ok(!verify("many-names2", "", ["many-constraints"], ["many-constraints"], ),
"Too many names and constraints to check (2)");
ok(!verify("many-names3", "", ["many-constraints"], ["many-constraints"], ),
"Too many names and constraints to check (3)");
ok(verify("some-names1", "", ["many-constraints"], ["many-constraints"], ),
"Not too many names and constraints to check (1)");
ok(verify("some-names2", "", ["many-constraints"], ["many-constraints"], ),
"Not too many names and constraints to check (2)");
ok(verify("some-names2", "", ["many-constraints"], ["many-constraints"], ),
"Not too many names and constraints to check (3)");
ok(verify("root-cert-rsa2", "", ["root-cert-rsa2"], [], "-check_ss_sig"),
"Public Key Algorithm rsa instead of rsaEncryption");
ok(verify("ee-self-signed", "", ["ee-self-signed"], [], "-attime", "1593565200"),
"accept trusted self-signed EE cert excluding key usage keyCertSign");
ok(verify("ee-ss-with-keyCertSign", "", ["ee-ss-with-keyCertSign"], []),
"accept trusted self-signed EE cert with key usage keyCertSign also when strict");
SKIP: {
skip "Ed25519 is not supported by this OpenSSL build", 6
if disabled("ec");
# ED25519 certificate from draft-ietf-curdle-pkix-04
ok(verify("ee-ed25519", "", ["root-ed25519"], []),
"accept X25519 EE cert issued by trusted Ed25519 self-signed CA cert");
ok(!verify("ee-ed25519", "", ["root-ed25519"], [], "-x509_strict"),
"reject X25519 EE cert in strict mode since AKID is missing");
ok(!verify("root-ed25519", "", ["ee-ed25519"], []),
"fail Ed25519 CA and EE certs swapped");
ok(verify("root-ed25519", "", ["root-ed25519"], []),
"accept trusted Ed25519 self-signed CA cert");
ok(!verify("ee-ed25519", "", ["ee-ed25519"], []),
"fail trusted Ed25519-signed self-issued X25519 cert");
ok(verify("ee-ed25519", "", ["ee-ed25519"], [], "-partial_chain"),
"accept last-resort direct leaf match Ed25519-signed self-issued cert");
}
SKIP: {
skip "SM2 is not supported by this OpenSSL build", 2 if disabled("sm2");
ok_nofips(verify("sm2", "", ["sm2-ca-cert"], [], "-vfyopt", "distid:1234567812345678"),
"SM2 ID test");
ok_nofips(verify("sm2", "", ["sm2-ca-cert"], [], "-vfyopt", "hexdistid:31323334353637383132333435363738"),
"SM2 hex ID test");
}
# Mixed content tests
my $cert_file = srctop_file('test', 'certs', 'root-cert.pem');
my $rsa_file = srctop_file('test', 'certs', 'key-pass-12345.pem');
SKIP: {
my $certplusrsa_file = 'certplusrsa.pem';
my $certplusrsa;
skip "Couldn't create certplusrsa.pem", 1
unless ( open $certplusrsa, '>', $certplusrsa_file
and copy($cert_file, $certplusrsa)
and copy($rsa_file, $certplusrsa)
and close $certplusrsa );
ok(run(app([ qw(openssl verify -trusted), $certplusrsa_file, $cert_file ])),
'Mixed cert + key file test');
}
SKIP: {
my $rsapluscert_file = 'rsapluscert.pem';
my $rsapluscert;
skip "Couldn't create rsapluscert.pem", 1
unless ( open $rsapluscert, '>', $rsapluscert_file
and copy($rsa_file, $rsapluscert)
and copy($cert_file, $rsapluscert)
and close $rsapluscert );
ok(run(app([ qw(openssl verify -trusted), $rsapluscert_file, $cert_file ])),
'Mixed key + cert file test');
}
# Certificate Policies
ok(verify("ee-cert-policies", "", ["root-cert"], ["ca-pol-cert"],
"-policy_check", "-policy", "1.3.6.1.4.1.16604.998855.1",
"-explicit_policy"),
"Certificate policy");
ok(!verify("ee-cert-policies-bad", "", ["root-cert"], ["ca-pol-cert"],
"-policy_check", "-policy", "1.3.6.1.4.1.16604.998855.1",
"-explicit_policy"),
"Bad certificate policy");
diff --git a/crypto/openssl/test/recipes/30-test_evp_data/evpkdf_tls13_kdf.txt b/crypto/openssl/test/recipes/30-test_evp_data/evpkdf_tls13_kdf.txt
index 9ad8b9fbd2df..c7e7b4b5bf90 100644
--- a/crypto/openssl/test/recipes/30-test_evp_data/evpkdf_tls13_kdf.txt
+++ b/crypto/openssl/test/recipes/30-test_evp_data/evpkdf_tls13_kdf.txt
@@ -1,4937 +1,4947 @@
#
# Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
# Tests start with one of these keywords
# Cipher Decrypt Derive Digest Encoding KDF MAC PBE
# PrivPubKeyPair Sign Verify VerifyRecover
# and continue until a blank line. Lines starting with a pound sign are ignored.
Title = TLS 1.3 KDF tests (from ACVP test vectors)
# Each test suite simulates the steps in a TLS 1.3 session
# The output of each step is used as an input for the next. These were not
# generally included in the ACVP data and have been generated. The end to end
# correctness indicates that the intermediate values are okay.
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f8af6aea2d397baf2948a25b2834200692cff17eee9165e4e27babee9edefd05
Output = 153b6394a9c03cf3f5accc6e455a7693281138a1bcfa3803c26735dd1194d216
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:153b6394a9c03cf3f5accc6e455a7693281138a1bcfa3803c26735dd1194d216
Ctrl.data = hexdata:7c92f68bd5bf3638ea338a6494722e1b44127e1b7e8aad535f2322a644ff22b3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = c80583a90e995c489600492a5da642e6b1f679ba674828792df087b939636171
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:153b6394a9c03cf3f5accc6e455a7693281138a1bcfa3803c26735dd1194d216
Ctrl.data = hexdata:7c92f68bd5bf3638ea338a6494722e1b44127e1b7e8aad535f2322a644ff22b3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 1fe336ab43b4a69b11ebc64c8343ed21a9c7f6724702d9d63970e8ff72a4bde7
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8e27fad32236cb11bb497eb878d636c3f1599f5ffdfae784cbf73e74746769d4
Ctrl.salt = hexsalt:153b6394a9c03cf3f5accc6e455a7693281138a1bcfa3803c26735dd1194d216
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = cbb0740fd37e5eff32b76cf88511eb83fc9694da4130ca48de754c7f80f561bd
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:cbb0740fd37e5eff32b76cf88511eb83fc9694da4130ca48de754c7f80f561bd
Ctrl.data = hexdata:78d80b86fb9b089fb73375e51ae5bcfd742df4cadbd84dea0aaa0ac9d07ba6dc
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = c2451ee08fd221331f3dabada534393ed1fc8f5983afa251c1d004ec94e823a2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:cbb0740fd37e5eff32b76cf88511eb83fc9694da4130ca48de754c7f80f561bd
Ctrl.data = hexdata:78d80b86fb9b089fb73375e51ae5bcfd742df4cadbd84dea0aaa0ac9d07ba6dc
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 40eefbf66cb79c41c9ee1bf0be7f41696da165e7e69628ca8e342fee51827abd
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:cbb0740fd37e5eff32b76cf88511eb83fc9694da4130ca48de754c7f80f561bd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 9bdaae0c714cdbd47dd27dd7e37a1b4e5cf82fcaead2389cd71e6de12470ee17
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9bdaae0c714cdbd47dd27dd7e37a1b4e5cf82fcaead2389cd71e6de12470ee17
Ctrl.data = hexdata:fb3e78c3924a01fe4bf912bff8ddb120848ddf3e4b3cdd2cd661abbeff16a96e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = b162c65cdc0f9425aa7cd8fb30a821c8c8f0e8f8f9eb42209d10d784dafadcb5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9bdaae0c714cdbd47dd27dd7e37a1b4e5cf82fcaead2389cd71e6de12470ee17
Ctrl.data = hexdata:fb3e78c3924a01fe4bf912bff8ddb120848ddf3e4b3cdd2cd661abbeff16a96e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 6fe71fd9a81dffb3fecedd80c7a4801804116c79bc37b3605f54bc01a9cbed99
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9bdaae0c714cdbd47dd27dd7e37a1b4e5cf82fcaead2389cd71e6de12470ee17
Ctrl.data = hexdata:fb3e78c3924a01fe4bf912bff8ddb120848ddf3e4b3cdd2cd661abbeff16a96e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = eb1069417c771402a32b4797099adc449fd2be22ac47fb771ccd319e1a11ce55
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9bdaae0c714cdbd47dd27dd7e37a1b4e5cf82fcaead2389cd71e6de12470ee17
Ctrl.data = hexdata:db603b863e82a12147bd81a8e715d3273efe641d467436309e19ae0254461a35
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = b4face4931df0e3380830805af22055bf29b030988a9e278f7d04f2b00f323e8
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Output = 33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:ad5c61780c37f5dbe1666e846ffcbfe0694e6d7ee87fc855850cd961420a0da2
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 265aa1591dd7b8046d95580c5dec47f4f175cd3121afc066ab65b14c2ff2eeec
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:ad5c61780c37f5dbe1666e846ffcbfe0694e6d7ee87fc855850cd961420a0da2
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = dfeadee3e4cd8d260ae389043e5f806ea55ee332270487289abaf3933ec219ed
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8ba75a8cee15fe15599cec2d6590313ca4cf2efd7aed87a85ed4cbcbdc5edf9bb1
Ctrl.salt = hexsalt:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 7a6d31fe71da649e8e8168a42c5ab12c668f39499df77bc94405853530b85702
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7a6d31fe71da649e8e8168a42c5ab12c668f39499df77bc94405853530b85702
Ctrl.data = hexdata:fc732c631dec5b82edae0288d698f0ab1823128d73ee370864cc0edc69b1dd15
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = f1f7241a9c150b2a9e1e20f00ba42c038688468167201cae15a51f83ddd8520b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7a6d31fe71da649e8e8168a42c5ab12c668f39499df77bc94405853530b85702
Ctrl.data = hexdata:fc732c631dec5b82edae0288d698f0ab1823128d73ee370864cc0edc69b1dd15
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 38f88680f83f4cbc7afc2e58c7161076da181185009074b5f576c61643bc2e55
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:7a6d31fe71da649e8e8168a42c5ab12c668f39499df77bc94405853530b85702
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 160f1552154d4be73bcdbcea0dca9594c86b319cf3b052e1e8b080f0b0f128ce
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:160f1552154d4be73bcdbcea0dca9594c86b319cf3b052e1e8b080f0b0f128ce
Ctrl.data = hexdata:127da44d7325927afc7f81b2108b006dd843f05011f4ddb6408c82a0a11da070
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = e8634a48b7162c0c0d55afea28af35f06fcbbd268328bd6a9034b6fcddc48bb2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:160f1552154d4be73bcdbcea0dca9594c86b319cf3b052e1e8b080f0b0f128ce
Ctrl.data = hexdata:127da44d7325927afc7f81b2108b006dd843f05011f4ddb6408c82a0a11da070
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 1f5f7e35b4495e94f2b847129e246d98cc67d511729ed9ce60fa3c8176a7c41d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:160f1552154d4be73bcdbcea0dca9594c86b319cf3b052e1e8b080f0b0f128ce
Ctrl.data = hexdata:127da44d7325927afc7f81b2108b006dd843f05011f4ddb6408c82a0a11da070
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = ff76b85accc260ce264686e011c9ab08e955cd01943d8c03989ac060ea4ad12e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:160f1552154d4be73bcdbcea0dca9594c86b319cf3b052e1e8b080f0b0f128ce
Ctrl.data = hexdata:26872f541995715cbf7fcdd26544cfeff9fdff638578d166851127fb8a91ade7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 9d0a1aa3ed67e5bd066e61f15fdfd7a552bea57aed956af3f8b49abc2a9480b7
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Output = 33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:ab9a6fa58d1efd4d862d33e5fa1b610ef8af8b1c66d12f7871598e39b5540dcd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 22c60538c233cbabc8d14ca55fa7b264f4bf1eaa68ca7460be6f965edc2706bd
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:ab9a6fa58d1efd4d862d33e5fa1b610ef8af8b1c66d12f7871598e39b5540dcd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 04c9e7d5e5709d0d5e98cce5b8d995973427a2adb1e3d092c5418e520959d24c
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:079d4c92c73f842771e76173ffc79976499728b81e75ba77255d3f97a9b075b515
Ctrl.salt = hexsalt:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 18420b91716670f5330e9281ff0816663cb16de070ce6d0378fddbbf2e3d2284
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:18420b91716670f5330e9281ff0816663cb16de070ce6d0378fddbbf2e3d2284
Ctrl.data = hexdata:eb62d1f34a8aeb2a391e3f6d1e2f9f66e3053530551a41e94ba8f38068f273af
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 2f0e7afb326b06b482c82e5a775d65656ae653cd4f9c5527f9fea54c4872331d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:18420b91716670f5330e9281ff0816663cb16de070ce6d0378fddbbf2e3d2284
Ctrl.data = hexdata:eb62d1f34a8aeb2a391e3f6d1e2f9f66e3053530551a41e94ba8f38068f273af
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 4c0d8dff2bb81366bde630eb466479765acd151bd14da1ce5a313292ad2e7f3f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:18420b91716670f5330e9281ff0816663cb16de070ce6d0378fddbbf2e3d2284
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 8ead73c6e289e2f8a0615a95301d80a11801b6e7ae25d59dd13e6fe1b9b3d058
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8ead73c6e289e2f8a0615a95301d80a11801b6e7ae25d59dd13e6fe1b9b3d058
Ctrl.data = hexdata:ad53aca17f9e3c0fdd64cea888d106584b24e673a834b81f84acadcb5e93addb
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 21ecbb49c1013e3fb86e21600b2643bb22db2a5747d1d580b088ec545985750c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8ead73c6e289e2f8a0615a95301d80a11801b6e7ae25d59dd13e6fe1b9b3d058
Ctrl.data = hexdata:ad53aca17f9e3c0fdd64cea888d106584b24e673a834b81f84acadcb5e93addb
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 692ce960da75200ba64c0898172c383eba3e910f943e2dc6fb0ca5ea860dd128
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8ead73c6e289e2f8a0615a95301d80a11801b6e7ae25d59dd13e6fe1b9b3d058
Ctrl.data = hexdata:ad53aca17f9e3c0fdd64cea888d106584b24e673a834b81f84acadcb5e93addb
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 414267573db54653b960060e78f24efbbe0e6eb3bba77f8a1330c52ce748cea9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8ead73c6e289e2f8a0615a95301d80a11801b6e7ae25d59dd13e6fe1b9b3d058
Ctrl.data = hexdata:2cf39c1d072fe6ca2e9385b5deb93f6706ca97c4cecd7141968ae9f92d1b331d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 71afefcc45ef6cf641320fd33c0711fce1b177f2de278a3009a423c013eb156e
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Output = 33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:0ba5fc85501734dc78cea66aacc3b2fa36be938b34b10037e842dc6ff493560d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = bcb5dab7001fb36b9877b3cc53c92157de4a4a304be8ce1ae8a49b71b5cf5384
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:0ba5fc85501734dc78cea66aacc3b2fa36be938b34b10037e842dc6ff493560d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = efc512b05a887d11ed829bdf90162ace73456c83a6543d74ef95f98022b6162c
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:51b7a0a74de27eed1bc77a0691850387f4bfbaafef1033780d027fb0a00d1ba957
Ctrl.salt = hexsalt:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = bb6ebdf3a3790704ba46b29277e0f699cc8d4eb0320c922c4537e3d2897dda7b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bb6ebdf3a3790704ba46b29277e0f699cc8d4eb0320c922c4537e3d2897dda7b
Ctrl.data = hexdata:9d3b6a05267ca141c132ae2685bba0b8eb27d8b4349af822607bf4c215070d2e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 7c318f397dd56ec69c7ab5eafde196c06aefccaf24fb2487e045b55f8d5865dc
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bb6ebdf3a3790704ba46b29277e0f699cc8d4eb0320c922c4537e3d2897dda7b
Ctrl.data = hexdata:9d3b6a05267ca141c132ae2685bba0b8eb27d8b4349af822607bf4c215070d2e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = f9b5e2e18869a920128dad1c836d57deacaa85cfec21012823a52182cb5484fc
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:bb6ebdf3a3790704ba46b29277e0f699cc8d4eb0320c922c4537e3d2897dda7b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 71e002695a3a5e8899ef4a705462505eb0ec33f9e3214a668d739eeca833e1ba
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:71e002695a3a5e8899ef4a705462505eb0ec33f9e3214a668d739eeca833e1ba
Ctrl.data = hexdata:cdb5539c16d3b95ca0c30abd03d11f78175f63768a79c7dd2a5f4ee72d93f7a8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 7b48562a81323355b3c090d59b8adbb6aaf17b8489448d3d20bee397523ef0ac
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:71e002695a3a5e8899ef4a705462505eb0ec33f9e3214a668d739eeca833e1ba
Ctrl.data = hexdata:cdb5539c16d3b95ca0c30abd03d11f78175f63768a79c7dd2a5f4ee72d93f7a8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 19c59876c3f79fad0f66e3038ef2126ff1f0167a15d8fe10901671fbdb7aca9e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:71e002695a3a5e8899ef4a705462505eb0ec33f9e3214a668d739eeca833e1ba
Ctrl.data = hexdata:cdb5539c16d3b95ca0c30abd03d11f78175f63768a79c7dd2a5f4ee72d93f7a8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = a41b62871f071de5536da378f4b88071dd9839b367065e84da932e45a6b155e6
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:71e002695a3a5e8899ef4a705462505eb0ec33f9e3214a668d739eeca833e1ba
Ctrl.data = hexdata:40248b70ecbe954e7b825281e052f5d1f784678f02c1574f91034c09fa5b4f91
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = c27da667ff071ee5907d272d0f26cb204af7df95895670a96c8441bcc9433c6c
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Output = 33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:1db79ad32111ded07970f5a4958d60deaaea16c9364d72fd97f1b9d2eb4389f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 9988ba03ffa2aa8f8332efc47051278dd4831bb2b2231010b49354f23a14fcc2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:1db79ad32111ded07970f5a4958d60deaaea16c9364d72fd97f1b9d2eb4389f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 332e88ff7e3b1b3e592a89b3151bb79a418f5db6dff522a73ff53bc7e237777e
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:6d42939374a8adf6d3d96bf450eece38f2d0268814262f9780acf5b6769582b0aa
Ctrl.salt = hexsalt:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = ab43c87709e09c9acbdaad583da6fe1e8e6756a43fddf59382113981a33621b1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:ab43c87709e09c9acbdaad583da6fe1e8e6756a43fddf59382113981a33621b1
Ctrl.data = hexdata:782580319c405ffabb7c272f730a4d0c06da94923f49fc8194e86c91b339cd0f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 60822aa502f3065ec3972e5dba90f14b254544f99d3274cd67fa3565e5e78f11
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:ab43c87709e09c9acbdaad583da6fe1e8e6756a43fddf59382113981a33621b1
Ctrl.data = hexdata:782580319c405ffabb7c272f730a4d0c06da94923f49fc8194e86c91b339cd0f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 4534439181f03ed7c34471c0b2cd59a064402a6cb8092f5e30dfe3db4ce29c65
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:ab43c87709e09c9acbdaad583da6fe1e8e6756a43fddf59382113981a33621b1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = bdc1b213a768dc7302f236094affb53ee401f6420f6f9730f9e5638600119c96
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bdc1b213a768dc7302f236094affb53ee401f6420f6f9730f9e5638600119c96
Ctrl.data = hexdata:87815c0c6533c20ce2a749d15be7f5e5efcb01a9d66ff0c1eaf9317a35f78c0a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 1fa11fda9fc1840f2082a9a81b9212bca08915c8402f5d9d3e6403df529a6872
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bdc1b213a768dc7302f236094affb53ee401f6420f6f9730f9e5638600119c96
Ctrl.data = hexdata:87815c0c6533c20ce2a749d15be7f5e5efcb01a9d66ff0c1eaf9317a35f78c0a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 5d3b814a5ea0b320dc2d6b0d50f766013073e92203184ea6f990f3a23ba1b936
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bdc1b213a768dc7302f236094affb53ee401f6420f6f9730f9e5638600119c96
Ctrl.data = hexdata:87815c0c6533c20ce2a749d15be7f5e5efcb01a9d66ff0c1eaf9317a35f78c0a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 12c9b8c8b42467ccfb6161cafda1027212c59782891fc9f4b43e68f66a6ff0be
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bdc1b213a768dc7302f236094affb53ee401f6420f6f9730f9e5638600119c96
Ctrl.data = hexdata:7d3160a347ba24ed246af7287f60a64cebe1678aa3055958693c1189f9ae45b8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = b39060999fb0e2319294654c6ddf17c6375e25d5e44da3d00474aba66384f961
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Output = 33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:491d9ca9cd0d5c8ddef62cd87b9ee6e934ec66191b22667447544355ae5903d5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 659f7cc8a36d4efcea9bb1dbe7d0723b968a7a78eb80d18966afb24fabdb86a2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.data = hexdata:491d9ca9cd0d5c8ddef62cd87b9ee6e934ec66191b22667447544355ae5903d5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 292bcf6dd3c94e79d2ac4bd4de158f0bedb7416591e87a911ea4034ba6da7a7c
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8bed9e790b96b98846068b237082f9c0c0e53af3bea98bdda5f1a079448775ab6d
Ctrl.salt = hexsalt:33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 9aed3d26bbdc6406c1262928224052a9e9e68f64dbc3a159f41b6644dccf81d0
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9aed3d26bbdc6406c1262928224052a9e9e68f64dbc3a159f41b6644dccf81d0
Ctrl.data = hexdata:b969708ab3a1b1b1b87f228a49d37df58a367064a6bccec689a475dc5edda812
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 7b4d547ba11886f439c6d53b1e65b09aff3f1fea4fb8628962a546013fd53bbc
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9aed3d26bbdc6406c1262928224052a9e9e68f64dbc3a159f41b6644dccf81d0
Ctrl.data = hexdata:b969708ab3a1b1b1b87f228a49d37df58a367064a6bccec689a475dc5edda812
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = cdb6b0be56d99c2a9a9c201a4b62b27df40877b228ba085fd0d06a5489545595
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:9aed3d26bbdc6406c1262928224052a9e9e68f64dbc3a159f41b6644dccf81d0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = c54b82100787f03b666cbb04d34bd894911346cc6c39266971a5de5f99fdb7bb
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c54b82100787f03b666cbb04d34bd894911346cc6c39266971a5de5f99fdb7bb
Ctrl.data = hexdata:129524eaf21476767f2f14c3ec038f7fadb38f0c35645391b41b218729a1a9da
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = f2a8f833af1dc5db36b842769955d97db05d3bd5014ca9c9fa301e8ac6214ebe
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c54b82100787f03b666cbb04d34bd894911346cc6c39266971a5de5f99fdb7bb
Ctrl.data = hexdata:129524eaf21476767f2f14c3ec038f7fadb38f0c35645391b41b218729a1a9da
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 1ac34b3063a496f7be40f83e01055a97a0899c9a0484121df5f11ce25d9ca426
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c54b82100787f03b666cbb04d34bd894911346cc6c39266971a5de5f99fdb7bb
Ctrl.data = hexdata:129524eaf21476767f2f14c3ec038f7fadb38f0c35645391b41b218729a1a9da
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 58374f792176371d434f9866ba8958fab9eced9edc0a4d7a787798ded90fa9b7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c54b82100787f03b666cbb04d34bd894911346cc6c39266971a5de5f99fdb7bb
Ctrl.data = hexdata:3279a4e27fc27a69208764df2fc0de77e3d9c73dd971b368b8d0a32536a6f8bb
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 1aff1cdf216ba86913a3d191159de6869490ca94e79da7fbc6173643c87d407a
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:b6d0a81fd3c91c1970a2d85ed695fba34143ae0fea07bc7c8653ad4830c905db
Output = 94374db506b58237defb8b1d7fd10c17440ea9c46380d00e22fdb879fbfe2cbc
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:94374db506b58237defb8b1d7fd10c17440ea9c46380d00e22fdb879fbfe2cbc
Ctrl.data = hexdata:47afa605ef0002b533bedbc155030e2b96c1d8d20d410dc44ce37dd94c8cb1e3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 122a73631c397d888895544f34925464a3d6983cdf647d6e23b050d140af1273
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:94374db506b58237defb8b1d7fd10c17440ea9c46380d00e22fdb879fbfe2cbc
Ctrl.data = hexdata:47afa605ef0002b533bedbc155030e2b96c1d8d20d410dc44ce37dd94c8cb1e3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 0bb4c7419f9a02f9eb52ab21886b20b7be6ae8223db2e67c50d5d3461ec9b936
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:d36680e32c17596202cbf2765472708cb5bc41399b2c9d7cf1c88ca219e7a1ee
Ctrl.salt = hexsalt:94374db506b58237defb8b1d7fd10c17440ea9c46380d00e22fdb879fbfe2cbc
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = e6d83b5c15773dd227c4f4506bf6584ae196d28153dec17aec2142077b4d1ae3
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:e6d83b5c15773dd227c4f4506bf6584ae196d28153dec17aec2142077b4d1ae3
Ctrl.data = hexdata:c724c6137e799c69850f94ccbe089b07896d44cc7845fcf07cfea716176cc0f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 0de142b91cfda627b365dab23e69ad00edb0085b33076052cf5f7f0ec735abc8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:e6d83b5c15773dd227c4f4506bf6584ae196d28153dec17aec2142077b4d1ae3
Ctrl.data = hexdata:c724c6137e799c69850f94ccbe089b07896d44cc7845fcf07cfea716176cc0f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = abdeed5d5f41fb963e1a136ac914aa35617c3cd19a56b1c975f27656b967db89
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:e6d83b5c15773dd227c4f4506bf6584ae196d28153dec17aec2142077b4d1ae3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 7eace69e348057e83a83a877a4920daa9fb4c7fbfe897600f29d9496424d5129
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7eace69e348057e83a83a877a4920daa9fb4c7fbfe897600f29d9496424d5129
Ctrl.data = hexdata:6550c34750ff90a4e62391d53b2cb45650380f018845cb63a399516a66681fc3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = d4e9ecf730820bf96846489a1b717af11cf498f7b0a2a779a4064996597cb97b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7eace69e348057e83a83a877a4920daa9fb4c7fbfe897600f29d9496424d5129
Ctrl.data = hexdata:6550c34750ff90a4e62391d53b2cb45650380f018845cb63a399516a66681fc3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 6d9189f42b5cc41f50c26ada399521e2e3a79f9d8764f00e76e6bce962169cc8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7eace69e348057e83a83a877a4920daa9fb4c7fbfe897600f29d9496424d5129
Ctrl.data = hexdata:6550c34750ff90a4e62391d53b2cb45650380f018845cb63a399516a66681fc3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 3998b7178fef3a48ce434d8ead4b09f136dc2f900218dcfcbe7321bc9ce4ec4b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7eace69e348057e83a83a877a4920daa9fb4c7fbfe897600f29d9496424d5129
Ctrl.data = hexdata:e8a32347070a957786be61942a657b1e51ef0a37591e4d69e4c1362033ced9f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = c3112140c8aed04d114af73b6f245fafdc0c7ff4661ad6252cc754b9afb5b59a
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:89f7a556f3c19a2833b3313868dc11f5728880fb3ac74eb142042bd5e951a1a6
Output = 7f9c0864adf9769f2f362f239121b620f2a0bfc4e2898e8cc1f05e11517ceac5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7f9c0864adf9769f2f362f239121b620f2a0bfc4e2898e8cc1f05e11517ceac5
Ctrl.data = hexdata:fb6e2fffef563561a53b0cbd6b93da78597fd7127f03069b1e724312e0f1a49f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 97cddc9e02e8a54646e1d3cd1018185d93bd76743a64cef03fef3bc1305db4cc
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7f9c0864adf9769f2f362f239121b620f2a0bfc4e2898e8cc1f05e11517ceac5
Ctrl.data = hexdata:fb6e2fffef563561a53b0cbd6b93da78597fd7127f03069b1e724312e0f1a49f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = b78c86ab545bd86e890359a2c0bf695c95dec4e3207ad7c110372153328641ae
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:0cec10693bc11dee75ca5e1d06cb42abba7d1d76762f7400f323b1c191e7e745
Ctrl.salt = hexsalt:7f9c0864adf9769f2f362f239121b620f2a0bfc4e2898e8cc1f05e11517ceac5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 1e88503eafb7a8e5d37d4d05c2d11a7b2a41b139c321eaf72aa33e155c815aee
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:1e88503eafb7a8e5d37d4d05c2d11a7b2a41b139c321eaf72aa33e155c815aee
Ctrl.data = hexdata:6f71510b9e2d8ef93dbdb4523bee6649f2066dbe9f8b0c1d3b8295b0c70f75e1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 8f4432e28701a3491742a5588ab506ef378d2ee46dcb9df3c2b8f1161638226a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:1e88503eafb7a8e5d37d4d05c2d11a7b2a41b139c321eaf72aa33e155c815aee
Ctrl.data = hexdata:6f71510b9e2d8ef93dbdb4523bee6649f2066dbe9f8b0c1d3b8295b0c70f75e1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 62ddaed76a7bc9aa623a10176e180333bf50e2d436ab9d6df2e6327c3934b0aa
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:1e88503eafb7a8e5d37d4d05c2d11a7b2a41b139c321eaf72aa33e155c815aee
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = f167151ca3b7e09230e2b19b35d5eb94ac185bcd11718bf3fa7b4ad9b13c50d8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f167151ca3b7e09230e2b19b35d5eb94ac185bcd11718bf3fa7b4ad9b13c50d8
Ctrl.data = hexdata:daf66774a6c5575457a3c4d8fd127fbcaeae1a95b518be04955dced1f14861de
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 5a25fbebbb09a70ee782337a601f6e86e7a77cdfe980c90d2e2acf48a2426c8b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f167151ca3b7e09230e2b19b35d5eb94ac185bcd11718bf3fa7b4ad9b13c50d8
Ctrl.data = hexdata:daf66774a6c5575457a3c4d8fd127fbcaeae1a95b518be04955dced1f14861de
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 495df78c999d00de7c410c8e964df0dbf9192231bbe1b06880b13a0dafee1003
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f167151ca3b7e09230e2b19b35d5eb94ac185bcd11718bf3fa7b4ad9b13c50d8
Ctrl.data = hexdata:daf66774a6c5575457a3c4d8fd127fbcaeae1a95b518be04955dced1f14861de
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = d39992ac1cfbe2715b1b95affff6e23934121d3b0b54685f668f5c4473f36f1d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f167151ca3b7e09230e2b19b35d5eb94ac185bcd11718bf3fa7b4ad9b13c50d8
Ctrl.data = hexdata:77100f9b44422180a922b28ef83701c5ac19fdc3aea8e4f966840f9fa3c893eb
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 928104946f6338386e8ac29c6a9b16453fa8c96ee18e7dd9e2f4091cd5399f91
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:90f8ba43a34bffd93495f3d854c84594e0daf85d9468b35c4dcf44a80eb31718
Output = c7222ce686f8f5ae6580fe79f05591187b9238eb9884828074c2d2af274a07d5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c7222ce686f8f5ae6580fe79f05591187b9238eb9884828074c2d2af274a07d5
Ctrl.data = hexdata:218aa61bd49bc0f7ad65332ad4bb18015d3e646cacfdc72f710c9efbe01979a9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = fd0edb84e6742a9f33892c91e7fc9fe59d932c7677ab3627ede5b15991a607ec
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c7222ce686f8f5ae6580fe79f05591187b9238eb9884828074c2d2af274a07d5
Ctrl.data = hexdata:218aa61bd49bc0f7ad65332ad4bb18015d3e646cacfdc72f710c9efbe01979a9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 25a8973e89c3f3eb3f1394df0f62ee66a7003c794876473c2cc800f7cf4c11fb
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a2092cf8a9357e82253844c9f563385e8d44b89d960a7b2fffbc8d697fdcb057
Ctrl.salt = hexsalt:c7222ce686f8f5ae6580fe79f05591187b9238eb9884828074c2d2af274a07d5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 917c83ffd6a51b4ec8682d215b683a4c1025180779b2d4af6321ea63a9c7abaf
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:917c83ffd6a51b4ec8682d215b683a4c1025180779b2d4af6321ea63a9c7abaf
Ctrl.data = hexdata:bfe3f121ae6e973c2b58a7ab40295212387146eeec3d3c5764a320de2c37051f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = a2861ceecd2842fac7245facc65f6b13145635eaaabd2c3a02db6b20b91f9d38
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:917c83ffd6a51b4ec8682d215b683a4c1025180779b2d4af6321ea63a9c7abaf
Ctrl.data = hexdata:bfe3f121ae6e973c2b58a7ab40295212387146eeec3d3c5764a320de2c37051f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 3b74970ceec49ff0aa043603487194c7c42f4e31ac4aab661f9056c8000afa25
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:917c83ffd6a51b4ec8682d215b683a4c1025180779b2d4af6321ea63a9c7abaf
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 67acff590a7ff60cf452d56a9824f8e8831f0b401b4e9968f7f715c73374d1af
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:67acff590a7ff60cf452d56a9824f8e8831f0b401b4e9968f7f715c73374d1af
Ctrl.data = hexdata:35f9b9be0850baa1016762d63005ea679c47971932f7141038ae009a904cf7f9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = c10c35faa34fc917cf0acb280fdb0c3ac513d5c86f418a99e5590d40ccb8fcb9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:67acff590a7ff60cf452d56a9824f8e8831f0b401b4e9968f7f715c73374d1af
Ctrl.data = hexdata:35f9b9be0850baa1016762d63005ea679c47971932f7141038ae009a904cf7f9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = f0ac9ca472ab7587b074d59824a5daec75d613da9b168a2589bbbdcd76c51976
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:67acff590a7ff60cf452d56a9824f8e8831f0b401b4e9968f7f715c73374d1af
Ctrl.data = hexdata:35f9b9be0850baa1016762d63005ea679c47971932f7141038ae009a904cf7f9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 5e8deab072f10d9c8ffdcda58b93ea5a61f11cf72ca0647118164a2a7fa03a08
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:67acff590a7ff60cf452d56a9824f8e8831f0b401b4e9968f7f715c73374d1af
Ctrl.data = hexdata:b8d1e9993b45dfda130aa77c5319074806042cb4aad1b505bedb951a40cf2003
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 6cf8a005b4b453cc982f4707dc64bc3dc8d00602aebd5f85413f4d405e656851
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bd1eead608338b0308e4243325a02b350ef6eb5e5fae728fd73f3f9a02c3d515
Output = c67ac5e381b0bdc51b8dc7891f581882a2b83408e6f7cdc36a6245cc2797270c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c67ac5e381b0bdc51b8dc7891f581882a2b83408e6f7cdc36a6245cc2797270c
Ctrl.data = hexdata:eaa65a5ab61073c13c86d5d4dc97dba62c746b6d63f4e09014d157223daf2a0e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 308ecfa294dec305f736df30570315d28b63b6c72507c1ce14c4f51441982e63
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c67ac5e381b0bdc51b8dc7891f581882a2b83408e6f7cdc36a6245cc2797270c
Ctrl.data = hexdata:eaa65a5ab61073c13c86d5d4dc97dba62c746b6d63f4e09014d157223daf2a0e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = a41017b7a9ef987dc543e52539688cfc74bb95094693ecf6d9a1724f78ba6403
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a501370b0ffebbf0f115b367ed21f6d8816b10282a2724cb480993583f64f787
Ctrl.salt = hexsalt:c67ac5e381b0bdc51b8dc7891f581882a2b83408e6f7cdc36a6245cc2797270c
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 6698bc4d53decbb95a8912dea1332c67f83a1f1fb077701bee15ead22054bc53
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:6698bc4d53decbb95a8912dea1332c67f83a1f1fb077701bee15ead22054bc53
Ctrl.data = hexdata:ebbe1a77c63580e02ff7b51438c736a955326403640edfbdb1812097b57c2fb4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = f2bed07ad9d2efd2718fb4da4a9dc90fa1dc40440b98c5291377beca16dc6599
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:6698bc4d53decbb95a8912dea1332c67f83a1f1fb077701bee15ead22054bc53
Ctrl.data = hexdata:ebbe1a77c63580e02ff7b51438c736a955326403640edfbdb1812097b57c2fb4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = f47f4524fd86c43d2c4c1618b03492f8bbcc3bdc1b8c8b97b4ec18581dc13f8e
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:6698bc4d53decbb95a8912dea1332c67f83a1f1fb077701bee15ead22054bc53
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 55042c631e7e5e78a6afca32f09741a93d987e55de8213bf8418546c5b40be8a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:55042c631e7e5e78a6afca32f09741a93d987e55de8213bf8418546c5b40be8a
Ctrl.data = hexdata:af6d979bb4e54e8a1cec24983efd7d72deccbf8d6bd137a9a95b94c70cceb335
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 64e2482febc65460e45d3b9dad2fa847ba2ec91737225920fa4d0afb83ac4558
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:55042c631e7e5e78a6afca32f09741a93d987e55de8213bf8418546c5b40be8a
Ctrl.data = hexdata:af6d979bb4e54e8a1cec24983efd7d72deccbf8d6bd137a9a95b94c70cceb335
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 902dcd1e49c7facf55ce6dbedab06f7265a092418a235df019102b4265d648d2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:55042c631e7e5e78a6afca32f09741a93d987e55de8213bf8418546c5b40be8a
Ctrl.data = hexdata:af6d979bb4e54e8a1cec24983efd7d72deccbf8d6bd137a9a95b94c70cceb335
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = e168010de64b519d0cf575dbf267590c03b45782d875e10e193be95366d450cd
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:55042c631e7e5e78a6afca32f09741a93d987e55de8213bf8418546c5b40be8a
Ctrl.data = hexdata:0fe329b7ebec20e21a6322f657702873afb4a52dab88f7484c9cfbfd3b1c1105
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 815929e43c3624dccc01db4adfd97f0fea124ff83bfe79cfd0aa76f91e36d9ea
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:47a2f1ed109d1ed2e7a31288312da8930e8f3445c98b6a8862da85ae07507bc6
Output = 1d08642939bbb7369d15c7a1d022ed05ec030321bd953593fabd43a8703b096b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:1d08642939bbb7369d15c7a1d022ed05ec030321bd953593fabd43a8703b096b
Ctrl.data = hexdata:31748082bf14950d21b4a0759143bb70474cb1c231cd91764d5bd241de984842
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 7b57c9475d089b4798340fec63fe876f9fd1214cf0947c8779d0f4952f6aa9c7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:1d08642939bbb7369d15c7a1d022ed05ec030321bd953593fabd43a8703b096b
Ctrl.data = hexdata:31748082bf14950d21b4a0759143bb70474cb1c231cd91764d5bd241de984842
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 0f0790d9d50286db6cb769f3b6c1ca72a8a9597176ff8c79d8969aa38be74215
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9674cae88f3468d7b34df9bd2c348b99f1a964d7ed2bd5340edae2c9c96399db
Ctrl.salt = hexsalt:1d08642939bbb7369d15c7a1d022ed05ec030321bd953593fabd43a8703b096b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = cd332e44da2306e3d3812f7f55171c50f7d8ad1bc57f7e758b452e51163bdf0c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:cd332e44da2306e3d3812f7f55171c50f7d8ad1bc57f7e758b452e51163bdf0c
Ctrl.data = hexdata:6db5315252802b3132297f0c49983ad9b406bacbb256bac50189a44055bd1819
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = b0beb402fbbd33be12a60927c160210f0343c31143945d0320d0337ed1466aa7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:cd332e44da2306e3d3812f7f55171c50f7d8ad1bc57f7e758b452e51163bdf0c
Ctrl.data = hexdata:6db5315252802b3132297f0c49983ad9b406bacbb256bac50189a44055bd1819
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 09bf60f0d825d1fa6696e0d52b93dd40cc1087bdeade1eb0970f55bd4cbe85fc
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:cd332e44da2306e3d3812f7f55171c50f7d8ad1bc57f7e758b452e51163bdf0c
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 8a1bf9169726cc39cd9f1496ae22a68d5407924d53d6003b41d6fd551566295c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8a1bf9169726cc39cd9f1496ae22a68d5407924d53d6003b41d6fd551566295c
Ctrl.data = hexdata:7ebc29c29c002f5ea3f80283a1919ee7689424c35be6637c86666d0a843bac2e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = a5150664aec6f4600ee21c9285943f26427e399a7d348fcd291ac804527be921
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8a1bf9169726cc39cd9f1496ae22a68d5407924d53d6003b41d6fd551566295c
Ctrl.data = hexdata:7ebc29c29c002f5ea3f80283a1919ee7689424c35be6637c86666d0a843bac2e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 695dedb2a8762a90ec40ea1c6c1cbd592b0106a7833df9a4d07cd108e62039bd
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8a1bf9169726cc39cd9f1496ae22a68d5407924d53d6003b41d6fd551566295c
Ctrl.data = hexdata:7ebc29c29c002f5ea3f80283a1919ee7689424c35be6637c86666d0a843bac2e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 389d8adce83b1b0aa6574155e62c22d999b43babb388d9223c0ed9f1fe458084
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:8a1bf9169726cc39cd9f1496ae22a68d5407924d53d6003b41d6fd551566295c
Ctrl.data = hexdata:9a38f4bc144df26d362f0249ed9a47ed0d29c2c40e566d0a688584303dcc79eb
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 4ba917b3adcbc372aa431bef94a44a4afa1b528ce9278aeb79a9bd35885ad745
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c4c9a0266ed3b657058cb9674c530247a09b660954cc26b888a2d56e579fcbd82ef6
Output = 3780287d1e1d2c16b1971dafc255c414e7523694a94c45f2faa3dc0f6519e222
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3780287d1e1d2c16b1971dafc255c414e7523694a94c45f2faa3dc0f6519e222
Ctrl.data = hexdata:b10c0c2d6a38f88c89be8f5e7a37da9d7fda20b021ccab52a1eccaa722f64691
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 08a4b77232d0c46ff57fd77306a2ed3edf0f10272525532fb69ad88c7d01a785
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3780287d1e1d2c16b1971dafc255c414e7523694a94c45f2faa3dc0f6519e222
Ctrl.data = hexdata:b10c0c2d6a38f88c89be8f5e7a37da9d7fda20b021ccab52a1eccaa722f64691
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 2b7574a39cdcebe3f0fc50a42422cd227d72164203661ad3ab0146220c51d638
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:3780287d1e1d2c16b1971dafc255c414e7523694a94c45f2faa3dc0f6519e222
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = bc7ce3027cd67bbf366c78e07023f2efedab1e021366a3bdf7e8f0331de1113c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bc7ce3027cd67bbf366c78e07023f2efedab1e021366a3bdf7e8f0331de1113c
Ctrl.data = hexdata:6a593ba39e4ea72392a7fc4198d56c01dd25094c808f9dc8f7ed39e808dd1e58
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 3c808386d173aa3edad8e0eb9e9bbec629d5a00d3503f1a524aa75c7e8ff4002
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bc7ce3027cd67bbf366c78e07023f2efedab1e021366a3bdf7e8f0331de1113c
Ctrl.data = hexdata:6a593ba39e4ea72392a7fc4198d56c01dd25094c808f9dc8f7ed39e808dd1e58
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = db33c5ae5c8b525ebfa000d5446c62a4b2469da9faa913c0694f154371e2c16b
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:bc7ce3027cd67bbf366c78e07023f2efedab1e021366a3bdf7e8f0331de1113c
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 5d151d7f20547939c3fa2c3c1a25a7b5f43c2d9e077e387816a23789589f4d8e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d151d7f20547939c3fa2c3c1a25a7b5f43c2d9e077e387816a23789589f4d8e
Ctrl.data = hexdata:375373bbfd7dc61d49f8b987b537808c79e673202f0825518d9c2f3e9973360a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 8885938e3e4be164c56aa53c52695ba4739c6fabdb51a9ab2b35423ebeec2416
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d151d7f20547939c3fa2c3c1a25a7b5f43c2d9e077e387816a23789589f4d8e
Ctrl.data = hexdata:375373bbfd7dc61d49f8b987b537808c79e673202f0825518d9c2f3e9973360a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 3e7d7c5f9ac3a184715ed7a45d68da393cf07a297456849ec671e1a3b29e1dce
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d151d7f20547939c3fa2c3c1a25a7b5f43c2d9e077e387816a23789589f4d8e
Ctrl.data = hexdata:375373bbfd7dc61d49f8b987b537808c79e673202f0825518d9c2f3e9973360a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 86e5c6fd2304433f8532a1f863716fc09022346a2f76e2d52fe03f8294fff882
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d151d7f20547939c3fa2c3c1a25a7b5f43c2d9e077e387816a23789589f4d8e
Ctrl.data = hexdata:1a06ef15e61cb724a2f84f51c9ba466877261e5597858adda4f461d8cb5352ef
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 426b2739c854867d4ea7b560092786a4601648d35505ad8040cf67b5978a5f25
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:925f595de96572a2e8c35346d9beeca43329f3a66c96168d50588f4e262ed01c66f2
Output = 3a03d61dec9a96667ac5aeae6d904eb87bf7f60362ca7c19eefc9c9d4466189d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3a03d61dec9a96667ac5aeae6d904eb87bf7f60362ca7c19eefc9c9d4466189d
Ctrl.data = hexdata:4abf7521447134215ad896ca371e0cee966c0d7fb152b98ca4bc872dcaba37b9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 7450f33c7ba624e4151bc8230df0a7163c164f863801949102d4e9715e4813f9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3a03d61dec9a96667ac5aeae6d904eb87bf7f60362ca7c19eefc9c9d4466189d
Ctrl.data = hexdata:4abf7521447134215ad896ca371e0cee966c0d7fb152b98ca4bc872dcaba37b9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = c6047f5c4eed302b627d1f10bac575db43a29e20a4fdfec20975c8e63a410205
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:3a03d61dec9a96667ac5aeae6d904eb87bf7f60362ca7c19eefc9c9d4466189d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 7a8ac221aa898261e625b7a88a964136e8522d100fca2d57d385a1a324670f73
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7a8ac221aa898261e625b7a88a964136e8522d100fca2d57d385a1a324670f73
Ctrl.data = hexdata:574d667be4aa6d090fb0bfd15eca6188004a2216969fb69768b786e1dae03978
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = cce2f4cf5dc234c4c2366488a8ea141a5be0ec1ef1418aafec947c08d37325b6
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7a8ac221aa898261e625b7a88a964136e8522d100fca2d57d385a1a324670f73
Ctrl.data = hexdata:574d667be4aa6d090fb0bfd15eca6188004a2216969fb69768b786e1dae03978
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 2a3c42a2125c21a7bdfb1902dbc5ab3df1cee0d496472c841751128b4f6ba7ea
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:7a8ac221aa898261e625b7a88a964136e8522d100fca2d57d385a1a324670f73
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = a5c4c6c92cae6d1f1bf65382b8aa396097587b6053ebfb30392e8a9e2095a3b4
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a5c4c6c92cae6d1f1bf65382b8aa396097587b6053ebfb30392e8a9e2095a3b4
Ctrl.data = hexdata:fc47a64ea7d238286e710775efb6fd4e6cc52238f956723f997c0c1a5d97c982
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = efd8f8e08644e81b8a2068d59bf4957da16f376dcce547d485f35158ed934463
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a5c4c6c92cae6d1f1bf65382b8aa396097587b6053ebfb30392e8a9e2095a3b4
Ctrl.data = hexdata:fc47a64ea7d238286e710775efb6fd4e6cc52238f956723f997c0c1a5d97c982
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 1ec28e0fdb42e283058c3cb093b64b2a51f25f309f6903736de591cb730b0d59
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a5c4c6c92cae6d1f1bf65382b8aa396097587b6053ebfb30392e8a9e2095a3b4
Ctrl.data = hexdata:fc47a64ea7d238286e710775efb6fd4e6cc52238f956723f997c0c1a5d97c982
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 1cd2d315b8720a771f7b8d84ee19704193a3ad7f903d62561d51318fda4ef8e2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a5c4c6c92cae6d1f1bf65382b8aa396097587b6053ebfb30392e8a9e2095a3b4
Ctrl.data = hexdata:6094455245209c442e19e5f313534da9f9c7e5d634d443d8cd14b9e9b6d778ab
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 7df15d385663c45a359e5d1f4b648d6e77156b48e3d382db08cb26d3218dabee
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3a985db779275ed7c23af0f123220d862db237fc9ac9834e76eec0692b1e98055c12
Output = 75a6012f1571fb5a7ab0712ef6d520a70246e8df9073445c28239fdb03c5c8dd
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:75a6012f1571fb5a7ab0712ef6d520a70246e8df9073445c28239fdb03c5c8dd
Ctrl.data = hexdata:1c80ac5d876634b04d7dbebfe687fbdf2df7f82df4e6549defa8e691b26dd3ad
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = adaacbad9407c0c69632800eb3c7e5f901af2bfae618fa0cbcf63fb0064df997
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:75a6012f1571fb5a7ab0712ef6d520a70246e8df9073445c28239fdb03c5c8dd
Ctrl.data = hexdata:1c80ac5d876634b04d7dbebfe687fbdf2df7f82df4e6549defa8e691b26dd3ad
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 70a6fd6201cddc6ac218cacf4487be2c23382e9a898a8e959d443602e66bc9ff
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:75a6012f1571fb5a7ab0712ef6d520a70246e8df9073445c28239fdb03c5c8dd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = b7be663035d51cb5f1a73c9618ebcb1836510ab2c8e29aaa8c0512dca901adea
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:b7be663035d51cb5f1a73c9618ebcb1836510ab2c8e29aaa8c0512dca901adea
Ctrl.data = hexdata:64dc967779196d895cf649ad603cd1abb1a9ac2f6e52df74c02c9fc38e0aca5b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = cedc4ca3f6acfc0495e9c4aacf236309e80688394296baab08b2821d8adeb3b2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:b7be663035d51cb5f1a73c9618ebcb1836510ab2c8e29aaa8c0512dca901adea
Ctrl.data = hexdata:64dc967779196d895cf649ad603cd1abb1a9ac2f6e52df74c02c9fc38e0aca5b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 22d95b8d42edc48c71e82ef68f3d0adea616742d829ef8dc40ee5a4a127e0c2f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:b7be663035d51cb5f1a73c9618ebcb1836510ab2c8e29aaa8c0512dca901adea
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 7c0c1e280449811974dcb2b95b2505c5dd267bb6e367dfad8403149f61980ba8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7c0c1e280449811974dcb2b95b2505c5dd267bb6e367dfad8403149f61980ba8
Ctrl.data = hexdata:771a6f78341f621fc9a0ada0e428b129a072515e6aa0eb29501e5b4f67357a3f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 36079cac5cd69338b13cdf43902c52353c0ad3bee52d9d4b80bdcbafb896c1f2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7c0c1e280449811974dcb2b95b2505c5dd267bb6e367dfad8403149f61980ba8
Ctrl.data = hexdata:771a6f78341f621fc9a0ada0e428b129a072515e6aa0eb29501e5b4f67357a3f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 5ccccbec1e524afdbfeb3f79eee231445ea4b970775ca44780b836278459e800
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7c0c1e280449811974dcb2b95b2505c5dd267bb6e367dfad8403149f61980ba8
Ctrl.data = hexdata:771a6f78341f621fc9a0ada0e428b129a072515e6aa0eb29501e5b4f67357a3f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 1f99d16935378ad2b629602be4902ef36803a0456f4b412dc60069b02907c157
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:7c0c1e280449811974dcb2b95b2505c5dd267bb6e367dfad8403149f61980ba8
Ctrl.data = hexdata:53fa7ef57bd948347ee221a58e0357e5d64fc68337a40e1a2a955c362305b7d0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 3f314a8cdade0c8fb7a8ada062c076cdc66f48ae85b06e9866823071b24569f6
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:147e5b2a8c852a29cd2dbe0889eae5e127c08c7dc4ef2fcd10c7f074132b9316f82c
Output = a4414022e17e270db589511aeed7c54f64383760bf6867b3ea2c87c6ab350c4a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a4414022e17e270db589511aeed7c54f64383760bf6867b3ea2c87c6ab350c4a
Ctrl.data = hexdata:c029b25f3eeaa245d3b16415a9dfbd738f49972abd20cedf77e712e34151d768
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = cf72dbf54ef12ad90c826cc5f745332a051bd22f3d4a4980e38ed5c91acdbe00
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a4414022e17e270db589511aeed7c54f64383760bf6867b3ea2c87c6ab350c4a
Ctrl.data = hexdata:c029b25f3eeaa245d3b16415a9dfbd738f49972abd20cedf77e712e34151d768
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 04e7fa07f592562b442f41403f89ce197a777b890dd6ad4a37330d7b97f9297f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:a4414022e17e270db589511aeed7c54f64383760bf6867b3ea2c87c6ab350c4a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = facf154981665599f9071f24fbe03da350726c0580865bec44eb81cca53624a2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:facf154981665599f9071f24fbe03da350726c0580865bec44eb81cca53624a2
Ctrl.data = hexdata:22ef82f8cfc550dfed76234ee158ffa49e142788d40bb8f11503df76eaa414ee
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = e86ea8bf6c00c4e1415f55ffe5c6fc639cfde1aedb549eea54e536920794b677
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:facf154981665599f9071f24fbe03da350726c0580865bec44eb81cca53624a2
Ctrl.data = hexdata:22ef82f8cfc550dfed76234ee158ffa49e142788d40bb8f11503df76eaa414ee
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 4470d8eaf03e31af06885a327decd84b44b073ed040d81e223cd40e018ae3ebb
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:facf154981665599f9071f24fbe03da350726c0580865bec44eb81cca53624a2
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 77c02b58bcf97af0ffded733e0a297b212f6d72e55af55609fdd85c99b52cb4c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:77c02b58bcf97af0ffded733e0a297b212f6d72e55af55609fdd85c99b52cb4c
Ctrl.data = hexdata:5cc964a080f748ff23e5b303b291002a4dbf13e657efd4fe880aec0f7ef42b29
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = e7a16831383b4617205c40de58a169f567f4c612b2c07667f10b61a4b137a088
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:77c02b58bcf97af0ffded733e0a297b212f6d72e55af55609fdd85c99b52cb4c
Ctrl.data = hexdata:5cc964a080f748ff23e5b303b291002a4dbf13e657efd4fe880aec0f7ef42b29
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 912010401679c0279d6e45cc968232ed8cea41b66dc80fa5ad1d4ac666a38873
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:77c02b58bcf97af0ffded733e0a297b212f6d72e55af55609fdd85c99b52cb4c
Ctrl.data = hexdata:5cc964a080f748ff23e5b303b291002a4dbf13e657efd4fe880aec0f7ef42b29
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = d3ad734749b9c723c3a4186ac4af12e70a6c8f209c96277af7caaf0a8a30a284
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:77c02b58bcf97af0ffded733e0a297b212f6d72e55af55609fdd85c99b52cb4c
Ctrl.data = hexdata:19c68fab2d15ea5cefe7de3478c9207f8321be8045ff3a3463cdc0c11dbe7cd1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 6acd62983abf673fc0884510ca8c92f617089ad5dad4b16b4a9c43c45af97020
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:d3b971aced61ea7ec4fbe922509a9f7184ee8fec3758728d199a78207ebb14078e68
Output = 5d60ce4dbf5ab602baef6141d47216c6f9c24c080525fe81f9f2c53e39cefe3b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d60ce4dbf5ab602baef6141d47216c6f9c24c080525fe81f9f2c53e39cefe3b
Ctrl.data = hexdata:62b7f550fdb7e6af518714ff659c8539fd5fe2cbefa7338dd4f01cee8734a744
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 747dd5593aa133934f8be2e7c92e7431dcb5c369222a2d5c6a8142435d1d6df5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d60ce4dbf5ab602baef6141d47216c6f9c24c080525fe81f9f2c53e39cefe3b
Ctrl.data = hexdata:62b7f550fdb7e6af518714ff659c8539fd5fe2cbefa7338dd4f01cee8734a744
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 20a8ddd7a7d1ba973465bf35610018bdc54baf59dc4984a6dad05d11308e4952
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:5d60ce4dbf5ab602baef6141d47216c6f9c24c080525fe81f9f2c53e39cefe3b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 58fc08f57ae7462775a3fb23cecaa4b3e7f5f9274c55aaf4d5aca9f57f3b1dfc
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:58fc08f57ae7462775a3fb23cecaa4b3e7f5f9274c55aaf4d5aca9f57f3b1dfc
Ctrl.data = hexdata:88cedc1856dd0d81e3af6a9b320f05d3d005bbb3664f0fc912e41007fb8645dc
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 8c8ea28aad5411f3963ad2827f2bdc84041cc6da53c7400c998c6434c5c15ba1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:58fc08f57ae7462775a3fb23cecaa4b3e7f5f9274c55aaf4d5aca9f57f3b1dfc
Ctrl.data = hexdata:88cedc1856dd0d81e3af6a9b320f05d3d005bbb3664f0fc912e41007fb8645dc
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 123b12381753a82aeb705cb2c3f2a2ae729511f1b1c92e6be3e587b07fe4c60f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:58fc08f57ae7462775a3fb23cecaa4b3e7f5f9274c55aaf4d5aca9f57f3b1dfc
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 3e415c1fa74e9f96d1c1af252fe3c8e1fb9e991f0e45a4a471e13d03bb2a2037
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3e415c1fa74e9f96d1c1af252fe3c8e1fb9e991f0e45a4a471e13d03bb2a2037
Ctrl.data = hexdata:84e00926de1231de5d058c9d907aeec6a6b94b9e2c8edecd7672b4013d4bd4a7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 5a8fde0ac38739f0eb2e739b440530c3943b37ad26ffaff73f2904e17bde058d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3e415c1fa74e9f96d1c1af252fe3c8e1fb9e991f0e45a4a471e13d03bb2a2037
Ctrl.data = hexdata:84e00926de1231de5d058c9d907aeec6a6b94b9e2c8edecd7672b4013d4bd4a7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 97e9a4d00eff6997d6e60d5a060851d7c1f5c6878ef198063fa5a3a9cc77e5e9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3e415c1fa74e9f96d1c1af252fe3c8e1fb9e991f0e45a4a471e13d03bb2a2037
Ctrl.data = hexdata:84e00926de1231de5d058c9d907aeec6a6b94b9e2c8edecd7672b4013d4bd4a7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 5b596ab4521a354c141898211ac96fdf6965931fb142ca601ec5dcaccd900f39
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3e415c1fa74e9f96d1c1af252fe3c8e1fb9e991f0e45a4a471e13d03bb2a2037
Ctrl.data = hexdata:622bf37da14b1110ffd9fde15a8b34b5a9192b7c003279df2d779a8441eb832a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 86fc27400916d558eb24e277ada87cfb217bb41993b5947049eaab30ee1967de
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:6e9a209d728b63a2649820ecba2439c3ced3facc56973fc63359e73f1fe8a5f0
Output = 5774c653d8f3ca4b852189369e8fcb03001837900c0c9b47037565139b2a8974
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5774c653d8f3ca4b852189369e8fcb03001837900c0c9b47037565139b2a8974
Ctrl.data = hexdata:d222fdad7a1eaf29aa5c1699fb2c6452337e6a3f4eed5112706edc32d2aa5942
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 4b3538bdc30df6f4052310a5f66ea6de2ca506a22a0e3631b2d3eff387dd2425
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5774c653d8f3ca4b852189369e8fcb03001837900c0c9b47037565139b2a8974
Ctrl.data = hexdata:d222fdad7a1eaf29aa5c1699fb2c6452337e6a3f4eed5112706edc32d2aa5942
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 377e1abcc286c58d438f146ceb39050d453a1b9c842ed8d9275842cfac27484b
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:5774c653d8f3ca4b852189369e8fcb03001837900c0c9b47037565139b2a8974
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 5feaf88808714444916bb5759151d2fa09d8dd884dbc76ed72f33023e45c1006
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5feaf88808714444916bb5759151d2fa09d8dd884dbc76ed72f33023e45c1006
Ctrl.data = hexdata:6f19f45a25846f2a30639c6a150a42c060007d3a4a637f9a1949ff980e151270
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 992ef872ba2d217c7e2256e42a2e4391a3482105db09fb0330813f4ae093d8ec
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5feaf88808714444916bb5759151d2fa09d8dd884dbc76ed72f33023e45c1006
Ctrl.data = hexdata:6f19f45a25846f2a30639c6a150a42c060007d3a4a637f9a1949ff980e151270
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = e439ad92cd58b349cf2d44ceada80f0dc62cd03a216c0a6e98b9c4faa762e178
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:5feaf88808714444916bb5759151d2fa09d8dd884dbc76ed72f33023e45c1006
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 02dc2e8f1f3827dd4eab288c3e2f02437a0a619e18db9092bf2a09fb01f14d7d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:02dc2e8f1f3827dd4eab288c3e2f02437a0a619e18db9092bf2a09fb01f14d7d
Ctrl.data = hexdata:110d218cd286649a49fa86565f02e89c1e155e9d724392f98398cab4a2c6536a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 5915a67e1934c6a65cc0ff2a8101d2ab42c1d2fb448374cc4a4a1aa5b79304d2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:02dc2e8f1f3827dd4eab288c3e2f02437a0a619e18db9092bf2a09fb01f14d7d
Ctrl.data = hexdata:110d218cd286649a49fa86565f02e89c1e155e9d724392f98398cab4a2c6536a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 1526a83cee865495333b13328e5b6cf6a6f42f1cb354d5e0fac6ab75e32a059f
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:02dc2e8f1f3827dd4eab288c3e2f02437a0a619e18db9092bf2a09fb01f14d7d
Ctrl.data = hexdata:110d218cd286649a49fa86565f02e89c1e155e9d724392f98398cab4a2c6536a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 4f7a8ecd191d6b18ede079553a6472159aed46da19f891349e94d14517614fe4
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:02dc2e8f1f3827dd4eab288c3e2f02437a0a619e18db9092bf2a09fb01f14d7d
Ctrl.data = hexdata:27c96e77f7f7e4dbdd958348ce3d95683f3b78652605fd41bc02280c091d199e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = c2d6e4992b13331da0843572e55dd0624a04067c9415a2f231f08e86d496fd15
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:d339bc83462b544456e27a735516d50bd330bce6f39d0c388a89ef33ac209001
Output = 4d1c1c060c37258aaeff7aa73976f61e09779ffb2c296558b32a951c9bef5f67
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:4d1c1c060c37258aaeff7aa73976f61e09779ffb2c296558b32a951c9bef5f67
Ctrl.data = hexdata:7b21856d85c0ed268cd2bd0fc5065edfe078c97e03ede2cb7912ce7615763b94
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 977fc35f7a57f30e6509cb0a2ad9ad5cd1bc18d9d945ef3d6efede51ca727be6
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:4d1c1c060c37258aaeff7aa73976f61e09779ffb2c296558b32a951c9bef5f67
Ctrl.data = hexdata:7b21856d85c0ed268cd2bd0fc5065edfe078c97e03ede2cb7912ce7615763b94
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = a0a444d95f34b3abd80fa9c61f00e522ebaaba9b0b392bce0d5bdd64c66faea8
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:4d1c1c060c37258aaeff7aa73976f61e09779ffb2c296558b32a951c9bef5f67
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 6d6c5cc5e179e9b883aef10af16e9f7fdfe185514c5a17ba42de5ea4ce4636a9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:6d6c5cc5e179e9b883aef10af16e9f7fdfe185514c5a17ba42de5ea4ce4636a9
Ctrl.data = hexdata:5212d18ab2b3f4749a2fdc8f7c5bfe86582c3ef4b82fd15e4fbcf679845a898f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = ae767de352cd5de70f06fa89c97c384f3114459d2d34358254536d6dc2a51a43
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:6d6c5cc5e179e9b883aef10af16e9f7fdfe185514c5a17ba42de5ea4ce4636a9
Ctrl.data = hexdata:5212d18ab2b3f4749a2fdc8f7c5bfe86582c3ef4b82fd15e4fbcf679845a898f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = eadd1815582776d2af4c5b2459884f636c668ddb4f9de2a3c9d748f3d30c6c55
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:6d6c5cc5e179e9b883aef10af16e9f7fdfe185514c5a17ba42de5ea4ce4636a9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 87d23fc7cb12e158371709a0c492ac6b454ed1bd5d6f9034d8faf568d8388ea1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:87d23fc7cb12e158371709a0c492ac6b454ed1bd5d6f9034d8faf568d8388ea1
Ctrl.data = hexdata:c326103e763f740bcfcf619cf5f6ed5516d73c58f73bb1a288ebe4c90f8a0376
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 05df2e13f0bbc39095a751653198fbd71316d60f0b0ff34a571be0f24a0110e4
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:87d23fc7cb12e158371709a0c492ac6b454ed1bd5d6f9034d8faf568d8388ea1
Ctrl.data = hexdata:c326103e763f740bcfcf619cf5f6ed5516d73c58f73bb1a288ebe4c90f8a0376
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 7548a168eadc002e00a9f6992464d89053a09fafe5455424043e88625f6aa1f5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:87d23fc7cb12e158371709a0c492ac6b454ed1bd5d6f9034d8faf568d8388ea1
Ctrl.data = hexdata:c326103e763f740bcfcf619cf5f6ed5516d73c58f73bb1a288ebe4c90f8a0376
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 55d8638f0b4e4a8c0c86a3b499c1f5a22c4b763f74f34415852fe66f5b14fc64
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:87d23fc7cb12e158371709a0c492ac6b454ed1bd5d6f9034d8faf568d8388ea1
Ctrl.data = hexdata:ef6958939a40f5a6da5514b25c61e65c785529da24b7abe4c2ff24de90e22865
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 91621081e013738d0565d87d48299f9663e9cb00ea10de8b4e524faed12b2549
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:10cd69a2ff07b9fc1b97f048ff04f76bde83ffa1b7c55a7c90f4a335c678e603
Output = 1b658957e8bfcaa895101e83f6aed7ee70e09c1f9a712b98da9ec8f82072d62a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:1b658957e8bfcaa895101e83f6aed7ee70e09c1f9a712b98da9ec8f82072d62a
Ctrl.data = hexdata:77c319274f0bee551e4ff02d35c109527430249982634b83620d555df1fc1b19
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 4a274d1c3ffb31ccfd02b822c58e22540a08e8805467949049c790523f22a521
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:1b658957e8bfcaa895101e83f6aed7ee70e09c1f9a712b98da9ec8f82072d62a
Ctrl.data = hexdata:77c319274f0bee551e4ff02d35c109527430249982634b83620d555df1fc1b19
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = fd0c1024664dce62f20828f6523804b6c3cf8cac1d0c226ca82c216617749278
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:1b658957e8bfcaa895101e83f6aed7ee70e09c1f9a712b98da9ec8f82072d62a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = f99b6c3c1a03d0ec64964a6a49e9ce4d9580e923c0afbbf9c46928e990e4cf2d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f99b6c3c1a03d0ec64964a6a49e9ce4d9580e923c0afbbf9c46928e990e4cf2d
Ctrl.data = hexdata:09579596d89a7bc16f6208f1b65d0af814a2e7dc2b5752153b01ebd403835b24
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 649f88a321910f7e079515517de528f096ad00b460f700ca3a42249ffb0f198c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f99b6c3c1a03d0ec64964a6a49e9ce4d9580e923c0afbbf9c46928e990e4cf2d
Ctrl.data = hexdata:09579596d89a7bc16f6208f1b65d0af814a2e7dc2b5752153b01ebd403835b24
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 591cccb532575b11f3f7644305fc98b39b4ab5e857884b83f112eded0748d86c
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:f99b6c3c1a03d0ec64964a6a49e9ce4d9580e923c0afbbf9c46928e990e4cf2d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 9e3829ca4efe839ce6518ecacbfb70699230a580c47d1593e7755663f42ab710
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9e3829ca4efe839ce6518ecacbfb70699230a580c47d1593e7755663f42ab710
Ctrl.data = hexdata:4a78c3e4fdf496868bb144f02d5c8d751172fe3b31a2708a34a84b0035359216
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 3b5e42c71b7f84c0c533c5b33fb677e5dbd00fa19461643a9f9a28ac68d33a34
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9e3829ca4efe839ce6518ecacbfb70699230a580c47d1593e7755663f42ab710
Ctrl.data = hexdata:4a78c3e4fdf496868bb144f02d5c8d751172fe3b31a2708a34a84b0035359216
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 0755417db746dbca652cac12fc9e272f2ee1d65b7ddb95be3a1458cc0feb7ceb
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9e3829ca4efe839ce6518ecacbfb70699230a580c47d1593e7755663f42ab710
Ctrl.data = hexdata:4a78c3e4fdf496868bb144f02d5c8d751172fe3b31a2708a34a84b0035359216
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 7e518bab7a36df94f3e43c022300afcc5219c4a0b0353d7ec8d7b81a957fe8b3
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:9e3829ca4efe839ce6518ecacbfb70699230a580c47d1593e7755663f42ab710
Ctrl.data = hexdata:05e757c9c7a0a88a5242f101a8b9813ff7c28cbb60f82fe8d64efb3b29e2a35f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 9df1f3a9a73ccf046ae832e6567f0381df1c279051d5e8d3d438533a8e3c286e
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:1d6a3ca45771b6de38bfa21ef1b18c7f392dc245a40a678638ff703bc429cdfa
Output = e283b4a0c6dee0763a2a7c1b3e5079f94c2e442c4876bdb37f9b2410687819bd
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:e283b4a0c6dee0763a2a7c1b3e5079f94c2e442c4876bdb37f9b2410687819bd
Ctrl.data = hexdata:b596924c279606af433ef8939cb7e2e8f22b1a4c58f868f5e9b8b66f89f95ec4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 35379b66e3989f860493b7f1a19d35a6b1786ead286f058b291a9e45f154984d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:e283b4a0c6dee0763a2a7c1b3e5079f94c2e442c4876bdb37f9b2410687819bd
Ctrl.data = hexdata:b596924c279606af433ef8939cb7e2e8f22b1a4c58f868f5e9b8b66f89f95ec4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 3c06224ebfe816c633c1ca1785d1b9c234b41a050608cd24d3873f3e8caf3c6d
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:e283b4a0c6dee0763a2a7c1b3e5079f94c2e442c4876bdb37f9b2410687819bd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 43081024ba4bc52ddbdaf075d2c0965e38521d0e2b43ad95235307ae567c4237
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:43081024ba4bc52ddbdaf075d2c0965e38521d0e2b43ad95235307ae567c4237
Ctrl.data = hexdata:39f99c22b551a77eadb49cc2df00c0651bb847f678394c04a9663ff592122daf
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 9d2d1d2d3aef26d116c4e8ae64c9cfc785c34b4e48ebed03291c05d97fbed48c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:43081024ba4bc52ddbdaf075d2c0965e38521d0e2b43ad95235307ae567c4237
Ctrl.data = hexdata:39f99c22b551a77eadb49cc2df00c0651bb847f678394c04a9663ff592122daf
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 8def30bd06498ab5d3687e1d5b7b255a4d8f0a350fff033e09fdedac103b33af
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:43081024ba4bc52ddbdaf075d2c0965e38521d0e2b43ad95235307ae567c4237
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = bdc1635b5a2efb9d40f948e1885ef7dafabb342924cb93d8b5a41ef6b1291749
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bdc1635b5a2efb9d40f948e1885ef7dafabb342924cb93d8b5a41ef6b1291749
Ctrl.data = hexdata:bfd5d60816d0d8aaa054a0c9ebe667f08b885bde11a0d2440ea48ae3d539ffd8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = e45932f62656d9b4a4424d25b0dee0edc4dd7e5cd97ed559826ac2dc8753e234
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bdc1635b5a2efb9d40f948e1885ef7dafabb342924cb93d8b5a41ef6b1291749
Ctrl.data = hexdata:bfd5d60816d0d8aaa054a0c9ebe667f08b885bde11a0d2440ea48ae3d539ffd8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 79e88b3776b65e1cf86e1652c1fa503b0fa9f425fb2d7f12ed980c82aea480d8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bdc1635b5a2efb9d40f948e1885ef7dafabb342924cb93d8b5a41ef6b1291749
Ctrl.data = hexdata:bfd5d60816d0d8aaa054a0c9ebe667f08b885bde11a0d2440ea48ae3d539ffd8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = a99de25f23b4c3b53e0f94c20e4cacbf69449eb6662ede20ecaf80f4b3588549
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:bdc1635b5a2efb9d40f948e1885ef7dafabb342924cb93d8b5a41ef6b1291749
Ctrl.data = hexdata:093be188157ab8ebdbc0862581178d451a89a496eec1d75a735c63745346d07e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 5d068f2083afa672d025b89c6883a7d47899352d1f534f757cf9d046f42f2158
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:b5c0634df696089d878e37b775c4c2f03f42748cec9dfc12661a8b888ed40685
Output = c2fcc802a14192c660e7728d983b6f85a21a9e9e0bfb1cc5154db457e5153795
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c2fcc802a14192c660e7728d983b6f85a21a9e9e0bfb1cc5154db457e5153795
Ctrl.data = hexdata:d4d8e30ea5e596830f165ab809b9c541383d621bf5502b83a27ed3ea2e570d2a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = cb5f4de81d60d9d8537b365b4311014a1380808c3b9c3a98a25dace58c0961c4
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c2fcc802a14192c660e7728d983b6f85a21a9e9e0bfb1cc5154db457e5153795
Ctrl.data = hexdata:d4d8e30ea5e596830f165ab809b9c541383d621bf5502b83a27ed3ea2e570d2a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 7aa5d4b291c159958c1781f0833e8dabf48ccd0d93553fbda644fea6ab1d730f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:c2fcc802a14192c660e7728d983b6f85a21a9e9e0bfb1cc5154db457e5153795
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = cde47edec9e5f1fb69819b0fc195360469a11af491b2b85bffa5fe3d3794f306
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:cde47edec9e5f1fb69819b0fc195360469a11af491b2b85bffa5fe3d3794f306
Ctrl.data = hexdata:f0ef84594377b8878aec3361beccd2c701cd1fff0bb1d091bdc960dbcc03ed2d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = bd18fde839dd5b186595135f6cce58f544c35168753489956d3bfc1691fdc9ea
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:cde47edec9e5f1fb69819b0fc195360469a11af491b2b85bffa5fe3d3794f306
Ctrl.data = hexdata:f0ef84594377b8878aec3361beccd2c701cd1fff0bb1d091bdc960dbcc03ed2d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = bd404aafe66f33b525da924eab5a01330eed5e6792c18a2733594efa5fbe1770
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:cde47edec9e5f1fb69819b0fc195360469a11af491b2b85bffa5fe3d3794f306
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 17dc622c65dd8b948cbd8dba752fbf1132fc689717ad9e7d57258e85cff6b4e5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:17dc622c65dd8b948cbd8dba752fbf1132fc689717ad9e7d57258e85cff6b4e5
Ctrl.data = hexdata:47a04fbfcb7af70cd735ccd29f978db89ad2884a208f5e0a0efed6c78e21f93e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 4a28e31a44a9084c31045bab3cd9ca4bb7cc6c0a7a3339265919b6dbbf9bd439
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:17dc622c65dd8b948cbd8dba752fbf1132fc689717ad9e7d57258e85cff6b4e5
Ctrl.data = hexdata:47a04fbfcb7af70cd735ccd29f978db89ad2884a208f5e0a0efed6c78e21f93e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 8f7bcfb0a364acb09af591dbfbd1f5d76a1b5da68eb86e22633e3d4ffd4ffb3b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:17dc622c65dd8b948cbd8dba752fbf1132fc689717ad9e7d57258e85cff6b4e5
Ctrl.data = hexdata:47a04fbfcb7af70cd735ccd29f978db89ad2884a208f5e0a0efed6c78e21f93e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 3d5d45e78c540d05a19ee723ef075ff5c30e4e637af9075a519224751bf73cbb
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:17dc622c65dd8b948cbd8dba752fbf1132fc689717ad9e7d57258e85cff6b4e5
Ctrl.data = hexdata:0f147eef330ea13e24db0e4f0f99ef57e226fcd893bcad0aa775736043a5678c
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 865f8cf4b1065211f6c79e2a269fc5d292c496389458ee1defdbdecdae3c178e
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c83e2d0710fea2c69df3ddb8e44ab8eff77b331b5bab68693150cb57024bb513
Output = 670bf2a12c3b914a0251276f624e2b7b38056b989c4e4e48a6bd9d6e649329a7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:670bf2a12c3b914a0251276f624e2b7b38056b989c4e4e48a6bd9d6e649329a7
Ctrl.data = hexdata:b91f2426c7a814aa728b0d066803bb5f5ba89053a107093525bd37b8a228bbe6
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = da288713ae469437c7d49934f87461dec0884cc1c075d0c2b80467c9b497493e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:670bf2a12c3b914a0251276f624e2b7b38056b989c4e4e48a6bd9d6e649329a7
Ctrl.data = hexdata:b91f2426c7a814aa728b0d066803bb5f5ba89053a107093525bd37b8a228bbe6
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 9c4d05cc523e7486fa518512c15697e8da785182c9a07553d185634653ad57e1
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3b2a40cdb43badc2354bbcab3232f150a29cdb6d701a4d954e53f93122ddb384
Ctrl.salt = hexsalt:670bf2a12c3b914a0251276f624e2b7b38056b989c4e4e48a6bd9d6e649329a7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 0cb3b141bf3fc28050388dd84a2504e7cbebb715c0963f8291793ecf6d8bdff3
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:0cb3b141bf3fc28050388dd84a2504e7cbebb715c0963f8291793ecf6d8bdff3
Ctrl.data = hexdata:106c8ade410c1a7972f9dcd60fde846a0652ad92dc3737120bceca0c3e316bac
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 11ca6d097742c16dd5b42af8508d46771fac61ad30120f1eeffd90b8c0ecb0d9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:0cb3b141bf3fc28050388dd84a2504e7cbebb715c0963f8291793ecf6d8bdff3
Ctrl.data = hexdata:106c8ade410c1a7972f9dcd60fde846a0652ad92dc3737120bceca0c3e316bac
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 4305a71a34bdb5e0821501b4bdd271593ab82dd4532cc273fed3db050ac2c1b6
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:0cb3b141bf3fc28050388dd84a2504e7cbebb715c0963f8291793ecf6d8bdff3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 59714d40ada923b4bd6fcc27a4ace84d75003431b1b0ec496b786c15fd74345c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:59714d40ada923b4bd6fcc27a4ace84d75003431b1b0ec496b786c15fd74345c
Ctrl.data = hexdata:8c22d8b59e26690f0279c8b079f3b1712544600a0e5e5aef21609a1544f0fd7e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 403399b9a3b3d8c729e488aedf59572057288184d845f65762965638d9044f02
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:59714d40ada923b4bd6fcc27a4ace84d75003431b1b0ec496b786c15fd74345c
Ctrl.data = hexdata:8c22d8b59e26690f0279c8b079f3b1712544600a0e5e5aef21609a1544f0fd7e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 84c047db046fe61aff8a08b1baf4d2d19cc64e5d8520e0a7b0d53cf1c4a0d931
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:59714d40ada923b4bd6fcc27a4ace84d75003431b1b0ec496b786c15fd74345c
Ctrl.data = hexdata:8c22d8b59e26690f0279c8b079f3b1712544600a0e5e5aef21609a1544f0fd7e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 4ff1809a55380799faac1c9e7795f61d2f2e8d94e05076a863cf0624b2f7910e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:59714d40ada923b4bd6fcc27a4ace84d75003431b1b0ec496b786c15fd74345c
Ctrl.data = hexdata:b3a2661fca9d2bd11f011da167daa18d7d705dffae6987ef1410fa932543bbc0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = c5fced915b2f444eba12a1dbda3487a2054201378640682a3a668a1513f6a232
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:76d2def296a73bbbe2c0c58061fda9a8486a65fe0d25a312061a33de39665229
Output = aad44b2999d3974a3a75f63b36380d3a4c1051b43054ff3681df46c52f3f7cab
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:aad44b2999d3974a3a75f63b36380d3a4c1051b43054ff3681df46c52f3f7cab
Ctrl.data = hexdata:f2c3f79a329d8a0a0c71fdff27d21b4f5396cef54eee48e8d95823730af5c7cd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = d2a135057bcf8843aed48c7c37a8d891ca459ac6def66950c57cf849a60cad9b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:aad44b2999d3974a3a75f63b36380d3a4c1051b43054ff3681df46c52f3f7cab
Ctrl.data = hexdata:f2c3f79a329d8a0a0c71fdff27d21b4f5396cef54eee48e8d95823730af5c7cd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 5c920375f607f4b1a179d31aff80074b3357108960051a22de8e001aa6979c0f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3313848ca37d8491646fd92c252257742d983c65090bc542c9a03fd4b26e9b1c
Ctrl.salt = hexsalt:aad44b2999d3974a3a75f63b36380d3a4c1051b43054ff3681df46c52f3f7cab
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 3b7f06aab24b86a7e17d898b8f43c9460a3fa5b949db5e64de401efa2826daa9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3b7f06aab24b86a7e17d898b8f43c9460a3fa5b949db5e64de401efa2826daa9
Ctrl.data = hexdata:68952fb6f6fab9968e16044c7d3d6e29f9b4cb969ea37d3b89317581242a51c3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 929e776e48697a19220f40bcdb91d17aa81c72609dad9e44ce504a9b1b1a3666
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:3b7f06aab24b86a7e17d898b8f43c9460a3fa5b949db5e64de401efa2826daa9
Ctrl.data = hexdata:68952fb6f6fab9968e16044c7d3d6e29f9b4cb969ea37d3b89317581242a51c3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = ca770b94d778f80d7bf5e9c57385d311944074fc971d4509666d9fd2da082f6f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:3b7f06aab24b86a7e17d898b8f43c9460a3fa5b949db5e64de401efa2826daa9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = c1cbedf5f8e8b561dd21c9ae1ee2e82ded1fa8ca3dbd58b8dbe153a78f87c316
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c1cbedf5f8e8b561dd21c9ae1ee2e82ded1fa8ca3dbd58b8dbe153a78f87c316
Ctrl.data = hexdata:94cc1ab5421bc914655d3c9b29c62257e3921357c251714f0603d97ecb6af5b4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 9cbdcf2aab74218e206b09990759afacf0b0fc6e9663df2ef3b1be8baa04137f
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c1cbedf5f8e8b561dd21c9ae1ee2e82ded1fa8ca3dbd58b8dbe153a78f87c316
Ctrl.data = hexdata:94cc1ab5421bc914655d3c9b29c62257e3921357c251714f0603d97ecb6af5b4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 68b56ade508cb9a80659247476e9bc51e11a2bf8996abcf31ef7ca40db8ce038
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c1cbedf5f8e8b561dd21c9ae1ee2e82ded1fa8ca3dbd58b8dbe153a78f87c316
Ctrl.data = hexdata:94cc1ab5421bc914655d3c9b29c62257e3921357c251714f0603d97ecb6af5b4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 99b1731836e008fce195b2656a978653fab931ca7568538ea445e07758eaec3e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:c1cbedf5f8e8b561dd21c9ae1ee2e82ded1fa8ca3dbd58b8dbe153a78f87c316
Ctrl.data = hexdata:9d6de017899f4866cf158fbcdff17f9be461b515424fcc68983ea14199b4f93e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = cfa68b4390998107c071a7a7f05aeaa67c399fbc74ae078d239953d97a9b192c
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:84e4720169f84d06305f31d48bc80c38533262092dad037431595504652ad812
Output = e8634fc371ec5aeb3e610dfaaa37f5d5964a3518a7c50dc02daeb409b5813a67
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:e8634fc371ec5aeb3e610dfaaa37f5d5964a3518a7c50dc02daeb409b5813a67
Ctrl.data = hexdata:629f374f2fbca62af9a940e8dbfa469605239b9af3d1a9ad870a5d09aa828d4b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 4de207e64746e30b0422f9f61bb0d62f3e1559685a5b6231491dbedd7e7d3c70
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:e8634fc371ec5aeb3e610dfaaa37f5d5964a3518a7c50dc02daeb409b5813a67
Ctrl.data = hexdata:629f374f2fbca62af9a940e8dbfa469605239b9af3d1a9ad870a5d09aa828d4b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = f98601cd853b472676a12f4d2b0ed496ded451aa7255f2261d9bc6b0e1831e26
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:0130ef5db75ffa78e0dd43c3c61d887a9153044d2ac8fe4046bb2b0c38034715
Ctrl.salt = hexsalt:e8634fc371ec5aeb3e610dfaaa37f5d5964a3518a7c50dc02daeb409b5813a67
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 45d0bc957523624818445ac480848850e07fb050d8d58a62614526c7b6f6a3cf
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:45d0bc957523624818445ac480848850e07fb050d8d58a62614526c7b6f6a3cf
Ctrl.data = hexdata:cb3e464901236370574fdb6e62e3578d6d055b13352bb009c7524be5046fe3f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 5e827d8f0a5198f40ce9a179220c64a5be7ffbb7238a7ce3924af12435517829
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:45d0bc957523624818445ac480848850e07fb050d8d58a62614526c7b6f6a3cf
Ctrl.data = hexdata:cb3e464901236370574fdb6e62e3578d6d055b13352bb009c7524be5046fe3f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = cd3650173b74032cd5923eedd2ca939f4986071612025a3931fcbdae424c3fe0
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:45d0bc957523624818445ac480848850e07fb050d8d58a62614526c7b6f6a3cf
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 305e840032f79d5fc438a556f9c2a0aed6e63ba96dee4dbbcc46e3cd5254e52d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:305e840032f79d5fc438a556f9c2a0aed6e63ba96dee4dbbcc46e3cd5254e52d
Ctrl.data = hexdata:05bb66eae94bafe82cbc264ce33f66a4259d1003910333ecd9d70a0dc6676280
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 87c29eb07ed9d69f4f17d19dbe7d792c96243bcbab5a6ad674d476ab2723f3e9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:305e840032f79d5fc438a556f9c2a0aed6e63ba96dee4dbbcc46e3cd5254e52d
Ctrl.data = hexdata:05bb66eae94bafe82cbc264ce33f66a4259d1003910333ecd9d70a0dc6676280
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 1bea4e5a0cce346fcf3784bbea219060a733bb9b3d9fbcd51b230df79e7bbaf7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:305e840032f79d5fc438a556f9c2a0aed6e63ba96dee4dbbcc46e3cd5254e52d
Ctrl.data = hexdata:05bb66eae94bafe82cbc264ce33f66a4259d1003910333ecd9d70a0dc6676280
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 56ad7e5af0a0c80dedf12d1206d731527e4a19d821ca666b887532da4dafddc2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:305e840032f79d5fc438a556f9c2a0aed6e63ba96dee4dbbcc46e3cd5254e52d
Ctrl.data = hexdata:2f35a4e79e594f9552231c0a20b1c044f335970e1672fcd232ee080e0b1003d5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 439199cbd6c133c77a01fd46314381dac23f9f75bc25a5b6bd3a0c3ae65c213a
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:846579bee2d8787197afac0ad73a05ace42fdc88973863867f7034edaaa67bab
Output = f2f46cf85e6dc82602eb1169a27aaa17185af5fc26ac8b4cc466f9be2f1b3882
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f2f46cf85e6dc82602eb1169a27aaa17185af5fc26ac8b4cc466f9be2f1b3882
Ctrl.data = hexdata:09183dfa8773dbcbcf4e956f909e91f9dc01134b4f3e478c2e9157c74610d4a9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 539cbdca2eea93fb99498a1828d74e538110602331ca05e2e0a33904dbacc7e0
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:f2f46cf85e6dc82602eb1169a27aaa17185af5fc26ac8b4cc466f9be2f1b3882
Ctrl.data = hexdata:09183dfa8773dbcbcf4e956f909e91f9dc01134b4f3e478c2e9157c74610d4a9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = c5eed5ccc461fc4eed16ba2d4e73e61ee5e1e65fd37e4c683f754f69300b9d0f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:0dc18e5c75390fcbff95fd629727fb8561efc9dbf88875aa37e59b204876d016
Ctrl.salt = hexsalt:f2f46cf85e6dc82602eb1169a27aaa17185af5fc26ac8b4cc466f9be2f1b3882
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = a308d6301c37989245c04c359fbc2cf2b07f8c4344bf37604cdb27c0e631a3ee
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a308d6301c37989245c04c359fbc2cf2b07f8c4344bf37604cdb27c0e631a3ee
Ctrl.data = hexdata:439b9eb6fc068e5c2709a044c98073d498d3151eab2237fc285093c6486fae8d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = d2ac822767a490a8087be7adcbcb2e213a98c5bed4a54c827ad2fc19ac0084e1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:a308d6301c37989245c04c359fbc2cf2b07f8c4344bf37604cdb27c0e631a3ee
Ctrl.data = hexdata:439b9eb6fc068e5c2709a044c98073d498d3151eab2237fc285093c6486fae8d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 06613eeefdc210ff2624820604ae88d7160de324b8bfbb279b40bb0caea4b251
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:a308d6301c37989245c04c359fbc2cf2b07f8c4344bf37604cdb27c0e631a3ee
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 36c02d8a722e424007309cf655c90d735ce618e7d3586a4c430253f3467e7ece
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:36c02d8a722e424007309cf655c90d735ce618e7d3586a4c430253f3467e7ece
Ctrl.data = hexdata:a0fe2ba2eee7dfc1431e4a0098f17146ccf75d424d4df5a325b10b130ca8a140
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 382e756a88f3dde4b775bc30064877563716e48e05c70382c4b4717b804f7900
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:36c02d8a722e424007309cf655c90d735ce618e7d3586a4c430253f3467e7ece
Ctrl.data = hexdata:a0fe2ba2eee7dfc1431e4a0098f17146ccf75d424d4df5a325b10b130ca8a140
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 08fbcf658bf0ccd792bf9486c8304d5cec3e066fb310e14c642b5e838a80cec2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:36c02d8a722e424007309cf655c90d735ce618e7d3586a4c430253f3467e7ece
Ctrl.data = hexdata:a0fe2ba2eee7dfc1431e4a0098f17146ccf75d424d4df5a325b10b130ca8a140
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = af263cbe584c6257872182e4259e90dacce4e857c0971e63e90ef68313241f09
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:36c02d8a722e424007309cf655c90d735ce618e7d3586a4c430253f3467e7ece
Ctrl.data = hexdata:db71bdb1435bf594988f4288e9c8aa9d1ffc400d3b74a8f166dfff72ac2d251e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = f79d066e915aa9fdc491b522536fd389309d93b9e386adbeabf276bc18826a4d
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:1c48bc355454d145972bf3e2fea127c34443a214ca2df0873d78db5610fd5598
Output = 4c0857f54a8332d09dfdd41043a87d758b2ffb86bff9ab972ba9c0afba25b017
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:4c0857f54a8332d09dfdd41043a87d758b2ffb86bff9ab972ba9c0afba25b017
Ctrl.data = hexdata:a65f378bd6b9e498256afc30f268d87f2b93e95925e361f5a5f35198457bd3f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 6e9db9369095c899626c20463ddd98d1885e41dac533981bb0d0352ef9874697
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:4c0857f54a8332d09dfdd41043a87d758b2ffb86bff9ab972ba9c0afba25b017
Ctrl.data = hexdata:a65f378bd6b9e498256afc30f268d87f2b93e95925e361f5a5f35198457bd3f0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 93877fd5a8a4b5323b8561cfbb0e7cff34d63db1f6c0783de9edaee832a93026
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:ca08248684cb6529a53900f08a28734f5722193c21e8b01b99b968a4711f67e6
Ctrl.salt = hexsalt:4c0857f54a8332d09dfdd41043a87d758b2ffb86bff9ab972ba9c0afba25b017
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = e60e0c3fc3dc3c54964089b1211fda1e217e9ef7df4b37611fefca1309550da9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:e60e0c3fc3dc3c54964089b1211fda1e217e9ef7df4b37611fefca1309550da9
Ctrl.data = hexdata:4b485da6cf1df86af0757b10a0f99d422a667444c42ea732c1ad9eb91b8a1200
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 18764172b9bf192527e7640b553c49785f49b17c139aec41d9ca711ad5c5aaa5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:e60e0c3fc3dc3c54964089b1211fda1e217e9ef7df4b37611fefca1309550da9
Ctrl.data = hexdata:4b485da6cf1df86af0757b10a0f99d422a667444c42ea732c1ad9eb91b8a1200
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 07f5837669456a7a5cbadb1f88e8faa50a620e1a0577ef3c4304f4679596ba4d
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.salt = hexsalt:e60e0c3fc3dc3c54964089b1211fda1e217e9ef7df4b37611fefca1309550da9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 5d0803e36d1597791f4cbbe23b21571776ac0319e8e4f7023254a8d412dd6c0b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d0803e36d1597791f4cbbe23b21571776ac0319e8e4f7023254a8d412dd6c0b
Ctrl.data = hexdata:5cef22380661440bbbe9d74f573a9329345481843b2512ef1a9a4f5d0d263f78
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 1f145b433d726ad8aed2b3d7a91dbf7dfee700a3a82650c496785c898b7be0f8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d0803e36d1597791f4cbbe23b21571776ac0319e8e4f7023254a8d412dd6c0b
Ctrl.data = hexdata:5cef22380661440bbbe9d74f573a9329345481843b2512ef1a9a4f5d0d263f78
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = ba32a25990ad0d52861f0e24e283b1bf2f229c14649867415b8d0ac3c1d55b8e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d0803e36d1597791f4cbbe23b21571776ac0319e8e4f7023254a8d412dd6c0b
Ctrl.data = hexdata:5cef22380661440bbbe9d74f573a9329345481843b2512ef1a9a4f5d0d263f78
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 8d95c36d97d0d724a4a925d30db54fa9a00a7f40491617149f354f6a22abde69
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-256
Ctrl.key = hexkey:5d0803e36d1597791f4cbbe23b21571776ac0319e8e4f7023254a8d412dd6c0b
Ctrl.data = hexdata:9581b3ed9dff21ace07228323489626f403dda4bf997885e80e23edaaa988d52
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 62750f7ddf116735e656c7014c9243b6c57a84f0ba6088f28deea97a91c6f2d3
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:910113657bdc298e97ebedd20511eb096f973f55fee0fcbb2d9cb5a686e7ed200ed417839066bbea4c05209434590daf
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = b7af828d2d478d384d2a3c49e4068156de9ecefce3deebf281e2cb0947cd83dd28d1472bcf4b0484a9e2fd3b33d3cb81
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:910113657bdc298e97ebedd20511eb096f973f55fee0fcbb2d9cb5a686e7ed200ed417839066bbea4c05209434590daf
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 98aaaed14b4ea329d9e1c2c4ae4e1c9fc74b58ca5748acb35be214cc106e23675ba8e7e95bea77aabdcaff37b7180953
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:69ebe2a6f0cbc6bda4f1fca02786df58a9abde209e15ca02ed167ecdaabaf78c26
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 19ff34d4b42a1a7066b34d60e3bfde4458eba1efd3fcd6ef1971824ca56468c1fb2cd35acc7e3ffbe95b3e59855c0b15
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:19ff34d4b42a1a7066b34d60e3bfde4458eba1efd3fcd6ef1971824ca56468c1fb2cd35acc7e3ffbe95b3e59855c0b15
Ctrl.data = hexdata:53d60b426068e463f9d09308a007d0ef27bc8d2001f045afa2d7a3888d47b1d774ab3e7102ab901065b8e242dac6722d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = c087814576d3a18ec8cf9d7e0fd4e720f0e32cada8bbfc59d048376d57334ac6847dc2f2e642fcd5f100e187d728c626
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:19ff34d4b42a1a7066b34d60e3bfde4458eba1efd3fcd6ef1971824ca56468c1fb2cd35acc7e3ffbe95b3e59855c0b15
Ctrl.data = hexdata:53d60b426068e463f9d09308a007d0ef27bc8d2001f045afa2d7a3888d47b1d774ab3e7102ab901065b8e242dac6722d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 0d6a7b15387fb7d8a748a07ddd4b6dc3ed9854410cb6c18515d013a8b0496cb3df1bbad7fa4ca64bec04e42362315269
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:19ff34d4b42a1a7066b34d60e3bfde4458eba1efd3fcd6ef1971824ca56468c1fb2cd35acc7e3ffbe95b3e59855c0b15
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 5fc2bcd2dc4427578c82386ec0a44b5837da7a7560ec9890609b0ce626d79263364adddeedb046b494da9daed06c2de8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:5fc2bcd2dc4427578c82386ec0a44b5837da7a7560ec9890609b0ce626d79263364adddeedb046b494da9daed06c2de8
Ctrl.data = hexdata:fbb73fd2d7c15c8ce25627f3ca7d61d1facebcfb6f9386c692479521a96973499ec24db280a12fc7bb83bfe32dc0a9ca
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = eb4e606e2198835b8733a026ef1c97bd7a8df3da598f32494ebc5809cf697c7999e0154c56399a60ec20b705d50ed9e0
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:5fc2bcd2dc4427578c82386ec0a44b5837da7a7560ec9890609b0ce626d79263364adddeedb046b494da9daed06c2de8
Ctrl.data = hexdata:fbb73fd2d7c15c8ce25627f3ca7d61d1facebcfb6f9386c692479521a96973499ec24db280a12fc7bb83bfe32dc0a9ca
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 580bb4a16e81ba7b21b1ae7688037bd76684dd8e5e1e9254732685acdcd44dd1a1ce8126815fcdb42f47ac6d8ac7d4b0
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:5fc2bcd2dc4427578c82386ec0a44b5837da7a7560ec9890609b0ce626d79263364adddeedb046b494da9daed06c2de8
Ctrl.data = hexdata:fbb73fd2d7c15c8ce25627f3ca7d61d1facebcfb6f9386c692479521a96973499ec24db280a12fc7bb83bfe32dc0a9ca
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = caa396d3f1b8bfce67752855df1b5150b34613f74d6f02d6f1c3d07cf1f64b1c69d8e4cb129de293de5addca635467c9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:5fc2bcd2dc4427578c82386ec0a44b5837da7a7560ec9890609b0ce626d79263364adddeedb046b494da9daed06c2de8
Ctrl.data = hexdata:37543f85f9c51e29d5bf1efeb8e82d35633fc1e53a6947453f579cbf3424e036b2d287b068079f9852cb2ed0b1577f65
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 0cd8131737f5411766ae31c739a8cf9c6156623c7e8a61960b368469db3df24be159f0dc3ea33489db810edfa38798bc
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:a807a39d8f59bcad113f00464839a49f2ea7bb3bf10ae124e706cbaef8438a69529d0423049659f41ca3bc879f135714
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 9ea652bed125a4f5eb038bb92b45bb2206a885536280cdd33dc04837b9f243ce60ac08f6a1b60e410e1cbe6da2d1bfa5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:a807a39d8f59bcad113f00464839a49f2ea7bb3bf10ae124e706cbaef8438a69529d0423049659f41ca3bc879f135714
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 379bac9dbc4c02bd651db88b2109402259526992a6be8051052046baafabfcba43ecc95b85b212eefeb82abb9bf6342c
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:afd957f59d3891c7dc0274a3f017f1002e81694fdc48890f9b1f174eea8335ab20
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 040af5bc880d44dad19c2960264c1f495f6e3a06096aec1787032169797f66f4167cbbba2c2a78748ce7117baf8e7bac
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:040af5bc880d44dad19c2960264c1f495f6e3a06096aec1787032169797f66f4167cbbba2c2a78748ce7117baf8e7bac
Ctrl.data = hexdata:fee3918af93355c76f410e931147484daebf34d71a32e819f92f294e083880113542ae4f2046bd047abee01919723690
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 8cf001ed150ee074eef37bc5ed369b46e5f47b022cdafc1feb8b506037983e2d7344ee7836348d66ad945507adea2852
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:040af5bc880d44dad19c2960264c1f495f6e3a06096aec1787032169797f66f4167cbbba2c2a78748ce7117baf8e7bac
Ctrl.data = hexdata:fee3918af93355c76f410e931147484daebf34d71a32e819f92f294e083880113542ae4f2046bd047abee01919723690
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = f920e99ce8b8765d9a4656ee00da97d5c26f9c9194202de256a27be7414ef6292bd0694ec07b6a7ceb50d31cec440645
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:040af5bc880d44dad19c2960264c1f495f6e3a06096aec1787032169797f66f4167cbbba2c2a78748ce7117baf8e7bac
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = e131d6c67661e34de72558ea5176e3bc791cac2225fe62978aa0717c8e9b36c5e1341caaa118dd02e774b2138c460694
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e131d6c67661e34de72558ea5176e3bc791cac2225fe62978aa0717c8e9b36c5e1341caaa118dd02e774b2138c460694
Ctrl.data = hexdata:963e5b5cdf40ed5f735727034dfa1440f34866d5dc7cdd573ce4e93e75bc9570dcff0ce7ab6ad393c8d6984d5bf7868b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 7053327731504219b522361396d6aba6d401bb4b5eabb9d05065c97b30b1cf704418740437b5afe6f4c3e1663d4fb602
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e131d6c67661e34de72558ea5176e3bc791cac2225fe62978aa0717c8e9b36c5e1341caaa118dd02e774b2138c460694
Ctrl.data = hexdata:963e5b5cdf40ed5f735727034dfa1440f34866d5dc7cdd573ce4e93e75bc9570dcff0ce7ab6ad393c8d6984d5bf7868b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 9b8e8196e2aaf0e1d8840fff8d17f7b2911a4f8cfd06a30d05a28792b4c6800bd0f0bac01552945733e7995ec67573f3
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e131d6c67661e34de72558ea5176e3bc791cac2225fe62978aa0717c8e9b36c5e1341caaa118dd02e774b2138c460694
Ctrl.data = hexdata:963e5b5cdf40ed5f735727034dfa1440f34866d5dc7cdd573ce4e93e75bc9570dcff0ce7ab6ad393c8d6984d5bf7868b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 48f982ca8046c850fe5431eee4c043e78c0a96c7ba87dcc97b9afc69ae2d0dd18f9fd2054f811976774098a91f7917b2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e131d6c67661e34de72558ea5176e3bc791cac2225fe62978aa0717c8e9b36c5e1341caaa118dd02e774b2138c460694
Ctrl.data = hexdata:5f458dd3261694b6a3f57918a94dfeb7c77851441bfee4dd2d118051abdb945d37c74bee575fe52d71d6ff696991893a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = f3a292849c0daa0abf9257cdd5b5c2f92092a904a80f017d1020fbe33637e2733d583332aa212d942d70f7fe30f15677
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:02b9fd278f70225406d715dd78eb54405fd19f9556e4a8a77882c6a63f9dc220944f27030c78ac1262e382fa95feb5c8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 3cec2e60c6386fa9edad0635132eab0ece3eee9bd71e8884813cca61d3da3a7dfbfd9a4775a9e69510fb9455cd9bdcd9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:02b9fd278f70225406d715dd78eb54405fd19f9556e4a8a77882c6a63f9dc220944f27030c78ac1262e382fa95feb5c8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 80c3e31156ad5bfd762b27d3f30bfa8a12f26eb0eb41ffe5cb155187b9a50178856f54e97076bb57518caad873cbd9d3
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:0ccc950ef8aa96c6b282e24741769bfb271d08a8b59324f6b08c6ef700d9a57049
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = af0b91b6da3e203922eeb31f60926c0706c8a1faa6428599c9d2f6456b91aec153ef978c93a949e4d40e45afc98fd3ef
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:af0b91b6da3e203922eeb31f60926c0706c8a1faa6428599c9d2f6456b91aec153ef978c93a949e4d40e45afc98fd3ef
Ctrl.data = hexdata:44aee84be26ed9e08590afc301ef29fe2c6ce1aeba54004b4840f2d42433edc310a4401545cc80c0db2adbc7764dc5a1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = cf114347819d9818f848be8662e1d88125558b48c5aa85b9fc51cb21934eaf6821c281beef7e8daece6ab7e48bdde433
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:af0b91b6da3e203922eeb31f60926c0706c8a1faa6428599c9d2f6456b91aec153ef978c93a949e4d40e45afc98fd3ef
Ctrl.data = hexdata:44aee84be26ed9e08590afc301ef29fe2c6ce1aeba54004b4840f2d42433edc310a4401545cc80c0db2adbc7764dc5a1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 531d87cc6e5319d60dd7b3b068249930572459219ec6d7dac14ebe6e79619f21a2cc370086f2090ac52e4e361d715ca5
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:af0b91b6da3e203922eeb31f60926c0706c8a1faa6428599c9d2f6456b91aec153ef978c93a949e4d40e45afc98fd3ef
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 93fcd922322a65134cbb01574797abfde8d5d0dab98d362646fa625d3a970ff5030d8f92b6fc0d2920bb600fd10ef3f2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:93fcd922322a65134cbb01574797abfde8d5d0dab98d362646fa625d3a970ff5030d8f92b6fc0d2920bb600fd10ef3f2
Ctrl.data = hexdata:93aee4415cb45f8548045fbc1b0391edbb837d6e8fe73958c951e30347490957b71642f43249ae13c4d0f36955fa2c29
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 92f638eaff114606821a19f881474502b3e761f70dc6b942280fbf2bc2b37976b4dc9c92bedb3c62e0a57d0d51259f75
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:93fcd922322a65134cbb01574797abfde8d5d0dab98d362646fa625d3a970ff5030d8f92b6fc0d2920bb600fd10ef3f2
Ctrl.data = hexdata:93aee4415cb45f8548045fbc1b0391edbb837d6e8fe73958c951e30347490957b71642f43249ae13c4d0f36955fa2c29
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 4d46be5133166d6b700177efc6ae82d6f35532d2bb5e25b7e8dc4cccbe8f3a2c232002e3ed88dea06bdfe637e7f87f65
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:93fcd922322a65134cbb01574797abfde8d5d0dab98d362646fa625d3a970ff5030d8f92b6fc0d2920bb600fd10ef3f2
Ctrl.data = hexdata:93aee4415cb45f8548045fbc1b0391edbb837d6e8fe73958c951e30347490957b71642f43249ae13c4d0f36955fa2c29
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = bc93830f69c49b15adec691b878ad08eba5bef6e721464dca985473456864231bde995571e9a3762d5db89c9e76f792b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:93fcd922322a65134cbb01574797abfde8d5d0dab98d362646fa625d3a970ff5030d8f92b6fc0d2920bb600fd10ef3f2
Ctrl.data = hexdata:6847a6b4f5923482be779c96ab86e9f0e05d8b50d3deaa160f9806e53021d0eaac196371f01b0e523def730935ff5d60
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 35dae76a13277d942955c4a0ee6f03d540493184bb609be848d5ce0e0b3bdabfb62028e60eb006c1ef4dbcd5b5706e79
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:0bb979afa49117daa4a48360472aef44c6ba3d8fb56ff276e6c54aafd5d975c79880dece805db219641fc36bd2e0163e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 8523607e3e5c9af1847211985f78397ead777b35d4b105c5176593131f3530709c60c8585b44250d770a4635db1a9980
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:0bb979afa49117daa4a48360472aef44c6ba3d8fb56ff276e6c54aafd5d975c79880dece805db219641fc36bd2e0163e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 638a7cab97994346d8a0cbab1a2d62ab83c924d91a8e4cd0df1dfa5e2803ff0770d41dd5000a2e0794e06aedfa52e43c
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:cd6f89d27bd11c9256080283dbce48f51375f74ae31658cb811c0bf8f991f11311
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = a0fe7ee6173a30d2db09b9a3e6edf578bd78be4490e6f67ceb4f0325de123065ab1ef4aa8c4885fc410be0d537f4f113
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a0fe7ee6173a30d2db09b9a3e6edf578bd78be4490e6f67ceb4f0325de123065ab1ef4aa8c4885fc410be0d537f4f113
Ctrl.data = hexdata:f76083df586b29987add3fdef9656d763e2cedb1acfa6a8a2fc9bf0a3f8d89b9f4945bf31614239f224656f24f101a31
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = dfc278a206e08140fcfab6dbd56687bbf8279e5669c5272dc737654db955168de3e796c1b96dbd5f54ef31e578e228b1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a0fe7ee6173a30d2db09b9a3e6edf578bd78be4490e6f67ceb4f0325de123065ab1ef4aa8c4885fc410be0d537f4f113
Ctrl.data = hexdata:f76083df586b29987add3fdef9656d763e2cedb1acfa6a8a2fc9bf0a3f8d89b9f4945bf31614239f224656f24f101a31
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = cf79486a3d6be7736df39ea7127b32b6968f7cfed044f6f1fea84cd63361e11582689aa5b9c082c93c466e9265094da5
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:a0fe7ee6173a30d2db09b9a3e6edf578bd78be4490e6f67ceb4f0325de123065ab1ef4aa8c4885fc410be0d537f4f113
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = e69381a54a5236afa62a0fa2c97e39b52adb6cfe6811528af49c2888b196dece1df819a59e4b71f249455a585183d43b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e69381a54a5236afa62a0fa2c97e39b52adb6cfe6811528af49c2888b196dece1df819a59e4b71f249455a585183d43b
Ctrl.data = hexdata:383c7df1b7d34be920a4d9f9ac4ff9d9a8d0f3cf482983c1992270629ba70fcdb6d9fe80a24cee997a233596ad78a306
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 5f3cdcf3ba4ace0797f4057bddc682a08fc87f8dc1fc22ea081881bfdb4d12e304339ee2afd4de9d5f532656fab410a5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e69381a54a5236afa62a0fa2c97e39b52adb6cfe6811528af49c2888b196dece1df819a59e4b71f249455a585183d43b
Ctrl.data = hexdata:383c7df1b7d34be920a4d9f9ac4ff9d9a8d0f3cf482983c1992270629ba70fcdb6d9fe80a24cee997a233596ad78a306
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = ff655c4b338b8db54474a5f810cef029c9fcd96f7b264818692695373f74585f20584fbf434d200f2b47862a797ed052
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e69381a54a5236afa62a0fa2c97e39b52adb6cfe6811528af49c2888b196dece1df819a59e4b71f249455a585183d43b
Ctrl.data = hexdata:383c7df1b7d34be920a4d9f9ac4ff9d9a8d0f3cf482983c1992270629ba70fcdb6d9fe80a24cee997a233596ad78a306
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 78a1e7c8f28704c2dc74ad35cfa88d79858449099daa274ff6fbc8c7ab60a00949e7c91f50bcc2f351af349fa1f4d912
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e69381a54a5236afa62a0fa2c97e39b52adb6cfe6811528af49c2888b196dece1df819a59e4b71f249455a585183d43b
Ctrl.data = hexdata:5d469943c925e80019b2e5e7c0556cfef6e6184125a1e9f1455fe7df95f8efbb5298f033c7a34a0433af8c804d4d08c8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 17fccc64a56ff0967de7552a4dbe131eba2fea98dab6ea1d8b53fa86ae73b6ba837d989080c2f3cb7199b533fcddca0f
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:a6189f3e10d03aded1fc28843f6a903ecc311595a9b65dd9099dd7fe00a495be739865040a612f8050cff809f20e1b20
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 7b4fbea544f26b5a16a26b9b9b45a76531871daca970f56fe121de31a718abfca41c041d0c7a5da3c65e6635e40a53a5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:a6189f3e10d03aded1fc28843f6a903ecc311595a9b65dd9099dd7fe00a495be739865040a612f8050cff809f20e1b20
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = bd94d381832c448f4ba15c98343152382b61903d0f4644ef19ce53a75507a3eae68cc24114aa67c6a6e42a20f9358e1a
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:6829094ea40dfe78cb9936cf95eff5888ebbdb087bb287b890ad2ab124f64d222e
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = f4559befac6c1502888c6f9c643a394d2e14431b87c7610308dacf7b51d391f3dcea4589e0f29a513b7cd545cbe90a43
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f4559befac6c1502888c6f9c643a394d2e14431b87c7610308dacf7b51d391f3dcea4589e0f29a513b7cd545cbe90a43
Ctrl.data = hexdata:b0c437bab8cc1d0cd8e0bf85f0b8d26f9e7585646b331a0c45065239dd1e7565b9988f7e8f8ea2912a015b2163481f3b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 11edee9dd7f7f70a1106b9db5096cb55acc0ddedbac1c042c9bbcc9ec95f60c7428af61fcb30f83e9f324a1d0833f743
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f4559befac6c1502888c6f9c643a394d2e14431b87c7610308dacf7b51d391f3dcea4589e0f29a513b7cd545cbe90a43
Ctrl.data = hexdata:b0c437bab8cc1d0cd8e0bf85f0b8d26f9e7585646b331a0c45065239dd1e7565b9988f7e8f8ea2912a015b2163481f3b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 7836f550debcc3933937f7d04fc6a5d5150f220a5bd6ea6c743aa843027ea8c97220b79f746d08f8504a61f7b5815e11
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:f4559befac6c1502888c6f9c643a394d2e14431b87c7610308dacf7b51d391f3dcea4589e0f29a513b7cd545cbe90a43
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = aeac9809af9a91381fd637dcd94738985b2183e20f799ff8f8493feab9710f941ebc100c37e44938dad9cfa3b5952b02
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:aeac9809af9a91381fd637dcd94738985b2183e20f799ff8f8493feab9710f941ebc100c37e44938dad9cfa3b5952b02
Ctrl.data = hexdata:b006f4dfe30e7375c58ae7ab7309b10774466d1ce0f785b71ecf8d653e6a02767f29739b34f2f624b8cb8d074cc0808d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = b13cde3c6dce710537f6eaa538feef006710081d4f600e2fe3e54c82c217db99cb0d616b79b43f0a3b4c6d477f379432
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:aeac9809af9a91381fd637dcd94738985b2183e20f799ff8f8493feab9710f941ebc100c37e44938dad9cfa3b5952b02
Ctrl.data = hexdata:b006f4dfe30e7375c58ae7ab7309b10774466d1ce0f785b71ecf8d653e6a02767f29739b34f2f624b8cb8d074cc0808d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = f31d0fc7abc50b7b4e671eb15441b559d635f928b3fb406362107d6312aa2aee8e6edc5904f275e145bf699b43e91dc9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:aeac9809af9a91381fd637dcd94738985b2183e20f799ff8f8493feab9710f941ebc100c37e44938dad9cfa3b5952b02
Ctrl.data = hexdata:b006f4dfe30e7375c58ae7ab7309b10774466d1ce0f785b71ecf8d653e6a02767f29739b34f2f624b8cb8d074cc0808d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 18dd5faaa96109c04f4f1ebb454b259aeedf288938c75bcb53213789d5efb450cb068e7fc82f8ddf934108390d1b8824
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:aeac9809af9a91381fd637dcd94738985b2183e20f799ff8f8493feab9710f941ebc100c37e44938dad9cfa3b5952b02
Ctrl.data = hexdata:097d40e52726a966258ad8860a005bfc09d00502ad4a8bd741188d95a1501bc2468bb4ace05aa6cccb3ce0664de814a6
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 3b5fc3f285bb93f59aa710cd294443a8e2835ebe170ef653222ca38bbacbff38251a836f8fd0705c9e734f547d89b5b0
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:8d552361c11a65c87f2118e14bd4fb35b3a3191bb3ae6b4877e4d6a8ee7a221956f4
Output = 4820ed67366026f4c3deb5709470ba3fd1101224f484195c6008c3e4a92282c60f008e5fa22a88e8d4cf238c0f634a30
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4820ed67366026f4c3deb5709470ba3fd1101224f484195c6008c3e4a92282c60f008e5fa22a88e8d4cf238c0f634a30
Ctrl.data = hexdata:144f8d45a013c35156c2337c3ed5e888d19f9d52372e95e1d25b908cee682b6637ee17d627badaed40c8782e41790c52
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = b6aeb75145d044afb9091680cc3e1c94e0ad92994f5986e5cfb0441d12bad5be3727b6d41e16a395704fd30e4a04f28a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4820ed67366026f4c3deb5709470ba3fd1101224f484195c6008c3e4a92282c60f008e5fa22a88e8d4cf238c0f634a30
Ctrl.data = hexdata:144f8d45a013c35156c2337c3ed5e888d19f9d52372e95e1d25b908cee682b6637ee17d627badaed40c8782e41790c52
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 9eaa4fb09fb6cd5c94c0ead11d065c0fe846bad38098b9afaa258682e3f9ab0a6f2c14fedec5a9733d08814ce2c9484f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:4820ed67366026f4c3deb5709470ba3fd1101224f484195c6008c3e4a92282c60f008e5fa22a88e8d4cf238c0f634a30
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = fa9580b220e7aebc4bd623b9c2d402d060f47bfb32b8e86c4f69b6184282af4b513d58d7759397316e0e570c475d34b0
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:fa9580b220e7aebc4bd623b9c2d402d060f47bfb32b8e86c4f69b6184282af4b513d58d7759397316e0e570c475d34b0
Ctrl.data = hexdata:40912a3cdc9623d86e6db201b56afe6a354335d9635b1c2478db75bb4a83554b3aef392205d0f226485db014ac22ad3b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 3edeed16646bfd7c54b088155f2fb9ecab99cc7db84f8c1a3db0cf0f6164d77e451dfaaab26f0b65c9cf88726aa84c90
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:fa9580b220e7aebc4bd623b9c2d402d060f47bfb32b8e86c4f69b6184282af4b513d58d7759397316e0e570c475d34b0
Ctrl.data = hexdata:40912a3cdc9623d86e6db201b56afe6a354335d9635b1c2478db75bb4a83554b3aef392205d0f226485db014ac22ad3b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 3a74c1f904c563bdab90b0f5b5de4a444f0da7395df6fed82352af9233060904640d98dbad43dae0a99483d588d68ef0
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:fa9580b220e7aebc4bd623b9c2d402d060f47bfb32b8e86c4f69b6184282af4b513d58d7759397316e0e570c475d34b0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 4a8758b949bd64907c664f24ef82deccd40ffe460279091ca07574f811f84fb80437755321f062764de435f14406b6c7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4a8758b949bd64907c664f24ef82deccd40ffe460279091ca07574f811f84fb80437755321f062764de435f14406b6c7
Ctrl.data = hexdata:61ff39f242bd6fee91ff507ba8bd39eba3616560202284a11c72a8c8cd5d80ce53c7a77135503c4a24544a62b47b933d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = b4b6d860927ac8b40e25fe6b813c7ea70ef4568528cad8ab1ebdd4854bcc0fe3b28786592dfd964e67eba564b1c554ea
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4a8758b949bd64907c664f24ef82deccd40ffe460279091ca07574f811f84fb80437755321f062764de435f14406b6c7
Ctrl.data = hexdata:61ff39f242bd6fee91ff507ba8bd39eba3616560202284a11c72a8c8cd5d80ce53c7a77135503c4a24544a62b47b933d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 8cf769bed70425785e28d1e78129cd9eabef64327ebbd96ebaca547b0d28580f1db20ac110eef29d82ac40813f9a044b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4a8758b949bd64907c664f24ef82deccd40ffe460279091ca07574f811f84fb80437755321f062764de435f14406b6c7
Ctrl.data = hexdata:61ff39f242bd6fee91ff507ba8bd39eba3616560202284a11c72a8c8cd5d80ce53c7a77135503c4a24544a62b47b933d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 0aff8ca80517eb3391f25ad81a5eb9307637d352d07b5047190fc384ed1b536b52b0b25a8349d7c8bab3923cbe10f63c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4a8758b949bd64907c664f24ef82deccd40ffe460279091ca07574f811f84fb80437755321f062764de435f14406b6c7
Ctrl.data = hexdata:5ac100d7b27ab146f0eb4766005ce1b1b49ffc087991ccc06552c23076b009be34ec0523ed3c33836c6e4007de3e592d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = c68a76b70f6664359aed4a054ea30ce1f2e4a91b0fd99b1effc6969fd1d9be98a09f685e2aae7558a136185ab36e5e4f
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:2ebcb08306728f71249a9c9ca9d53115ba0fd2cc0b63bf690f9236b2516a47d0696d
Output = 38368374565fbc9298eff41132e8e4a6468b9ce87b3138ac6007e078018960958494f7b56ac71a0c1dc39c7b62fa3465
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:38368374565fbc9298eff41132e8e4a6468b9ce87b3138ac6007e078018960958494f7b56ac71a0c1dc39c7b62fa3465
Ctrl.data = hexdata:2a15af6fe2e7031563a612f2c99a05bacaff3c624238ef80d82e5af8579c169a40166d954f7784087bce56f39c26f55d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = f440521d6595c7177d167bb3516f896bf47d362ab140f55306b7da7a9df1fd936e0f619d0eb6806fc6d04437f1e86747
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:38368374565fbc9298eff41132e8e4a6468b9ce87b3138ac6007e078018960958494f7b56ac71a0c1dc39c7b62fa3465
Ctrl.data = hexdata:2a15af6fe2e7031563a612f2c99a05bacaff3c624238ef80d82e5af8579c169a40166d954f7784087bce56f39c26f55d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = cc9a09d1f6e7479fc48ac997d83f1a9af0d5301d10d8fab41bf0b29c1e464118e58dd7100f7633c0a59eeff50a5773ab
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:38368374565fbc9298eff41132e8e4a6468b9ce87b3138ac6007e078018960958494f7b56ac71a0c1dc39c7b62fa3465
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 383461863a7cb4e697e2c49e991de737172fd2a66225e49e49fd640555e5bda70c0d4058a8b32af5ec3de74eb5fb98c7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:383461863a7cb4e697e2c49e991de737172fd2a66225e49e49fd640555e5bda70c0d4058a8b32af5ec3de74eb5fb98c7
Ctrl.data = hexdata:3fe1067b88b96241527495f4ac60cf866692da7dda56bd39e4cccb6d615dc64dff6f519d3d3112ff2cf6b6b728835da1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 86c7556537dad08499e20f9a424e0e1683af4a53617acb763881482b3f3cc78336246f81a1e5cc62cd699920eff0a9cb
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:383461863a7cb4e697e2c49e991de737172fd2a66225e49e49fd640555e5bda70c0d4058a8b32af5ec3de74eb5fb98c7
Ctrl.data = hexdata:3fe1067b88b96241527495f4ac60cf866692da7dda56bd39e4cccb6d615dc64dff6f519d3d3112ff2cf6b6b728835da1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 67391f7c78f569458c5216784af513f5ea049e3d2b3a120fda04ec5d79b659067fc1f8bac821bfa65b8585c1d974919e
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:383461863a7cb4e697e2c49e991de737172fd2a66225e49e49fd640555e5bda70c0d4058a8b32af5ec3de74eb5fb98c7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 841757ceebb2cd7ea33c7a6b54efa0f14ca4f5fd1a65da887dcd96feb35b1284737b6234202ad25aaecf6fb67d702af5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:841757ceebb2cd7ea33c7a6b54efa0f14ca4f5fd1a65da887dcd96feb35b1284737b6234202ad25aaecf6fb67d702af5
Ctrl.data = hexdata:504aa70ba600d023e5e809c4be7e6d9c102c15417b5d0f810c41d16bd692ece5e840236cd5b9c10055e67a7968f7f544
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 96a17b111ac35dbb36ef4e581c96b4c6cae7e881adaf234c2455c1d8ad16089df1ad2e52141ef755b0476ccd618770fb
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:841757ceebb2cd7ea33c7a6b54efa0f14ca4f5fd1a65da887dcd96feb35b1284737b6234202ad25aaecf6fb67d702af5
Ctrl.data = hexdata:504aa70ba600d023e5e809c4be7e6d9c102c15417b5d0f810c41d16bd692ece5e840236cd5b9c10055e67a7968f7f544
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 98b00bc80a58a985dd722ee096df34e1be84f0bda2d57abe2b9f9c6852439805d0400e0f1b1647f38fdbe65f148ab708
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:841757ceebb2cd7ea33c7a6b54efa0f14ca4f5fd1a65da887dcd96feb35b1284737b6234202ad25aaecf6fb67d702af5
Ctrl.data = hexdata:504aa70ba600d023e5e809c4be7e6d9c102c15417b5d0f810c41d16bd692ece5e840236cd5b9c10055e67a7968f7f544
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 8b1a1cbae365cbb11dc43033954694ed7d380c6ebb2e7be69a6919f89e0508769f8ef8428a86b0448e5e89f07a7f2337
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:841757ceebb2cd7ea33c7a6b54efa0f14ca4f5fd1a65da887dcd96feb35b1284737b6234202ad25aaecf6fb67d702af5
Ctrl.data = hexdata:7e9a0c28e3f74322aba45bd272aaa50dc6b980ac6df6264673123bbacd366cf4c34b4f21d9c4175f88ca66e00b51ed4e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 656905d7ea03b8b0d4b3205f8d6f8a0a94a38fb502f6cbd656856ea39ac1e56f6092a8cd4146bfccc34694cf933ccf5a
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f83d4d1b185c8048bf809417aff978f5a11e273f85f32b5d300023862311fb3d065c
Output = 34d31b6d6e5fd67911f3acef72e9431ee39299a248ce7ce86a7b0f535a76b0a6a3fcf77b32427c2e9c60afca2505b358
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:34d31b6d6e5fd67911f3acef72e9431ee39299a248ce7ce86a7b0f535a76b0a6a3fcf77b32427c2e9c60afca2505b358
Ctrl.data = hexdata:51ff1b75137890323881e92e02f181b4bebc57a83d99962716e288ebe9407c052d13ca2f05e480b8188ff159713f7e60
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = b1f6485f84452614abbc9747e660e6b55ecf118fce063aad511840adeb91c5f5fedc08098f5a74e41b6e5cf0ce23652a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:34d31b6d6e5fd67911f3acef72e9431ee39299a248ce7ce86a7b0f535a76b0a6a3fcf77b32427c2e9c60afca2505b358
Ctrl.data = hexdata:51ff1b75137890323881e92e02f181b4bebc57a83d99962716e288ebe9407c052d13ca2f05e480b8188ff159713f7e60
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 12025b376c8629f261864e978feeff98ab1a1212e84c88248159bea4187210c012059fad3758651b37861bc550f3c0be
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:34d31b6d6e5fd67911f3acef72e9431ee39299a248ce7ce86a7b0f535a76b0a6a3fcf77b32427c2e9c60afca2505b358
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = b5d00844fc22b643dde3edc0454559eb01d33e57477ac980542aade6f8a3ccbf4502f0381489ed1fe8e74c966f1c3564
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:b5d00844fc22b643dde3edc0454559eb01d33e57477ac980542aade6f8a3ccbf4502f0381489ed1fe8e74c966f1c3564
Ctrl.data = hexdata:f0b08322d42922a77fbf3e4830aacfb34a7bf85ac255ae7d1f39ee39f9b07c2a88bc5e41912c6a97d0f54996df663e04
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 6aabce40a3acc0e953db1cb8b21e47d4644e108324aa4058f9ca2703da1c4500f78ad47287a441d13dbe1f5a98a97887
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:b5d00844fc22b643dde3edc0454559eb01d33e57477ac980542aade6f8a3ccbf4502f0381489ed1fe8e74c966f1c3564
Ctrl.data = hexdata:f0b08322d42922a77fbf3e4830aacfb34a7bf85ac255ae7d1f39ee39f9b07c2a88bc5e41912c6a97d0f54996df663e04
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 4d0f32ce9a86530a1f9cad218be9f38ecbd50f1deb30bf42b450e93bce059a98d25c1be9d918f6b1ca9ddcacdd9b4db8
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:b5d00844fc22b643dde3edc0454559eb01d33e57477ac980542aade6f8a3ccbf4502f0381489ed1fe8e74c966f1c3564
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 979a7a7cbaf194be9765a1a090454d7fcd1eee2908ffaa93b865504817177d29c6e10b1d59e559a73034c6f1f3021e68
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:979a7a7cbaf194be9765a1a090454d7fcd1eee2908ffaa93b865504817177d29c6e10b1d59e559a73034c6f1f3021e68
Ctrl.data = hexdata:48f7b41404c75cc97a6f78ba395606e8efbf1d25a6d174835a45fdfc7debf3ebf5e8e5f264834804562ceaa748566714
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = cf3a30ab60be054d04ff82fd94bb296403a1f51b630ba13df261acea3a648f19f32777b2ad568c084c317401af7e6201
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:979a7a7cbaf194be9765a1a090454d7fcd1eee2908ffaa93b865504817177d29c6e10b1d59e559a73034c6f1f3021e68
Ctrl.data = hexdata:48f7b41404c75cc97a6f78ba395606e8efbf1d25a6d174835a45fdfc7debf3ebf5e8e5f264834804562ceaa748566714
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 86b6f7a7a937a30a1ef165da03141270f40f9b8bdb84bed8ca200984b7415e2f5ab2eb663a8ea4f70d4c5613318c4d7c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:979a7a7cbaf194be9765a1a090454d7fcd1eee2908ffaa93b865504817177d29c6e10b1d59e559a73034c6f1f3021e68
Ctrl.data = hexdata:48f7b41404c75cc97a6f78ba395606e8efbf1d25a6d174835a45fdfc7debf3ebf5e8e5f264834804562ceaa748566714
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = cf6b0c13f121942acd855da7f2658dfdc59c816290664f7e8c8750d38d961a87e663e6c59f5b89b8477738eeaa76dc40
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:979a7a7cbaf194be9765a1a090454d7fcd1eee2908ffaa93b865504817177d29c6e10b1d59e559a73034c6f1f3021e68
Ctrl.data = hexdata:8b958cce832b7cb2381a90cf82ebd72ee8a89cd804ffde338e707603ce544db3a11cd9afa317751b48d959c750047d88
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = c947b9b68f77e4aef96ab3fe06f9214fecc7f6344b3558bfdd40dd3e6bbfcfe69cf0420f7a24998d8d387b6f85683038
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:042e669b52a5e563597e050b84755a685dfc62dba6a393af0aa1cb4047c2ae7442ee
Output = 4b43ba7c9138e1fedc23f76a3ded5621c6e4d45cda9edfb7e950a2e494624a976def2ec03d53d8829801dddf17989bfa
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4b43ba7c9138e1fedc23f76a3ded5621c6e4d45cda9edfb7e950a2e494624a976def2ec03d53d8829801dddf17989bfa
Ctrl.data = hexdata:fe13fda946943a323e2c160b7cda76454ce96bf0e51456311d0ce4ca484145bf1b00b8f7d692fa3bd1dacce0bee4e020
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 1779cfae5a472401c6df4971092f9e915b97d6dcf29e142dfbacff9c1781a8b8626d38296d7599a0de57593f3a7f7572
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4b43ba7c9138e1fedc23f76a3ded5621c6e4d45cda9edfb7e950a2e494624a976def2ec03d53d8829801dddf17989bfa
Ctrl.data = hexdata:fe13fda946943a323e2c160b7cda76454ce96bf0e51456311d0ce4ca484145bf1b00b8f7d692fa3bd1dacce0bee4e020
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 337022f95da2b5ced71d41e35fd4d63c44270af18c51df8abd54943ec5a583a95b218fcce741384b826e3c0f3b34cb45
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:4b43ba7c9138e1fedc23f76a3ded5621c6e4d45cda9edfb7e950a2e494624a976def2ec03d53d8829801dddf17989bfa
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 3b763cfd81c1c7cbfe55cd3de78334a2eea6e3a70e539ab048b3fef93cd6ff0fe6ba8c351cafff3057fe39e00652a510
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:3b763cfd81c1c7cbfe55cd3de78334a2eea6e3a70e539ab048b3fef93cd6ff0fe6ba8c351cafff3057fe39e00652a510
Ctrl.data = hexdata:a0bf8b6062a2de56aaab2b97e77f15bafc340bdb2b32e868959858d9e4b8b2da264aca4e7d16f6a58b14f6c4b42f97d4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 83272868aa2517b5163422b3b93b0f97a34541b27ce5a771f702b9ae088fd73eab282db646f23d5ce499de0f0503b95d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:3b763cfd81c1c7cbfe55cd3de78334a2eea6e3a70e539ab048b3fef93cd6ff0fe6ba8c351cafff3057fe39e00652a510
Ctrl.data = hexdata:a0bf8b6062a2de56aaab2b97e77f15bafc340bdb2b32e868959858d9e4b8b2da264aca4e7d16f6a58b14f6c4b42f97d4
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = d4a42d79131a720358da9f9a8a4b56684f127f8e2cd0bb03b4fd23e519924696062d1288fb416ec0fa90530fef576dc4
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:3b763cfd81c1c7cbfe55cd3de78334a2eea6e3a70e539ab048b3fef93cd6ff0fe6ba8c351cafff3057fe39e00652a510
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = fbd732c04b2e4c6a510cc909e676cce55615f951ca35b1d16692a1a4f597c65b48e5ebdbf342295c90c19ef966242570
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:fbd732c04b2e4c6a510cc909e676cce55615f951ca35b1d16692a1a4f597c65b48e5ebdbf342295c90c19ef966242570
Ctrl.data = hexdata:fe4cd2c6305e333fe3e1be7d554ccd18777112af181444ee9dbf08b27789d56442b9062ee9e4bc9d32d75a90df01aa97
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = b85370eea397bbff07af997282e64d95d16bab298a884b0e076174f2c1731371100e219c9ebe0395786c7571bdb1250f
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:fbd732c04b2e4c6a510cc909e676cce55615f951ca35b1d16692a1a4f597c65b48e5ebdbf342295c90c19ef966242570
Ctrl.data = hexdata:fe4cd2c6305e333fe3e1be7d554ccd18777112af181444ee9dbf08b27789d56442b9062ee9e4bc9d32d75a90df01aa97
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 058fcbc86aee05c1611daa116d823e4cbc90806048bc7c06818dc93f5a7cb88ffc556107da7cfdfd36322bdb46bac809
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:fbd732c04b2e4c6a510cc909e676cce55615f951ca35b1d16692a1a4f597c65b48e5ebdbf342295c90c19ef966242570
Ctrl.data = hexdata:fe4cd2c6305e333fe3e1be7d554ccd18777112af181444ee9dbf08b27789d56442b9062ee9e4bc9d32d75a90df01aa97
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 8ed866879bdaa4df92512530bc5ae51fee9fa014a128296cc4fc160650ac76977f2a8c2f9531e0ad492fec186c980ef9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:fbd732c04b2e4c6a510cc909e676cce55615f951ca35b1d16692a1a4f597c65b48e5ebdbf342295c90c19ef966242570
Ctrl.data = hexdata:57551aa889d3bd4633864a9975afbd649baffaa5608d3d3cdd7cb594f72de6af9b08f9b8fe0eb961275b07701a5dfef7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 6d74d0e7f3add328e3197f3e3b0fb77db4557347aaf8cc0eb826ad3cf31aa2144f52d15008c6d40dc077ab8a50557757
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:902e0cb930aa412f9ed919bb03ce94ffca2c0f59f0ab5e66695f65497162c41dfc2f
Output = a0b05f92044e706d497a4fa2e739220a091407e52c4c58bda817a11ee67842f6bce21bf1fc96421d9917b9d1f0783b8a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a0b05f92044e706d497a4fa2e739220a091407e52c4c58bda817a11ee67842f6bce21bf1fc96421d9917b9d1f0783b8a
Ctrl.data = hexdata:a67f985ae3cb2f7ea12ecf1c3f7175226d34899ea48003633321697301a2fa788e92673fa9a9538c8f992f0ef0885728
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = bd808dca2c7c0412abd5a747fb5fe5a1c644b43d8a8826fe11d48703448b38b9b6fe43f11241aef154fbd5e5e83e302d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a0b05f92044e706d497a4fa2e739220a091407e52c4c58bda817a11ee67842f6bce21bf1fc96421d9917b9d1f0783b8a
Ctrl.data = hexdata:a67f985ae3cb2f7ea12ecf1c3f7175226d34899ea48003633321697301a2fa788e92673fa9a9538c8f992f0ef0885728
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 19d1b4c9130572d7d4c5a8a81bfdde492455b63b2124f01c16d3b92a41467b2a58a63e1df7eeb85642dcb1591ae6c697
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:a0b05f92044e706d497a4fa2e739220a091407e52c4c58bda817a11ee67842f6bce21bf1fc96421d9917b9d1f0783b8a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = b2284374a83691c9f0f3d699faf8847ea9bad0bf3fd2467e6eb1537d9535e6db03b3b5efc828ad72b1a34bba1627eca2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:b2284374a83691c9f0f3d699faf8847ea9bad0bf3fd2467e6eb1537d9535e6db03b3b5efc828ad72b1a34bba1627eca2
Ctrl.data = hexdata:19bc6495e6322bf29e75002f1b519a95ca18790d13ed9473ee3805ea634047540a1c16eaa1713e60e38841431f7070fc
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 0a64d745563e72ffe3e5f7d1ad095cff283c0febc529ae317ae67ef0b5ed763f2749a1ccf932966eb13c7ea8916441f4
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:b2284374a83691c9f0f3d699faf8847ea9bad0bf3fd2467e6eb1537d9535e6db03b3b5efc828ad72b1a34bba1627eca2
Ctrl.data = hexdata:19bc6495e6322bf29e75002f1b519a95ca18790d13ed9473ee3805ea634047540a1c16eaa1713e60e38841431f7070fc
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 83136fc401f35789959110b7263dd754353aa97c8b9a0072f415220d86b92e9ab2d1020c18f605a9b367ac4940bebc9c
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:b2284374a83691c9f0f3d699faf8847ea9bad0bf3fd2467e6eb1537d9535e6db03b3b5efc828ad72b1a34bba1627eca2
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 4c6a0ac8b5cd96e6b694bbdbdf64eb516305e92f150270bc80fea736e12fab48bb96d0307a90c7a906a679f5f55d7860
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4c6a0ac8b5cd96e6b694bbdbdf64eb516305e92f150270bc80fea736e12fab48bb96d0307a90c7a906a679f5f55d7860
Ctrl.data = hexdata:3b4922e38c531328520150f640ad82720a6eef4ea94e06ec4ab32276b2d901710cb585bd86f47e92c1c6cf39961daf36
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = bf77e676173422a783ffde07e076541385aee04b82a6e3f26ea7249587b3596f68262e4c3ed4e6d56dfd75ed39512989
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4c6a0ac8b5cd96e6b694bbdbdf64eb516305e92f150270bc80fea736e12fab48bb96d0307a90c7a906a679f5f55d7860
Ctrl.data = hexdata:3b4922e38c531328520150f640ad82720a6eef4ea94e06ec4ab32276b2d901710cb585bd86f47e92c1c6cf39961daf36
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 31f8accd9f0f923c8b9f413840bd5f4a60b5693773022b78a25802e0e68f7ae33314dfc25ff2b1a1f32490df80c9e185
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4c6a0ac8b5cd96e6b694bbdbdf64eb516305e92f150270bc80fea736e12fab48bb96d0307a90c7a906a679f5f55d7860
Ctrl.data = hexdata:3b4922e38c531328520150f640ad82720a6eef4ea94e06ec4ab32276b2d901710cb585bd86f47e92c1c6cf39961daf36
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 488b7e09c0565137f22008362e7a4505f23ff1b24b0565322a11b6f4d3e1af7f06b8efdae18d74a7adee4e1e9753185c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4c6a0ac8b5cd96e6b694bbdbdf64eb516305e92f150270bc80fea736e12fab48bb96d0307a90c7a906a679f5f55d7860
Ctrl.data = hexdata:b8e14051b4e84bc66bd65601ed6b2e57e469e167e277e8c30c93bc52a6e836abad9b7ac6a81ecbd47ee9917a14154a2b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = e1f85e642615ceef410c6112339627607d3d1920ba168f5b10fed1a13a468401253df07323b826f156f0997bc584a937
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:ce2820a53357bc83ebd26b54d8ad48f4137f914034368dc705bfe852c2d87553
Output = 1aa52a5650ec46ab58a0e424ba92771077702ee242b752ee04036ca4ea43f16a092bbe2b5b09a4e34b98203e3b3ac0ec
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:1aa52a5650ec46ab58a0e424ba92771077702ee242b752ee04036ca4ea43f16a092bbe2b5b09a4e34b98203e3b3ac0ec
Ctrl.data = hexdata:ee61912f8d2cb51a3458a799af5c31a8ea4b2f9585fa63e71447289b3b6c6d979663580e6b115a652fed485c30cc535d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 53e8283806255b6eb3d1958fcf2b50d68e3226aab14b0fbd88529d6bfc6dcc88f90767aed25ba81baffa94e199ce8124
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:1aa52a5650ec46ab58a0e424ba92771077702ee242b752ee04036ca4ea43f16a092bbe2b5b09a4e34b98203e3b3ac0ec
Ctrl.data = hexdata:ee61912f8d2cb51a3458a799af5c31a8ea4b2f9585fa63e71447289b3b6c6d979663580e6b115a652fed485c30cc535d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = dcc274d12f153c7c23e02e5dfbafe90a65021a8100e09c891b790ea36092d6f694569fa5522ca823a7a6a026d25dd9b2
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a65f8b90963feda2e77ac0d6c33dc068a9f7eb4ec9878de9a002fbb90ca7d23c
Ctrl.salt = hexsalt:1aa52a5650ec46ab58a0e424ba92771077702ee242b752ee04036ca4ea43f16a092bbe2b5b09a4e34b98203e3b3ac0ec
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = c57b7353740853e2f4534218383741dbff9b5006aeaefa590f4b771a65d24dc4ee25bf3bbb13ad6a3ed4eefb68d0ae6a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:c57b7353740853e2f4534218383741dbff9b5006aeaefa590f4b771a65d24dc4ee25bf3bbb13ad6a3ed4eefb68d0ae6a
Ctrl.data = hexdata:0558822667fc051cb1864843b24c06eeb65c70754f56752808e33cf87ec64f9bffce395784df9940157b50bf01c11a1b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 5e9bf5910954eabc3a4c659be466cd4b66252685a8f4daf2afc414568420613f0bc4d0269e0edf266aa9faa70761840b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:c57b7353740853e2f4534218383741dbff9b5006aeaefa590f4b771a65d24dc4ee25bf3bbb13ad6a3ed4eefb68d0ae6a
Ctrl.data = hexdata:0558822667fc051cb1864843b24c06eeb65c70754f56752808e33cf87ec64f9bffce395784df9940157b50bf01c11a1b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = d296e0b7ba4f6eb7257cdfe9ed87618cc116a192f24cc8a5226edb2cd9cde893f7478c94e8d0dba9d9326dd674955bf4
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:c57b7353740853e2f4534218383741dbff9b5006aeaefa590f4b771a65d24dc4ee25bf3bbb13ad6a3ed4eefb68d0ae6a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = cdafc4fc6f6a718db9e77867f647c517bd4d43ebd794f1c2b5253c0b4ebb71f56848f4335aae0772065ae67d02baddae
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:cdafc4fc6f6a718db9e77867f647c517bd4d43ebd794f1c2b5253c0b4ebb71f56848f4335aae0772065ae67d02baddae
Ctrl.data = hexdata:619091dadb4c82f4524ad838625aeeca25264b7e645eeafa95ac10d3c32cf76dbd965269bffab4d9fc2a8d30bf63e397
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 0e3cfd61b1e5ce95dc37b01c872d90855ccebb98bd56702b1ec337163e63e3b133a9a6c7847a1d421776ccbdcae6a01f
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:cdafc4fc6f6a718db9e77867f647c517bd4d43ebd794f1c2b5253c0b4ebb71f56848f4335aae0772065ae67d02baddae
Ctrl.data = hexdata:619091dadb4c82f4524ad838625aeeca25264b7e645eeafa95ac10d3c32cf76dbd965269bffab4d9fc2a8d30bf63e397
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = d113ea4f795fd94788b782922c31c3dd1195287564a073590e17a61599da729c7f3a01aa777b1071f6cff7b69cadcf32
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:cdafc4fc6f6a718db9e77867f647c517bd4d43ebd794f1c2b5253c0b4ebb71f56848f4335aae0772065ae67d02baddae
Ctrl.data = hexdata:619091dadb4c82f4524ad838625aeeca25264b7e645eeafa95ac10d3c32cf76dbd965269bffab4d9fc2a8d30bf63e397
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 43943f7395babfbe3b327d5e9784e2082936189226af39b21b030e3e8c8244ee6aa4cc1e047df7a329793421c3006bc1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:cdafc4fc6f6a718db9e77867f647c517bd4d43ebd794f1c2b5253c0b4ebb71f56848f4335aae0772065ae67d02baddae
Ctrl.data = hexdata:755c319f41259c93dd83f3a3003f8d5c6e56e3cc486bfff5f636b5f97fadc8470271ef3e209501ec48a872f3ca16f84e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 6ad0e35cbf134d62e1ae57ba07288d0ce4774c0d2ca6faf06d8f18b3f2c290c6225be4f4a8df2016de2c0ccf63525ed3
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:8bb4a1a37dcb14ff5b57c922a13dc730a745392240ce43df80b23e67aae5bc86
Output = d2fe919797167c4b36f093d59244ff4ab455ccb59ea6ab2991789c049c2a110902c3f0c1dddb2b28b41013a13b223ab8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:d2fe919797167c4b36f093d59244ff4ab455ccb59ea6ab2991789c049c2a110902c3f0c1dddb2b28b41013a13b223ab8
Ctrl.data = hexdata:7bd8dc442c15b7cccc4a88aa2346f7e1434c0043ccd7075ec8b049bfa40c2b9b8882dfed654d762ef01cdf4bf55002e3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 7115918823a35c8ee8985966dfddc5be483db4029047296b3ddeb5c884712b5ddf27152a7f71e82a91e1420c7e4c25e8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:d2fe919797167c4b36f093d59244ff4ab455ccb59ea6ab2991789c049c2a110902c3f0c1dddb2b28b41013a13b223ab8
Ctrl.data = hexdata:7bd8dc442c15b7cccc4a88aa2346f7e1434c0043ccd7075ec8b049bfa40c2b9b8882dfed654d762ef01cdf4bf55002e3
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 3122eaea9244f61a733e2370e0689a47491e28ce3a2062224f0a8021f05eb5da22a5558dd7edcaf04821e483f84b5ba1
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:3edd347353ab8965bdb38e823004df6824a653329946620417a1857d56900efc
Ctrl.salt = hexsalt:d2fe919797167c4b36f093d59244ff4ab455ccb59ea6ab2991789c049c2a110902c3f0c1dddb2b28b41013a13b223ab8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 1edc8c10871598074baf38600a4a5927da7aa6256ea691fb1d026872ad751a1542726307c415af6c44121e37b86c81ff
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:1edc8c10871598074baf38600a4a5927da7aa6256ea691fb1d026872ad751a1542726307c415af6c44121e37b86c81ff
Ctrl.data = hexdata:29cfd57bd578514558e2e168e4c665759eded30d761e14d3cbc2123c2f38c63380e5f4a0d8c5895ab58f7af7bb16fbaa
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 2a795383e320e478b78f195b5f5b7477dfea13bb23da34eebae22dd12857ed33757486a9fc237d8a37ac1c09feb07bd9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:1edc8c10871598074baf38600a4a5927da7aa6256ea691fb1d026872ad751a1542726307c415af6c44121e37b86c81ff
Ctrl.data = hexdata:29cfd57bd578514558e2e168e4c665759eded30d761e14d3cbc2123c2f38c63380e5f4a0d8c5895ab58f7af7bb16fbaa
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = a51643b6c42b43f517e002decaf41823a10b717d525d55ed6996ef1ccff055c75218dec36815473fa5289c85bb301019
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:1edc8c10871598074baf38600a4a5927da7aa6256ea691fb1d026872ad751a1542726307c415af6c44121e37b86c81ff
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 3934b26badf5af9470de9dee4dfcb1addc69ea237c902291817e08c1032748a9315f579e42066cb86d16cb2cffbba24e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:3934b26badf5af9470de9dee4dfcb1addc69ea237c902291817e08c1032748a9315f579e42066cb86d16cb2cffbba24e
Ctrl.data = hexdata:605880f06229184763495b328496ba313882a8edccf956602713cf86fead2894e4339a0c6d8062073e781fc729336568
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 3ac8206a7f9e819c76ddd72bcd07397f64d9f698c4d75ec1d8ef610e9027c462d2cadf55d227a8c7b4eb63ab2012e827
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:3934b26badf5af9470de9dee4dfcb1addc69ea237c902291817e08c1032748a9315f579e42066cb86d16cb2cffbba24e
Ctrl.data = hexdata:605880f06229184763495b328496ba313882a8edccf956602713cf86fead2894e4339a0c6d8062073e781fc729336568
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 691e1db0137f5a54d4f51a8d6c2a89ebbbb0000cf81ddd5d08682416db9f48309d6b19819ba07e1860e34edecee4e23d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:3934b26badf5af9470de9dee4dfcb1addc69ea237c902291817e08c1032748a9315f579e42066cb86d16cb2cffbba24e
Ctrl.data = hexdata:605880f06229184763495b328496ba313882a8edccf956602713cf86fead2894e4339a0c6d8062073e781fc729336568
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 5c32c8fcb2e90cdfd5d86cef427b828fc162371236b3e39c4812deda4038cdbbb4bde6859a502f54acfb482666fd4295
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:3934b26badf5af9470de9dee4dfcb1addc69ea237c902291817e08c1032748a9315f579e42066cb86d16cb2cffbba24e
Ctrl.data = hexdata:b21112193c9c5604a544f95c0325d94041ec595f46a9a4cbba0a8c72501ac72ad8ed1d8fb17f82e0b288144d6f0f1d53
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 77538d76ba22a23215ee93ef07f542f7a7bc43f77af5da3395688f8b8d81afa2c47952db8a0f2da2435d3e340411b0f7
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:def2b619233e04b1dfe39ef92ae061791a84974c71921819697f86a255342b38
Output = de59d25fddb6ebeab4dbcfb55c5f7c24f2d15910da8c3463dd69241139e88c09d51f59a7aaeeeb4f08459f3360be3fa0
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:de59d25fddb6ebeab4dbcfb55c5f7c24f2d15910da8c3463dd69241139e88c09d51f59a7aaeeeb4f08459f3360be3fa0
Ctrl.data = hexdata:705c00dd0ad91ec54a86e311ef7931ad61d6b14c2c75411e95d7f3a80a21cc2b5a19b396e1147bf56dd3ee10dcf18d37
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = e539e7e8b3a065a4a40ffc7e8c8c70eedaccf7fa14a28b18503865805f7590ae7e9c550fae2d493d932a85e9fbe18f22
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:de59d25fddb6ebeab4dbcfb55c5f7c24f2d15910da8c3463dd69241139e88c09d51f59a7aaeeeb4f08459f3360be3fa0
Ctrl.data = hexdata:705c00dd0ad91ec54a86e311ef7931ad61d6b14c2c75411e95d7f3a80a21cc2b5a19b396e1147bf56dd3ee10dcf18d37
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 418e41f54f7fead42d623e9f40be68812fefa50c19b4cf4268b2dd4bd206414597d0af720242f1667cf4cdce325bb3f6
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:63505c479ea4544899a17a09ac19abc706d3ac60126d3239d19710926184a6d9
Ctrl.salt = hexsalt:de59d25fddb6ebeab4dbcfb55c5f7c24f2d15910da8c3463dd69241139e88c09d51f59a7aaeeeb4f08459f3360be3fa0
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = f7d0595a4a3b71cd6714376580e90e54f3be9f78c04e5708093931f01759b6283a9157ab9b32f322abf9795ebf18fe06
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f7d0595a4a3b71cd6714376580e90e54f3be9f78c04e5708093931f01759b6283a9157ab9b32f322abf9795ebf18fe06
Ctrl.data = hexdata:0000487cdfa6107c6b08d4d64e353585b30bc45414b7f5066e4c8dd6c9a80d3c9d5c204d664f4e43fa0842a462f4faab
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = f0f2c238ef72dff22e63bc018c41a1061fb8ca7755ac416ba3df5e8280faa21c84c07a8f0ac9f1ee6e50a6e56fa39377
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f7d0595a4a3b71cd6714376580e90e54f3be9f78c04e5708093931f01759b6283a9157ab9b32f322abf9795ebf18fe06
Ctrl.data = hexdata:0000487cdfa6107c6b08d4d64e353585b30bc45414b7f5066e4c8dd6c9a80d3c9d5c204d664f4e43fa0842a462f4faab
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 718cf52c40760e4ec4455b42ba829b7decbe1d6e89e36e74b86e09df090ad2a2f9ad7cf896317cb4803e332a828c9aa9
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:f7d0595a4a3b71cd6714376580e90e54f3be9f78c04e5708093931f01759b6283a9157ab9b32f322abf9795ebf18fe06
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 613b33b466defd69c2fb8ae637aa2034be4807a6676599f768db22a69669f2befc0a9732c286c880fcd6a04bd0da4059
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:613b33b466defd69c2fb8ae637aa2034be4807a6676599f768db22a69669f2befc0a9732c286c880fcd6a04bd0da4059
Ctrl.data = hexdata:2e3407a8e3f146036fbd35c1633f83daaf4f8e9bdc9e067f75d5b56d8201175b7b05f267db7940e0db534b57e037d575
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 333d43099efea0bb1c294fe4a34660bf4534f0af983c31723044363b6bbecccdba09d9702234db04534dee31a4ed0ab1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:613b33b466defd69c2fb8ae637aa2034be4807a6676599f768db22a69669f2befc0a9732c286c880fcd6a04bd0da4059
Ctrl.data = hexdata:2e3407a8e3f146036fbd35c1633f83daaf4f8e9bdc9e067f75d5b56d8201175b7b05f267db7940e0db534b57e037d575
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 68f85f1e025f9d3924be5327ce57b9abc4b7a078c20fa0ea513e7996af69723cece7ffa748f6034a66be7eae5e18068d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:613b33b466defd69c2fb8ae637aa2034be4807a6676599f768db22a69669f2befc0a9732c286c880fcd6a04bd0da4059
Ctrl.data = hexdata:2e3407a8e3f146036fbd35c1633f83daaf4f8e9bdc9e067f75d5b56d8201175b7b05f267db7940e0db534b57e037d575
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 2f71d6f423bd523b8a94e2ccc9f653a63594dfa030fdaa3796540075035f73bbe2d89f85af2de61462c22104c03ffa87
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:613b33b466defd69c2fb8ae637aa2034be4807a6676599f768db22a69669f2befc0a9732c286c880fcd6a04bd0da4059
Ctrl.data = hexdata:ba106fffdb82b75330da7132de828b1b032fad4878c7ab70acdffa4a76163ecdec8d25202715b78901e87a910f7e3b34
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 202803c8237412f20263b428932afcb5d8a7dcdd7fa147ea2af95a7dd091bf0d79686a6710f572bc868d2f533a488a6f
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a357ab62ad6eaf90426fe7a2cee0659583acbe423a17771690895b26aefd62a8
Output = c5cae95fcebb3eec27fc88654a2679cf600071d2a25a34fe7f34732415e922eb9a1de0f6db357026d3dfdadc5cb36b8d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:c5cae95fcebb3eec27fc88654a2679cf600071d2a25a34fe7f34732415e922eb9a1de0f6db357026d3dfdadc5cb36b8d
Ctrl.data = hexdata:ab0bb35f9586beaf843e44af363e8e0c49cc9820f063cefb1f8e20191bec2b3558fd51760dec17bbc299bf205292e549
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 40093dc6b48667da9b412bf718217bf25b4405a4d1c759af797c78ae25443def12be155d1954edd4216cf62a422fa4cf
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:c5cae95fcebb3eec27fc88654a2679cf600071d2a25a34fe7f34732415e922eb9a1de0f6db357026d3dfdadc5cb36b8d
Ctrl.data = hexdata:ab0bb35f9586beaf843e44af363e8e0c49cc9820f063cefb1f8e20191bec2b3558fd51760dec17bbc299bf205292e549
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 0b4f7ee9c8801b7cdbfbe064322d4879272b730e395b9c7e2bf8a07f99b101dc37687b993e4519d0d0ec607823c2a118
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:6b2ddbec771dbaf2c1de74c1de6f4ca391de63011ef8a5bd05c7fa716ee02cd1
Ctrl.salt = hexsalt:c5cae95fcebb3eec27fc88654a2679cf600071d2a25a34fe7f34732415e922eb9a1de0f6db357026d3dfdadc5cb36b8d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 58fb050686d06d7199031657d3332f0b9a5e64059a48a88d07c6c2775df17ebbe71a2c8e0d81abc7e87fd0fd96aae4f8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:58fb050686d06d7199031657d3332f0b9a5e64059a48a88d07c6c2775df17ebbe71a2c8e0d81abc7e87fd0fd96aae4f8
Ctrl.data = hexdata:671f55d398118eab16f4a2a87970615a7b37aa47b9fd935945a9a6da724c1f27dc4eefb2b123cbdee091c26985f81b7d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = dd489530beb209f2562b86413baabdbc052b2024ab7fb70a31e5e0e65f9c959034a6889f8b042c005ac132c879c40dc7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:58fb050686d06d7199031657d3332f0b9a5e64059a48a88d07c6c2775df17ebbe71a2c8e0d81abc7e87fd0fd96aae4f8
Ctrl.data = hexdata:671f55d398118eab16f4a2a87970615a7b37aa47b9fd935945a9a6da724c1f27dc4eefb2b123cbdee091c26985f81b7d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 973c20837584cb79bd35bcfbe34d3eafd36e5280f7547d92b794c446bf578be38688f734eed942ae8c1de6864af496e4
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:58fb050686d06d7199031657d3332f0b9a5e64059a48a88d07c6c2775df17ebbe71a2c8e0d81abc7e87fd0fd96aae4f8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = b7a8660e5b5dd7d85695d6b00655a25af851d956d93be87d970172651a808f115fccb155535121a56fba6a6a9c197971
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:b7a8660e5b5dd7d85695d6b00655a25af851d956d93be87d970172651a808f115fccb155535121a56fba6a6a9c197971
Ctrl.data = hexdata:1788d205772075ae39032c56c28abe25262c5cc2642304fe3ed25958b9ca0905144f6e9a140c043e7e2822087d9e81f5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 763af37257c1d8fc3620127669c779ec2cb8433e4108ff797f71fec1e90364a0ee0ad9c272308ea8951866c44cb7ac0a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:b7a8660e5b5dd7d85695d6b00655a25af851d956d93be87d970172651a808f115fccb155535121a56fba6a6a9c197971
Ctrl.data = hexdata:1788d205772075ae39032c56c28abe25262c5cc2642304fe3ed25958b9ca0905144f6e9a140c043e7e2822087d9e81f5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 3f1f4aaf11b3b30b5d76fcd077900a5dabdad92980bed0f3f0de6495c9ccf2c58aea08f7745b7b6c0cc3829b048c89de
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:b7a8660e5b5dd7d85695d6b00655a25af851d956d93be87d970172651a808f115fccb155535121a56fba6a6a9c197971
Ctrl.data = hexdata:1788d205772075ae39032c56c28abe25262c5cc2642304fe3ed25958b9ca0905144f6e9a140c043e7e2822087d9e81f5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = f5fb64671edfb74aa85a061cd845945a93281d09badfcdca81a3f29bce743fa784536c8a259b9c7af667f783554a9700
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:b7a8660e5b5dd7d85695d6b00655a25af851d956d93be87d970172651a808f115fccb155535121a56fba6a6a9c197971
Ctrl.data = hexdata:629e6112e7d0812e590a7b0dabc0a72b5a8539df1ca809a5f6ea8fe3ff35caf5a2bf0761232d97f0331e65f8ef2f28f5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 984e97a983945c49ac2f6482855771f514688d8dafe4e8a4d4438f90aa3a76dae0fa027ffb189d736ce13a9bd64c9d7f
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:02a241afe7072dc28fddc66987e22a710a5f2c3460766d55d5af58d549bd8f21
Output = ef81b12b65b731fa750705c7799ec296cf4f3218bc34a3ef5819a6857aece0fd608e27f1589ce09a9fa72f941d304894
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:ef81b12b65b731fa750705c7799ec296cf4f3218bc34a3ef5819a6857aece0fd608e27f1589ce09a9fa72f941d304894
Ctrl.data = hexdata:a911360d1d4f3bbd671908701106913fd281436de65cc2b9645e2cdccd31452cde589ccbbe41d926d3b82d468c2e812d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 93c085d9eb42edcb69274adc8c04fd4ee074672c99c1e44ff7ce4f0b3c3c0d56875845d2b148ebd1558547141cd35200
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:ef81b12b65b731fa750705c7799ec296cf4f3218bc34a3ef5819a6857aece0fd608e27f1589ce09a9fa72f941d304894
Ctrl.data = hexdata:a911360d1d4f3bbd671908701106913fd281436de65cc2b9645e2cdccd31452cde589ccbbe41d926d3b82d468c2e812d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 0a5265d6097424d190572a4c7110f43097ea10056af875f74be4f02b82adf1de4dc7b90423e550bb0f0100ca2f0fcda5
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:1426c851a7872eb25a197b7e58410871f0760e81345e67a1ffb6459f7b621f05
Ctrl.salt = hexsalt:ef81b12b65b731fa750705c7799ec296cf4f3218bc34a3ef5819a6857aece0fd608e27f1589ce09a9fa72f941d304894
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 8751149d301adca9db725b867e22ceb4be056cd16aa43ac55307d1ffae4f656cf43678bff88057e65a90871b8a2a9910
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:8751149d301adca9db725b867e22ceb4be056cd16aa43ac55307d1ffae4f656cf43678bff88057e65a90871b8a2a9910
Ctrl.data = hexdata:5492f38f35ca8254b8b50e45dba0f9eca6e5b4fd1275d80984e67cbc4c3377f1ed734c46a1a53fd774f9d10de7cb8186
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 13d2a5aa1e375e769e4062d829c0df66a8138357e460adbfe859fcd09252dec37e93076a225b9aa51569f0a60960f425
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:8751149d301adca9db725b867e22ceb4be056cd16aa43ac55307d1ffae4f656cf43678bff88057e65a90871b8a2a9910
Ctrl.data = hexdata:5492f38f35ca8254b8b50e45dba0f9eca6e5b4fd1275d80984e67cbc4c3377f1ed734c46a1a53fd774f9d10de7cb8186
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 3c05d6e0733946fbb7fbbec7cfc6a1a647d8313c14ee7f3d0de15c29ad56cda0cdfa171a5b312cc7318c12a8fac80206
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:8751149d301adca9db725b867e22ceb4be056cd16aa43ac55307d1ffae4f656cf43678bff88057e65a90871b8a2a9910
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = dbcbe0371453d2d7794e18fb951d16e587046b1c8672b8975985067b8826e3174b18ec1a622d104d2349fbe7cf516acc
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:dbcbe0371453d2d7794e18fb951d16e587046b1c8672b8975985067b8826e3174b18ec1a622d104d2349fbe7cf516acc
Ctrl.data = hexdata:c8456dec887407791bff92fc9a929b94139e90837c778d61735f85d057d2b59b45a57535368c78fbac10e6440a46af6f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = bfa7282e1e5e7396743994a1b7708bed617b20a2d1f8514e28e9322187e7afce7ea133881ecf305e0aeacbe972835ce1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:dbcbe0371453d2d7794e18fb951d16e587046b1c8672b8975985067b8826e3174b18ec1a622d104d2349fbe7cf516acc
Ctrl.data = hexdata:c8456dec887407791bff92fc9a929b94139e90837c778d61735f85d057d2b59b45a57535368c78fbac10e6440a46af6f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 91eca687ecf6db1613aab6b8bc60b118a4e6e98b94afb48638efa00717451310cefa5a533867281b7624ecbdd7614deb
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:dbcbe0371453d2d7794e18fb951d16e587046b1c8672b8975985067b8826e3174b18ec1a622d104d2349fbe7cf516acc
Ctrl.data = hexdata:c8456dec887407791bff92fc9a929b94139e90837c778d61735f85d057d2b59b45a57535368c78fbac10e6440a46af6f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 1b1e6b3a2e33d3616a5a41368993d80a7ff4ebfbd3973fa6bb6582a13bceb21f3085dd7b0a731bc03ea931dd668549f8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:dbcbe0371453d2d7794e18fb951d16e587046b1c8672b8975985067b8826e3174b18ec1a622d104d2349fbe7cf516acc
Ctrl.data = hexdata:4e14e5e218a29c7d70a83bb39b782d2c9ba5a2ba856e8963bacb4fc1aaa7d376e16175cbeb17634f90225a2f8483b2ed
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 50ceeded13db2c364b44c976d708b7fee57eec0998c85eacc05c2b0a3b4cafeda1642751f78530c433f689ee4a23d4e3
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:bb156178fd7d06e40789668fe93b4432d7e52c0294f11eb2f64c5bd24836115c7034b403a453976f51d699a348e64104
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 9bd2371a1c4e8850f6d52eadfd088cc380c8f76612fcde4ac4a6605a6ae5117820ebe108273f6533cdeea942bcb3ab6a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:bb156178fd7d06e40789668fe93b4432d7e52c0294f11eb2f64c5bd24836115c7034b403a453976f51d699a348e64104
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 71b365f40805bd7a810d704512c6f17110589d9585580324d9cfceff6f81f4eceb2128fa295f9b236fe5fee4629e1859
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:83945a53ffb26b51f21f69d75c414309e5155fa030723c1c38cffe89cb04edb6
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 12c2bb4946770fc0378134cb2cb3504b44724a2fc10d80bd691b42ea5a77370888af2cc8832564214dabc967fab153b1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:12c2bb4946770fc0378134cb2cb3504b44724a2fc10d80bd691b42ea5a77370888af2cc8832564214dabc967fab153b1
Ctrl.data = hexdata:00589f3587b9fd9e27cd4e411568bf56df30a6a0d969e88eec4944b5b442d2cd7188c1b11e78912824bf6f48db8dd30e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 20832548d9ca0fa619833e866639df7412ac7c3906e8076c6e4553a2e56fa8703b1727d64015cb6aad020e8b5d889a6b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:12c2bb4946770fc0378134cb2cb3504b44724a2fc10d80bd691b42ea5a77370888af2cc8832564214dabc967fab153b1
Ctrl.data = hexdata:00589f3587b9fd9e27cd4e411568bf56df30a6a0d969e88eec4944b5b442d2cd7188c1b11e78912824bf6f48db8dd30e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = ab2f7ea9aaf2573370c6b46e929910cab6da6a0aebb236b337e5241e9c5226be3b423bfde3f06b34a7560d98885c8c54
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:12c2bb4946770fc0378134cb2cb3504b44724a2fc10d80bd691b42ea5a77370888af2cc8832564214dabc967fab153b1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 2a3381ce1639af02a64ac0735edfc729dc4019696fe7d4f9464ab7cd7a9978436cbca4461d19e93a3aaad1f7dad6c36d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:2a3381ce1639af02a64ac0735edfc729dc4019696fe7d4f9464ab7cd7a9978436cbca4461d19e93a3aaad1f7dad6c36d
Ctrl.data = hexdata:a6a0c99dc81a74aedf37284ef07701cea224293ea00dc688ef3ed30368c811a4a5c3cd4e7a2a969539bf7bfeb79253e9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 2217a5a433ed108d3fda94ed78632222806baa2c3f16b0b95534760ae0bd7403d8f9d95f47888b2f2b0b080b3b046d5c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:2a3381ce1639af02a64ac0735edfc729dc4019696fe7d4f9464ab7cd7a9978436cbca4461d19e93a3aaad1f7dad6c36d
Ctrl.data = hexdata:a6a0c99dc81a74aedf37284ef07701cea224293ea00dc688ef3ed30368c811a4a5c3cd4e7a2a969539bf7bfeb79253e9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 3c32294e5dafebf41e4b45f2ff7f70b925c2ea78d1ab0d31f8cf813d7ac47b766809519cac70c5b3bba389e33a04e6f4
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:2a3381ce1639af02a64ac0735edfc729dc4019696fe7d4f9464ab7cd7a9978436cbca4461d19e93a3aaad1f7dad6c36d
Ctrl.data = hexdata:a6a0c99dc81a74aedf37284ef07701cea224293ea00dc688ef3ed30368c811a4a5c3cd4e7a2a969539bf7bfeb79253e9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = f92f95ee85dadda7467b4a402c877c746d170a986a18ffe13a7263f11a74e4322d567ecca89d0e5dda4f624aac0101ba
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:2a3381ce1639af02a64ac0735edfc729dc4019696fe7d4f9464ab7cd7a9978436cbca4461d19e93a3aaad1f7dad6c36d
Ctrl.data = hexdata:4ad8bec778fc2c32c98470e27d4151126e2a215a32cdd2a688e47717e5fa7490b586d2c4fb54e0996417ccdf189fbe73
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 517a3f7ef3d51098512ba68b0066deed4a6f3f016d78949e79dadb1ab730beb84d556b31c8c1eb7d741cccfd12313049
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:ce8a273136c4c91b175a57e7b27eb2929a31e3410e9c5b8b7dfa442f5459e59222d6dbea6f1d0e5b7b8d8bcae28b58c9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = d3fc95dacd1c4ed05b0d0f11ea7128f309c7dc81ab7d732b7333d4e6347189923e44ee2a0b4047fcd502f7e74edef55d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:ce8a273136c4c91b175a57e7b27eb2929a31e3410e9c5b8b7dfa442f5459e59222d6dbea6f1d0e5b7b8d8bcae28b58c9
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = fa6c3df3027a0711fe712c3e43886eb56b0f26894a8203c5a1a3a7813977ccf6668ff1e2d94bca987e6fb169e6f47b85
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:d57947df07774b69399f726359860d5f20ab3b23c64446386c2370defcdc915e
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = e87f946ab1726ab5e911df8b14f6393db1c72caa512e3d235847a271ae1b4d8643ff19b393710b67961eca39cebcf138
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e87f946ab1726ab5e911df8b14f6393db1c72caa512e3d235847a271ae1b4d8643ff19b393710b67961eca39cebcf138
Ctrl.data = hexdata:9e7c01ccd11887a65a50be6bd9ca2263fe02a5fa483579d0e139faea00e920b12ef044fa1c3a29480217ccbba6fff0b8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = bfc1f429408ebc49b9ae80a36e1f354e695351c24c002fd96059763b06ac6db3c2169b4af955ac03dd431cd4aa5269f9
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:e87f946ab1726ab5e911df8b14f6393db1c72caa512e3d235847a271ae1b4d8643ff19b393710b67961eca39cebcf138
Ctrl.data = hexdata:9e7c01ccd11887a65a50be6bd9ca2263fe02a5fa483579d0e139faea00e920b12ef044fa1c3a29480217ccbba6fff0b8
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 3ae6b72885417b225a3c4f92ebf8e3f7d33f968f44ec51edbdd628d867432adbdc672579d857bcc5a575a646e3622904
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:e87f946ab1726ab5e911df8b14f6393db1c72caa512e3d235847a271ae1b4d8643ff19b393710b67961eca39cebcf138
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = a92245795eac1334ddd246d3857de343813f59bb2eaf78dc8e92dcc61926b89d5252e357289485573c693da5b7a0b3ab
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a92245795eac1334ddd246d3857de343813f59bb2eaf78dc8e92dcc61926b89d5252e357289485573c693da5b7a0b3ab
Ctrl.data = hexdata:6b301e7a7b3f3d960a620ca6c0a8855c7806cdee61e8c3344330c15c023f76fc31996ced8b35beee2c492c910f2dc2db
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = b48a4caac858a953f1b5f9019484fb4fea955b533865db740fbaf945392d3bac0d0f4038d2283e00838dcdbdbdf2d9b0
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a92245795eac1334ddd246d3857de343813f59bb2eaf78dc8e92dcc61926b89d5252e357289485573c693da5b7a0b3ab
Ctrl.data = hexdata:6b301e7a7b3f3d960a620ca6c0a8855c7806cdee61e8c3344330c15c023f76fc31996ced8b35beee2c492c910f2dc2db
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = f54b230bd2fb82bdb0eefde4368177383e5d104ec4e6ab71ff129e356807737ed9d522d6014ac56bad4ae23cad76e8b7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a92245795eac1334ddd246d3857de343813f59bb2eaf78dc8e92dcc61926b89d5252e357289485573c693da5b7a0b3ab
Ctrl.data = hexdata:6b301e7a7b3f3d960a620ca6c0a8855c7806cdee61e8c3344330c15c023f76fc31996ced8b35beee2c492c910f2dc2db
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = e9c305cafa53d3bb189013492fc6e40f01fd194304aea30fe73b8322161edf4a39e6530c3904cb5bd8fa8644ece55a2a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:a92245795eac1334ddd246d3857de343813f59bb2eaf78dc8e92dcc61926b89d5252e357289485573c693da5b7a0b3ab
Ctrl.data = hexdata:5e28ee7474db3de8996894fb8285af4469349a0cc7cca47544b0b7c7663dd3ea7399ad26f054a75f4f0a9260447f4030
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = be0b885a296f266b0f50dc53f78b27ebac7292f627b3658bc4a95607529f5864d47e25c848363c0ab5dcd83193fd62cc
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:53c45ce0fa2644a0a532fc5e73272a655bca78e483d86e872c521cf5a0a75a34b9f546f4b9a56e8a2c3a52525b0ddcce
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 3e67e81d98d6a17439294130cb14383aeca788251a609bb97e7c2b81f53c195fb5f95a6133d014083b5e2c3a9d04c1e2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:53c45ce0fa2644a0a532fc5e73272a655bca78e483d86e872c521cf5a0a75a34b9f546f4b9a56e8a2c3a52525b0ddcce
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = d02ae01d3bb7e72d99f32ff7561e1243576bd37ea06b3c8a31e991c92b169f647541fa5eba74086891b6436489dae045
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:eaef8daa591f860e4e4693a39a01a246790c3e26c6545a9831a69550bbb87b91
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 6f06af2ecb2262d77a9a6a8e94cbacca3645cefa3dd9f23e4bbcc59042a1ac46029950f894f1b96fbdb8c926375d107a
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:6f06af2ecb2262d77a9a6a8e94cbacca3645cefa3dd9f23e4bbcc59042a1ac46029950f894f1b96fbdb8c926375d107a
Ctrl.data = hexdata:16fd0b738388236a90949eb344161ae277b5851169ba636cc83614c0b88f800d69eca40d3a93a9b284ee9dacb1cc197c
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = e1f668956b8f85ffc5516b300c29f26d0af9a3403982dc75e3994a6a5cf105e891567737dcee9cfd48457c948059e411
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:6f06af2ecb2262d77a9a6a8e94cbacca3645cefa3dd9f23e4bbcc59042a1ac46029950f894f1b96fbdb8c926375d107a
Ctrl.data = hexdata:16fd0b738388236a90949eb344161ae277b5851169ba636cc83614c0b88f800d69eca40d3a93a9b284ee9dacb1cc197c
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 852e3d5b12fadfbbf3defe048a14ac51401299d39c92e0c359b8ff9a3c34335d1d0bb6881b2c30435248c4fa341033e3
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:6f06af2ecb2262d77a9a6a8e94cbacca3645cefa3dd9f23e4bbcc59042a1ac46029950f894f1b96fbdb8c926375d107a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 566e81b068476abf14a8495f49b34441ffd488d1252c0d0140a437ed8a42ca0532311ac7117510481bd5b1b4427bdf8f
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:566e81b068476abf14a8495f49b34441ffd488d1252c0d0140a437ed8a42ca0532311ac7117510481bd5b1b4427bdf8f
Ctrl.data = hexdata:852395eb84730bac2c1a09f3843a6e0705fb66924953f48ecabe9a0d3c73c1933c8f99efb0ca9cbb8b2dbbc966fb5bd1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 307f12a3c070fb00f706a4bf6d7492d5b3c1e4eea713d14ab5d52324237eeb75f585b6b278df896614f64a9119e750fe
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:566e81b068476abf14a8495f49b34441ffd488d1252c0d0140a437ed8a42ca0532311ac7117510481bd5b1b4427bdf8f
Ctrl.data = hexdata:852395eb84730bac2c1a09f3843a6e0705fb66924953f48ecabe9a0d3c73c1933c8f99efb0ca9cbb8b2dbbc966fb5bd1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = cf098b49f302e84c11aec463638b22ada6083de98e319903a934d114613084d6c162e4c8d26522ef8cdd45c515a7c74b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:566e81b068476abf14a8495f49b34441ffd488d1252c0d0140a437ed8a42ca0532311ac7117510481bd5b1b4427bdf8f
Ctrl.data = hexdata:852395eb84730bac2c1a09f3843a6e0705fb66924953f48ecabe9a0d3c73c1933c8f99efb0ca9cbb8b2dbbc966fb5bd1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 9def86f445a25c8458ab71af0030fa4b1aa44858adb4875702ea521bd6cb2272fb6938b52bb3842963755bb0658ccad7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:566e81b068476abf14a8495f49b34441ffd488d1252c0d0140a437ed8a42ca0532311ac7117510481bd5b1b4427bdf8f
Ctrl.data = hexdata:80c10c6944df45bb77135b12af17738a5625802faf9c3fc22600f18969f147a141e94e131eca654ad86c491d1d98a9ec
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 7931cc9028395f8b1392e398358dffa95f2cea2804ddd3d1c0c477d6373fbd48be6c5e4d971d5707e0674a97c512cdba
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:4d4855b455ea510c22bd621486b43c6cd12d28af2c17cb0bfe7c5df2e94d56c9d1c43d591d39572018322cc8210ae12b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 2571b9bc3d01f14a1e509764092de227e2ab28b5faf70661bfcd79de6374367d4bf90ad6f3bc0f01e12b61ed4943f042
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:4d4855b455ea510c22bd621486b43c6cd12d28af2c17cb0bfe7c5df2e94d56c9d1c43d591d39572018322cc8210ae12b
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 09cd4219de326e48bdf79d2d88689877cff7941715bd37aa992e638eb8998a9b79dc689e11215c7681809205ed1eabff
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:aadfb50d4a29c09e7058dbaba4a90ea3a0aa37de17275c9b89176f442d6e4b06
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 45ffc3730b02754071604360ff8689c372e0e63abb5665e1a1799f91dc79f04ad87ab4cb589205224ca810a8cf872448
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:45ffc3730b02754071604360ff8689c372e0e63abb5665e1a1799f91dc79f04ad87ab4cb589205224ca810a8cf872448
Ctrl.data = hexdata:81f8bb49b27cc25f4062ddee4794fc7e3c583dfbdf160eb9b4a39de5f7fdca2c83c8842ed18dc93db6b4556504a72291
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 21456e5662e2067c7beb09079a7e12e4b27a3721e3047571a87d2da45267dafd1c6af9d62d212d802ed69cd69ed63067
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:45ffc3730b02754071604360ff8689c372e0e63abb5665e1a1799f91dc79f04ad87ab4cb589205224ca810a8cf872448
Ctrl.data = hexdata:81f8bb49b27cc25f4062ddee4794fc7e3c583dfbdf160eb9b4a39de5f7fdca2c83c8842ed18dc93db6b4556504a72291
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = b2e69b45e4a926ce6895f59af91efd9b2edd0e5338452bd772247f432ca294380b6e494fd4e5321f013787036225b9ac
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:45ffc3730b02754071604360ff8689c372e0e63abb5665e1a1799f91dc79f04ad87ab4cb589205224ca810a8cf872448
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 06deb1755458ed01f6e53ca640eb2d4c6f42641221fb50e64de8e3a2466691222cc6a21bfcc3a2e1a6fd631174b0bb00
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:06deb1755458ed01f6e53ca640eb2d4c6f42641221fb50e64de8e3a2466691222cc6a21bfcc3a2e1a6fd631174b0bb00
Ctrl.data = hexdata:f359cee8145326f8588220d19274068b16166021b07a371b66955a5504695254ad30b2c0daa5a6ee97a59d338af19ebd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 3b6af39d0f782e9e14102c259584a84e22b8f01cb8bcc474b7682d03f896905bb5080db4818fb2f5e036d48f8ff9f829
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:06deb1755458ed01f6e53ca640eb2d4c6f42641221fb50e64de8e3a2466691222cc6a21bfcc3a2e1a6fd631174b0bb00
Ctrl.data = hexdata:f359cee8145326f8588220d19274068b16166021b07a371b66955a5504695254ad30b2c0daa5a6ee97a59d338af19ebd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = cf0d58f7bfc58fc46eb87dd8201b1ec59da4fe4fde9e864e295d5c1ca11a1c80cbda554637c8b244df0dde1f171408b1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:06deb1755458ed01f6e53ca640eb2d4c6f42641221fb50e64de8e3a2466691222cc6a21bfcc3a2e1a6fd631174b0bb00
Ctrl.data = hexdata:f359cee8145326f8588220d19274068b16166021b07a371b66955a5504695254ad30b2c0daa5a6ee97a59d338af19ebd
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 0585f4818b8203525986415b4a253901f80040cbd62bd081009b14788a01f71aa05ef9b38b2cc15eb09cdbba82e4381b
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:06deb1755458ed01f6e53ca640eb2d4c6f42641221fb50e64de8e3a2466691222cc6a21bfcc3a2e1a6fd631174b0bb00
Ctrl.data = hexdata:8fbf37769af8301a6d6067348b7b4d30b2da212dba16cd83f4bfd9da83964053c37eec6954ad77259ba77d69a074e13e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 74075af4eef3b6d0bd14ebcc1a30aa4800c426b197945dac99d359bf655e3f60facf22dc20bd7b835d9fce8054d5dbad
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:d43bb2adb7ad63a04e40fd5390e7cc7ba0ed8953c2cda92f4383ed8e3d2632a48dda67b9a54eee831ed7f2e2a9f99c5e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 0f76f5af5ab1ce245943313fdc5f78aca0277e27fae95fb12b57469d485bb6612b35b9795cfb8bbda734c8b5291dc35e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:d43bb2adb7ad63a04e40fd5390e7cc7ba0ed8953c2cda92f4383ed8e3d2632a48dda67b9a54eee831ed7f2e2a9f99c5e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 7d40656445a89b8a03a7ccaca413d9438d8a7b434812b6d141b2089464953accbc4cace5c124c3038a558d0b59e7915d
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:ad2cfa585abc0d2ca5db71c0d1a765e78b59cda0cf3b5eab80731a99a951072b
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = c859ebeb69d7621864780cd992f00c87f7902c5f23d16c780ffb3baa9d7e6b33aff77ab0811886bb9aa43f4229bcfe31
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:c859ebeb69d7621864780cd992f00c87f7902c5f23d16c780ffb3baa9d7e6b33aff77ab0811886bb9aa43f4229bcfe31
Ctrl.data = hexdata:73f2b0896bc0c24dde3b4f01b3285eed02f78633f1bd910ff5f9a331b6495d70d1fb06610a312f3a60d9f6a7a5f39690
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = ac3b6e92e1f973f82b29e283bfaccce9c5f4c16e2d885b49fbde0e537cdee5718377ea7117e0add2ab997a7c12357858
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:c859ebeb69d7621864780cd992f00c87f7902c5f23d16c780ffb3baa9d7e6b33aff77ab0811886bb9aa43f4229bcfe31
Ctrl.data = hexdata:73f2b0896bc0c24dde3b4f01b3285eed02f78633f1bd910ff5f9a331b6495d70d1fb06610a312f3a60d9f6a7a5f39690
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 35127fae2fdfcfc744578ac51994e1d6140cb215cecc1172f052c2626a03edfc9c0b270326313272b1a7a82a45495cbf
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:c859ebeb69d7621864780cd992f00c87f7902c5f23d16c780ffb3baa9d7e6b33aff77ab0811886bb9aa43f4229bcfe31
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = f14ec4e75c444e149c8528c1d86424b0d0ec6de8af14a0045443a5aa462d09e24c346060a26721d7f337297fcdb73e65
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f14ec4e75c444e149c8528c1d86424b0d0ec6de8af14a0045443a5aa462d09e24c346060a26721d7f337297fcdb73e65
Ctrl.data = hexdata:79f1027369f4af0a5d5b84b5083ab2dbd1244139aaf648bea9d3e03abcff938aa78670aa9f12e0e160c3eda36f65ab75
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 006523da7c759a9664b0a29c6d4d6c3f24a5f1f0642874f6f260b3617514dc933703f8e21be3d79246511d6eb0602fa8
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f14ec4e75c444e149c8528c1d86424b0d0ec6de8af14a0045443a5aa462d09e24c346060a26721d7f337297fcdb73e65
Ctrl.data = hexdata:79f1027369f4af0a5d5b84b5083ab2dbd1244139aaf648bea9d3e03abcff938aa78670aa9f12e0e160c3eda36f65ab75
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 56c42d1105ac8073316e6be3efd459539bf8c9fe8b55f24895d643f2d5a6e882a9334e7a3e8e7092072e62d6c67ba038
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f14ec4e75c444e149c8528c1d86424b0d0ec6de8af14a0045443a5aa462d09e24c346060a26721d7f337297fcdb73e65
Ctrl.data = hexdata:79f1027369f4af0a5d5b84b5083ab2dbd1244139aaf648bea9d3e03abcff938aa78670aa9f12e0e160c3eda36f65ab75
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 40c01edda9d1bb545623f56ddd05fd9c788b7eacd667bbb3916ae0d71c1235f3b8943fbedae9447b1c9492e2d5806f07
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f14ec4e75c444e149c8528c1d86424b0d0ec6de8af14a0045443a5aa462d09e24c346060a26721d7f337297fcdb73e65
Ctrl.data = hexdata:f782fce708c7fb5bf48303d42e38c4c3598b4c82e186b424cd2e6a4514a58da02a6e472e04981d9235a996fa82de748e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 6d2a9e1c4f7a07f51af877f2e301ddf37c2c7deae30947c53c076e7b20dd20dd137724f62706b35ba3dd02fe1bbc6771
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:07db069260fd2ea0cc174c1bbbb2b685d090ff14eb1a1e750a55e633ec6eae8d8eb30c38864b4c8cff92f8e14fba6deb
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 0930f5fe2f1a7651534350db7cbf81a30d90d6acf11ee7054fb1fe03ba6f1657a5452f1e0c8aec106e682bf3ce319d9d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:07db069260fd2ea0cc174c1bbbb2b685d090ff14eb1a1e750a55e633ec6eae8d8eb30c38864b4c8cff92f8e14fba6deb
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 9a64292070a6ea9704cd7117bfcbe7c6378c9c63ed0c0f997cfb518db5f87ca1006e1eb374a3b9515138e9b39774218f
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:371954308edaeefb9e4abddcfc514a9c812bb34dfbcfcb6cea1d2246a62427d5
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 0b4028bb1c50c64620b0595cb2c77a43d4d729245d0502a00c76740cc195e320b13086af43cd21ecbcbe7d926fca496c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:0b4028bb1c50c64620b0595cb2c77a43d4d729245d0502a00c76740cc195e320b13086af43cd21ecbcbe7d926fca496c
Ctrl.data = hexdata:50543ddbf93cb27df7d958cc31bc88a74e459bc19ad3a2454436618b5145ca1dbe921c164e8453194e94b79cf0b5a0d2
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 43d49b8255b120ed5e58ec8a6e8af25a9744bcf09f49385df6fc1568165241349fc546d4f0fb5c8024453b96df6dd2e1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:0b4028bb1c50c64620b0595cb2c77a43d4d729245d0502a00c76740cc195e320b13086af43cd21ecbcbe7d926fca496c
Ctrl.data = hexdata:50543ddbf93cb27df7d958cc31bc88a74e459bc19ad3a2454436618b5145ca1dbe921c164e8453194e94b79cf0b5a0d2
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 3d9858bf41c9e22fc524227a645f3782fbee662c900b2fb1888427a72117ac0fb1e013162bff6bbaa3f5f1547eec7be2
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:0b4028bb1c50c64620b0595cb2c77a43d4d729245d0502a00c76740cc195e320b13086af43cd21ecbcbe7d926fca496c
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 9a758229844cc9b3de5cf554bc5984b959269773f937deefd0ee58ed0d719a978b7d16a7770d23510b27978a70281474
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:9a758229844cc9b3de5cf554bc5984b959269773f937deefd0ee58ed0d719a978b7d16a7770d23510b27978a70281474
Ctrl.data = hexdata:4b857ace793fce3accfb9444de7aee6803e0decdd3f457bef0b1d4dd6447359eeaf3c9a284622aa0731b7cd888897bd1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 64477d25734889a7062ccd36d73e3ae3ce4a416efc4ca6e625b79052a1db24c285e34c8cdf31656c8323ab9ce44ad4df
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:9a758229844cc9b3de5cf554bc5984b959269773f937deefd0ee58ed0d719a978b7d16a7770d23510b27978a70281474
Ctrl.data = hexdata:4b857ace793fce3accfb9444de7aee6803e0decdd3f457bef0b1d4dd6447359eeaf3c9a284622aa0731b7cd888897bd1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = e0036e688f3a556a15ffe19fe2795913d9f499ffd3919d9107ae062066b53f5395486bee26e8f9892616e2c99cced28d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:9a758229844cc9b3de5cf554bc5984b959269773f937deefd0ee58ed0d719a978b7d16a7770d23510b27978a70281474
Ctrl.data = hexdata:4b857ace793fce3accfb9444de7aee6803e0decdd3f457bef0b1d4dd6447359eeaf3c9a284622aa0731b7cd888897bd1
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 2c1f8cd1719ce51ff646c6fc92a5763ec5ff6902400dd012bf880087370033b00650ba4ae3b3681881d6cc591ed5641c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:9a758229844cc9b3de5cf554bc5984b959269773f937deefd0ee58ed0d719a978b7d16a7770d23510b27978a70281474
Ctrl.data = hexdata:43fbbfe6d001f7ac624624c609ba92441e04aa4c0fef40654b82e01b72a791e80618e175d22fe6b5ab5c178f7667e867
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = a2495c69d4cc3b35dbfee989ae9455415705935a77651a37385b67908eaed40c071208755018bec80a6c34bd64406710
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:e7b076d704091b4080952316270481f229c5e7bcffcecbe6eaa9c418230419dbd442fbfa6c89d12c8ba0090f89d90de5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = ad0645846c685bc37094123403a2a7f7caec78e687b185e1496f655d254f3bcffd04bc29e2b2dc04d8ec8e9f11ddfcf4
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:e7b076d704091b4080952316270481f229c5e7bcffcecbe6eaa9c418230419dbd442fbfa6c89d12c8ba0090f89d90de5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = ba83f794ed25e29fe7aeff5b542457fc3e90e4c3acc980110ba95a2e4652afedb25787b265972892002369b894516231
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:0b8a848caaab3159494881a4dd372009485dafc170fc11648bfe829f9001dc63
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = f5b03496a24c3331f58bf6a3435abc614b796bcaef11b65f104ce3855261b20b7a07b1592f025bc8ec2d9b5f35644e18
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f5b03496a24c3331f58bf6a3435abc614b796bcaef11b65f104ce3855261b20b7a07b1592f025bc8ec2d9b5f35644e18
Ctrl.data = hexdata:7f892b8cb527cf479711cd127c69152c6ef32aae37a48b6e4160c04190adbc6b8bbaff775ab8edb59284d1c86d277755
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 3a3c7ba28192268cb293a348092bcda2d8b60428b3c3a0bb4317d0ed5a1111a3054f4aa514beb79e31121e91965e9e80
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f5b03496a24c3331f58bf6a3435abc614b796bcaef11b65f104ce3855261b20b7a07b1592f025bc8ec2d9b5f35644e18
Ctrl.data = hexdata:7f892b8cb527cf479711cd127c69152c6ef32aae37a48b6e4160c04190adbc6b8bbaff775ab8edb59284d1c86d277755
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 731e40db136f53384be606574f940d789c5be823c28727d46817b628ee9b836696d50d064298f89ee80d2adfc092ce72
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:f5b03496a24c3331f58bf6a3435abc614b796bcaef11b65f104ce3855261b20b7a07b1592f025bc8ec2d9b5f35644e18
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 509df878e86b4eb004ea2ac7228d26612ff3f284ca112a039390e12ffef7270c84adaf41451e75699ae08dc2efa02071
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:509df878e86b4eb004ea2ac7228d26612ff3f284ca112a039390e12ffef7270c84adaf41451e75699ae08dc2efa02071
Ctrl.data = hexdata:d71bf2f002c654eccad8225a97d877ea38f40b67dd30040658419e9caf579d8ae349883f5299bf54aba0f61d971b7f90
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = cd593873f98049f9729edb4562ca7cc434142f633a098c0119be0931cdb78d084d3daa01d7a46526d1d2fc1b04b918b2
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:509df878e86b4eb004ea2ac7228d26612ff3f284ca112a039390e12ffef7270c84adaf41451e75699ae08dc2efa02071
Ctrl.data = hexdata:d71bf2f002c654eccad8225a97d877ea38f40b67dd30040658419e9caf579d8ae349883f5299bf54aba0f61d971b7f90
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = 38b5ff48b24cfd296919ecb290f774f02a56d247430c8cdb4615d1a4d9c80ae08fef8a4f5c06d1d566ce34dcbbd8f9c4
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:509df878e86b4eb004ea2ac7228d26612ff3f284ca112a039390e12ffef7270c84adaf41451e75699ae08dc2efa02071
Ctrl.data = hexdata:d71bf2f002c654eccad8225a97d877ea38f40b67dd30040658419e9caf579d8ae349883f5299bf54aba0f61d971b7f90
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 6a25ad33e7a00d1fd2336d16c00068e0ac0bdb155b2035248cd9c10c4d8f7806adc26a34fcefe4cf958351d8af04454e
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:509df878e86b4eb004ea2ac7228d26612ff3f284ca112a039390e12ffef7270c84adaf41451e75699ae08dc2efa02071
Ctrl.data = hexdata:377bd75f1a7f42975c10046c29884917dc101db1b42d0b56ae55f3fe64b19ad9b4538fb70d99cf4e48d23787538f1542
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 73b00fb31a4c8f1e2db8ae1dcab522b0db44b1cbee4c2bb79cf59df1818c516dbbc5f060c3235a2baab8b285c5947cfe
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:d12079d043237f25e320c42aa4f189e013b2301cd2cae46709b3fc236b1b55052948e90cd57dd3346974dabe61a0e28a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = bb79c15599851619e575397c9e10951c49c840f30ec15e3320f600be6eac5d899bc1236f170254ce292765e853cc0459
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:d12079d043237f25e320c42aa4f189e013b2301cd2cae46709b3fc236b1b55052948e90cd57dd3346974dabe61a0e28a
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 9acbe9f41e06ae8f628277e9bf5f3cc8bb35586ccc1be1e0ab73199c674e156a3d72940e77f6df3c8e07728bc9c75ff6
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ed65de5e19dae7c8ecbcfe1c85cedda4c0e0320bbfa863cf8f7123a45b7454b
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 2beb905b5a41a4b60b903ec139a6dbd1c45ce4d31ff3af34b73ad31dec77838777b0ed0c62c816863982939bce20ff2f
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:2beb905b5a41a4b60b903ec139a6dbd1c45ce4d31ff3af34b73ad31dec77838777b0ed0c62c816863982939bce20ff2f
Ctrl.data = hexdata:99ffe011dc3a2f66aa5db47f4cbef2e2bf4619b4d25a830f859b13dbb1f8c1ae6007bf27616e9c45d8adae4d98c8e174
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 8097220d31a4dd82ceefcf40e805b314f9b7f25b246da9397a1417379e8ee08ee9f41dda7081945a7c1a6eb4a6a09296
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:2beb905b5a41a4b60b903ec139a6dbd1c45ce4d31ff3af34b73ad31dec77838777b0ed0c62c816863982939bce20ff2f
Ctrl.data = hexdata:99ffe011dc3a2f66aa5db47f4cbef2e2bf4619b4d25a830f859b13dbb1f8c1ae6007bf27616e9c45d8adae4d98c8e174
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 1fc2a842d11076c62432ddbc065a73c7a022d65cc382aefc74ebc07b95cff1dba2422cbd5ddf7e47ce9f9738c8deb5d1
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:2beb905b5a41a4b60b903ec139a6dbd1c45ce4d31ff3af34b73ad31dec77838777b0ed0c62c816863982939bce20ff2f
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 60651bc199972f8e1b97a2286d744bc9f5832cf28191ac6ce09135ca3ce3f2bd09e8b98052da27a1c5b1a425b5785de1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:60651bc199972f8e1b97a2286d744bc9f5832cf28191ac6ce09135ca3ce3f2bd09e8b98052da27a1c5b1a425b5785de1
Ctrl.data = hexdata:b207273145e7c5e17f9f088f23e271166d822b7d1850efe3641015560379312cef900012ae06bd1b97c423a6f4cacfe6
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 0eaef4e848bbd1927ff4263a9a6cf67ea1dd0c00af88cc00e31714387fe5706a2415fdc939a6167cbdc89fd9133ccca1
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:60651bc199972f8e1b97a2286d744bc9f5832cf28191ac6ce09135ca3ce3f2bd09e8b98052da27a1c5b1a425b5785de1
Ctrl.data = hexdata:b207273145e7c5e17f9f088f23e271166d822b7d1850efe3641015560379312cef900012ae06bd1b97c423a6f4cacfe6
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = ed0cce2c375b1690d5940de879205a6c859cc81904c1f9da882ba559bfb8fbcd7b24b3a6f58947d21a8023aced8ae156
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:60651bc199972f8e1b97a2286d744bc9f5832cf28191ac6ce09135ca3ce3f2bd09e8b98052da27a1c5b1a425b5785de1
Ctrl.data = hexdata:b207273145e7c5e17f9f088f23e271166d822b7d1850efe3641015560379312cef900012ae06bd1b97c423a6f4cacfe6
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 03f29110d0c506ff9306ef46b3ef76366fa5fc9e28f6aff85272bba972ba93590326b11677a4b9e5c320db84888a2b5d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:60651bc199972f8e1b97a2286d744bc9f5832cf28191ac6ce09135ca3ce3f2bd09e8b98052da27a1c5b1a425b5785de1
Ctrl.data = hexdata:6c6c915c1256ed57209751aa4850daa7454819858a0fedb12c373a7037abc50c7b547cdfd32c33cb8f6138c088165e61
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 52abe73f22784e9e5af068f7f3ded581bc5950c1a0923a0ea47a3357f8bfcf7f071b3178ec320a91f82286a81bfa3c43
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:3cf57a8d291350ce24d8633b603e2f0c515bc01c62540ad48a0abee30a49492cc3aa0e5a46fb514ea7af86f0ad0079f7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 40bff2dcbdee9a8b61f55017319943a546398712bb8a966ce898169d5802f49db9e5358a41ad2f2aef4897853267e92d
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:3cf57a8d291350ce24d8633b603e2f0c515bc01c62540ad48a0abee30a49492cc3aa0e5a46fb514ea7af86f0ad0079f7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = 954fb227097f71dcbd9acea908bcefab365bafeb4f0fbe1185511c75fa9d5cf935e2d9e3f0ac3a4327931a6cf0e142b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:1bfc5d5773f74aa53facc022cd186a00cabb76e156d2ea1abfb0f4889f4c129d
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = f2821923edba8641e31acd28f2c3617dc88aa10831fc605387ccbdfa1c5ede00e6df4a13c75d9ede1d8296ea24a92ed7
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f2821923edba8641e31acd28f2c3617dc88aa10831fc605387ccbdfa1c5ede00e6df4a13c75d9ede1d8296ea24a92ed7
Ctrl.data = hexdata:10bd98a2468a46f79b5e797a93e153d64cbaacc2b7b52fb62c492d695bd230c758fc290a504161f0f2372ead3f4eda2e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 31d469f1dc7fe92aa00eae4bc9ce3f625b00add7194bd40ed1e2ea8fc1ea653b458002ad4f7644e80c2dd9ad2c4930e3
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:f2821923edba8641e31acd28f2c3617dc88aa10831fc605387ccbdfa1c5ede00e6df4a13c75d9ede1d8296ea24a92ed7
Ctrl.data = hexdata:10bd98a2468a46f79b5e797a93e153d64cbaacc2b7b52fb62c492d695bd230c758fc290a504161f0f2372ead3f4eda2e
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 50a9866eff7c6875dff61dba25eab5d6fa4f73b4be5dd257fa6697f987c5fd2cd7e45c539939611f9255e99708a8763c
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:f2821923edba8641e31acd28f2c3617dc88aa10831fc605387ccbdfa1c5ede00e6df4a13c75d9ede1d8296ea24a92ed7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 4dbdcccdd2385d8b13dc59db55873d94524331a127e73e88cbcfec756a5b535ae7d7dd8ff73d48cd85fba01b66022b93
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4dbdcccdd2385d8b13dc59db55873d94524331a127e73e88cbcfec756a5b535ae7d7dd8ff73d48cd85fba01b66022b93
Ctrl.data = hexdata:c0c2d49e4fe8e5b14d557020548dec84b474bab505ef5e9e46c9ba774653286da331debce0b20d45bf216ae2e14879c5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = 4e48ccc5baf9fef7faca6b6488554afecdfe95aafe1735ad7132dfca679a398cb292072a20b3d654e77d4f4088c3c442
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4dbdcccdd2385d8b13dc59db55873d94524331a127e73e88cbcfec756a5b535ae7d7dd8ff73d48cd85fba01b66022b93
Ctrl.data = hexdata:c0c2d49e4fe8e5b14d557020548dec84b474bab505ef5e9e46c9ba774653286da331debce0b20d45bf216ae2e14879c5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = b6216139c37365152a9212fd9c1c196722aed27e18f9e3d7b1e85b4a4c1138a1b1067b232047bb64b87b3f929678e920
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4dbdcccdd2385d8b13dc59db55873d94524331a127e73e88cbcfec756a5b535ae7d7dd8ff73d48cd85fba01b66022b93
Ctrl.data = hexdata:c0c2d49e4fe8e5b14d557020548dec84b474bab505ef5e9e46c9ba774653286da331debce0b20d45bf216ae2e14879c5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = e6613af88be1d9293810ab50aad497da17e5225f7b8a164101220eb6550a244400b4da5b452e9b9e1a23d97c0af675bd
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:4dbdcccdd2385d8b13dc59db55873d94524331a127e73e88cbcfec756a5b535ae7d7dd8ff73d48cd85fba01b66022b93
Ctrl.data = hexdata:f3344607473544b81c603c2e454a746a8a4be1c160de9e179d3a18d7992e8e81b26e614915194a49559a5af162266469
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = f736aaa47bf602b96fa971f98110c76919b88e460cb9e0dc6ed39135e204638b3c00ed9bc5e7e4f66c90339a515cc76e
# New TLS 1.3 session starts here
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Output = 7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:1b49e91af94aa5b311518149a28aba1a0f22dfefb7e9cb1e38cae86451cbcebda3f94193398ae2b109831fc4ce3b6dfe
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6320652074726166666963
Output = 9c5f3f76bd2ec1e2cce62de12f6502c3588e52585d1cb2d35d4b4ca80cb98acd77b545275fd1021118c41b13ec14faca
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.data = hexdata:1b49e91af94aa5b311518149a28aba1a0f22dfefb7e9cb1e38cae86451cbcebda3f94193398ae2b109831fc4ce3b6dfe
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:6520657870206d6173746572
Output = a4a4fe8b35f44a35be31b532937514de2f79a7fa0db63241463ec04be6eb2e56288d579af1160c12d5218e42c921cfb3
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:219eb41da6bbbe2f14de92589983c15c6b84119ce6c515f32d1850835d73e8d6
Ctrl.salt = hexsalt:7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 431b7156622cc17132aa45139f01c9516abd140a5b15f7bac80be758f3447e7a31213aa83c6fc6e84436447b3c4dc717
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:431b7156622cc17132aa45139f01c9516abd140a5b15f7bac80be758f3447e7a31213aa83c6fc6e84436447b3c4dc717
Ctrl.data = hexdata:5b83ca74e83eacdda37b6a858e8bc05af8723e926ede3af9306a5d5057242b4cec28cfc092b31096ef52856ddec7d96d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632068732074726166666963
Output = 9cd9027a2964c3b088f7f7b870b1fe8a490f08951228e28dbddd6fcece8871d4f76d087caf4eea780707d4094f7c6d3c
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:431b7156622cc17132aa45139f01c9516abd140a5b15f7bac80be758f3447e7a31213aa83c6fc6e84436447b3c4dc717
Ctrl.data = hexdata:5b83ca74e83eacdda37b6a858e8bc05af8723e926ede3af9306a5d5057242b4cec28cfc092b31096ef52856ddec7d96d
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732068732074726166666963
Output = 77e5a6b8b7f8ecd805953b2fe7a0e71ede9216d09a6d7f82aecc9bf30c60039c7571164d192f5a1df0a4960afe8cc0d8
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.salt = hexsalt:431b7156622cc17132aa45139f01c9516abd140a5b15f7bac80be758f3447e7a31213aa83c6fc6e84436447b3c4dc717
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:64657269766564
Output = 6547c5bdc85b07b114ba5146f6eba34092ac27625897146b922d56da379a41bf8011fa8d2e88fa02065677fc7c930907
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:6547c5bdc85b07b114ba5146f6eba34092ac27625897146b922d56da379a41bf8011fa8d2e88fa02065677fc7c930907
Ctrl.data = hexdata:95033d93b572219981af9a974d9cc2d78cde24fb39e13766c304c53597843ff54ab0c91fa6174611b16da5271dce79c7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:632061702074726166666963
Output = be7f1f64963b74fff1aaecb5c9983692d1f2bb3dd71feeddd9f890eeda29d311793ded08b7bd9c4399e5bc20c5ec7d81
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:6547c5bdc85b07b114ba5146f6eba34092ac27625897146b922d56da379a41bf8011fa8d2e88fa02065677fc7c930907
Ctrl.data = hexdata:95033d93b572219981af9a974d9cc2d78cde24fb39e13766c304c53597843ff54ab0c91fa6174611b16da5271dce79c7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:732061702074726166666963
Output = eec520009350bd7c53c88bc30bb65e94bdb5a883dd386a454a557c457db49eb3d2725daaa7152fd893fd6367bff5c533
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:6547c5bdc85b07b114ba5146f6eba34092ac27625897146b922d56da379a41bf8011fa8d2e88fa02065677fc7c930907
Ctrl.data = hexdata:95033d93b572219981af9a974d9cc2d78cde24fb39e13766c304c53597843ff54ab0c91fa6174611b16da5271dce79c7
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:657870206d6173746572
Output = 0c529fb71c21986c91c4f2d47b5502065ba9ac2ac65559f1db6e1a09b9b36b6f4cbed7bb347a690b5b23c76f77afc6b5
KDF = TLS13-KDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.digest = digest:SHA2-384
Ctrl.key = hexkey:6547c5bdc85b07b114ba5146f6eba34092ac27625897146b922d56da379a41bf8011fa8d2e88fa02065677fc7c930907
Ctrl.data = hexdata:5371106674e76ed37b98539d231b84a663abe1818125034e91b2debc4280ba942381c0426e338d43951e5206a09f30d2
Ctrl.prefix = hexprefix:746c73313320
Ctrl.label = hexlabel:726573206d6173746572
Output = 7eacca12e407d32a062bc0aabbcbc9d32953cd50b131fcc63d34e5a4b200347098001b6e43c28a68705edac3c967285b
Title = TLS13-KDF bad mode test
KDF = TLS13-KDF
Ctrl.mode = mode:EXTRACT_AND_EXPAND
Ctrl.digest = digest:SHA256
Result = KDF_CTRL_ERROR
+# Test that salt of arbitrary length works
+FIPSversion = >=3.4.0
+KDF = TLS13-KDF
+Ctrl.mode = mode:EXTRACT_ONLY
+Ctrl.digest = digest:SHA2-256
+Ctrl.key = hexkey:f8af6aea2d397baf2948a25b2834200692cff17eee9165e4e27babee9edefd05
+Ctrl.salt = hexsalt:00010203040506070809000102030405060708090001020304050607080900010203040506070809
+Ctrl.prefix = hexprefix:746c73313320
+Ctrl.label = hexlabel:64657269766564
+Output = ef0aa4925ab6f4588759e15dfadcf7602ca7aa39ebb092bd7ab48f6a68c54449
diff --git a/crypto/openssl/test/recipes/80-test_cmp_http.t b/crypto/openssl/test/recipes/80-test_cmp_http.t
index 0ca547354fc7..c704cc758e91 100644
--- a/crypto/openssl/test/recipes/80-test_cmp_http.t
+++ b/crypto/openssl/test/recipes/80-test_cmp_http.t
@@ -1,298 +1,298 @@
#! /usr/bin/env perl
-# Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
# Copyright Nokia 2007-2019
# Copyright Siemens AG 2015-2019
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
use strict;
use warnings;
use POSIX;
use OpenSSL::Test qw/:DEFAULT cmdstr data_file data_dir srctop_dir bldtop_dir result_dir/;
use OpenSSL::Test::Utils;
BEGIN {
setup("test_cmp_http");
}
use lib srctop_dir('Configurations');
use lib bldtop_dir('.');
plan skip_all => "These tests are not supported in a fuzz build"
if config('options') =~ /-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION|enable-fuzz-afl/;
plan skip_all => "These tests are not supported in a no-cmp build"
if disabled("cmp");
plan skip_all => "These tests are not supported in a no-ec build"
if disabled("ec");
plan skip_all => "These tests are not supported in a no-sock build"
if disabled("sock");
plan skip_all => "Tests involving local HTTP server not available on Windows or VMS"
if $^O =~ /^(VMS|MSWin32|msys)$/;
plan skip_all => "Tests involving local HTTP server not available in cross-compile builds"
if defined $ENV{EXE_SHELL};
sub chop_dblquot { # chop any leading and trailing '"' (needed for Windows)
my $str = shift;
$str =~ s/^\"(.*?)\"$/$1/;
return $str;
}
my $proxy = chop_dblquot($ENV{http_proxy} // $ENV{HTTP_PROXY} // "");
$proxy = "<EMPTY>" if $proxy eq "";
$proxy =~ s{^https?://}{}i;
my $no_proxy = $ENV{no_proxy} // $ENV{NO_PROXY};
my @app = qw(openssl cmp);
# the CMP server configuration consists of:
my $ca_dn; # The CA's Distinguished Name
my $server_dn; # The server's Distinguished Name
my $server_host;# The server's host name or IP address
my $server_port;# The server's port
my $server_tls; # The server's TLS port, if any, or 0
my $server_path;# The server's CMP alias
my $server_cert;# The server's cert
my $kur_port; # The server's port for kur (cert update)
my $pbm_port; # The server port to be used for PBM
my $pbm_ref; # The reference for PBM
my $pbm_secret; # The secret for PBM
my $column; # The column number of the expected result
my $sleep = 0; # The time to sleep between two requests
my $server_fh; # Server file handle
# The local $server_name variables below are among others taken as the name of a
# sub-directory with server-specific certs etc. and CA-specific config section.
sub load_config {
my $server_name = shift;
my $section = shift;
my $test_config = $ENV{OPENSSL_CMP_CONFIG} // "$server_name/test.cnf";
open (CH, $test_config) or die "Cannot open $test_config: $!";
my $active = 0;
while (<CH>) {
if (m/\[\s*$section\s*\]/) {
$active = 1;
} elsif (m/\[\s*.*?\s*\]/) {
$active = 0;
} elsif ($active) {
$ca_dn = $1 eq "" ? '""""' : $1 if m/^\s*ca_dn\s*=\s*(.*)?\s*$/;
$server_dn = $1 eq "" ? '""""' : $1 if m/^\s*server_dn\s*=\s*(.*)?\s*$/;
$server_host = $1 eq "" ? '""""' : $1 if m/^\s*server_host\s*=\s*(\S*)?\s*(\#.*)?$/;
$server_port = $1 eq "" ? '""""' : $1 if m/^\s*server_port\s*=\s*(.*)?\s*$/;
$server_tls = $1 eq "" ? '""""' : $1 if m/^\s*server_tls\s*=\s*(.*)?\s*$/;
$server_path = $1 eq "" ? '""""' : $1 if m/^\s*server_path\s*=\s*(.*)?\s*$/;
$server_cert = $1 eq "" ? '""""' : $1 if m/^\s*server_cert\s*=\s*(.*)?\s*$/;
$kur_port = $1 eq "" ? '""""' : $1 if m/^\s*kur_port\s*=\s*(.*)?\s*$/;
$pbm_port = $1 eq "" ? '""""' : $1 if m/^\s*pbm_port\s*=\s*(.*)?\s*$/;
$pbm_ref = $1 eq "" ? '""""' : $1 if m/^\s*pbm_ref\s*=\s*(.*)?\s*$/;
$pbm_secret = $1 eq "" ? '""""' : $1 if m/^\s*pbm_secret\s*=\s*(.*)?\s*$/;
$column = $1 eq "" ? '""""' : $1 if m/^\s*column\s*=\s*(.*)?\s*$/;
$sleep = $1 eq "" ? '""""' : $1 if m/^\s*sleep\s*=\s*(.*)?\s*$/;
}
}
close CH;
die "Cannot find all CMP server config values in $test_config section [$section]\n"
if !defined $ca_dn
|| !defined $server_dn || !defined $server_host
|| !defined $server_port || !defined $server_tls
|| !defined $server_path || !defined $server_cert
|| !defined $kur_port || !defined $pbm_port
|| !defined $pbm_ref || !defined $pbm_secret
|| !defined $column || !defined $sleep;
$server_dn = $server_dn // $ca_dn;
}
my @server_configurations = ("Mock");
@server_configurations = split /\s+/, $ENV{OPENSSL_CMP_SERVER} if $ENV{OPENSSL_CMP_SERVER};
# set env variable, e.g., OPENSSL_CMP_SERVER="Mock Insta" to include further CMP servers
my @all_aspects = ("connection", "verification", "credentials", "commands", "enrollment");
@all_aspects = split /\s+/, $ENV{OPENSSL_CMP_ASPECTS} if $ENV{OPENSSL_CMP_ASPECTS};
# set env variable, e.g., OPENSSL_CMP_ASPECTS="commands enrollment" to select specific aspects
my $faillog;
my $file = $ENV{HARNESS_FAILLOG}; # pathname relative to result_dir
if ($file) {
open($faillog, ">", $file) or die "Cannot open $file for writing: $!";
}
sub test_cmp_http {
my $server_name = shift;
my $aspect = shift;
my $n = shift;
my $i = shift;
my $title = shift;
my $params = shift;
my $expected_result = shift;
$params = [ '-server', "127.0.0.1:$server_port", @$params ]
unless grep { $_ eq '-server' } @$params;
my $cmd = app([@app, @$params]);
unless (is(my $actual_result = run($cmd), $expected_result, $title)) {
if ($faillog) {
my $quote_spc_empty = sub { $_ eq "" ? '""' : $_ =~ m/ / ? '"'.$_.'"' : $_ };
my $invocation = cmdstr($cmd, display => 1);
print $faillog "$server_name $aspect \"$title\" ($i/$n)".
" expected=$expected_result actual=$actual_result\n";
print $faillog "$invocation\n\n";
}
}
}
sub test_cmp_http_aspect {
my $server_name = shift;
my $aspect = shift;
my $tests = shift;
subtest "CMP app CLI $server_name $aspect\n" => sub {
my $n = scalar @$tests;
plan tests => $n;
my $i = 1;
foreach (@$tests) {
test_cmp_http($server_name, $aspect, $n, $i++, $$_[0], $$_[1], $$_[2]);
sleep($sleep);
}
};
# not unlinking test.certout*.pem, test.cacerts.pem, and test.extracerts.pem
}
# The input files for the tests done here dynamically depend on the test server
# selected (where the Mock server used by default is just one possibility).
# On the other hand the main test configuration file test.cnf, which references
# several server-dependent input files by relative file names, is static.
# Moreover the tests use much greater variety of input files than output files.
# Therefore we chose the current directory as a subdirectory of $SRCTOP and it
# was simpler to prepend the output file names by BLDTOP than doing the tests
# from $BLDTOP/test-runs/test_cmp_http and prepending the input files by SRCTOP.
indir data_dir() => sub {
plan tests => 1 + @server_configurations * @all_aspects
- (grep(/^Mock$/, @server_configurations)
&& grep(/^certstatus$/, @all_aspects));
foreach my $server_name (@server_configurations) {
$server_name = chop_dblquot($server_name);
load_config($server_name, $server_name);
{
SKIP: {
my $pid;
if ($server_name eq "Mock") {
indir "Mock" => sub {
$pid = start_mock_server("");
die "Cannot start or find the started CMP mock server" unless $pid;
}
}
foreach my $aspect (@all_aspects) {
$aspect = chop_dblquot($aspect);
next if $server_name eq "Mock" && $aspect eq "certstatus";
load_config($server_name, $aspect); # update with any aspect-specific settings
indir $server_name => sub {
my $tests = load_tests($server_name, $aspect);
test_cmp_http_aspect($server_name, $aspect, $tests);
};
};
stop_mock_server($pid) if $pid;
ok(1, "killing mock server");
}
}
};
};
close($faillog) if $faillog;
sub load_tests {
my $server_name = shift;
my $aspect = shift;
my $test_config = $ENV{OPENSSL_CMP_CONFIG} // "$server_name/test.cnf";
my $file = data_file("test_$aspect.csv");
my $result_dir = result_dir();
my @result;
open(my $data, '<', $file) || die "Cannot open $file for reading: $!";
LOOP:
while (my $line = <$data>) {
chomp $line;
$line =~ s{\r\n}{\n}g; # adjust line endings
$line =~ s{_CA_DN}{$ca_dn}g;
$line =~ s{_SERVER_DN}{$server_dn}g;
$line =~ s{_SERVER_HOST}{$server_host}g;
$line =~ s{_SERVER_PORT}{$server_port}g;
$line =~ s{_SERVER_TLS}{$server_tls}g;
$line =~ s{_SERVER_PATH}{$server_path}g;
$line =~ s{_SERVER_CERT}{$server_cert}g;
$line =~ s{_KUR_PORT}{$kur_port}g;
$line =~ s{_PBM_PORT}{$pbm_port}g;
$line =~ s{_PBM_REF}{$pbm_ref}g;
$line =~ s{_PBM_SECRET}{$pbm_secret}g;
$line =~ s{_RESULT_DIR}{$result_dir}g;
next LOOP if $server_tls == 0 && $line =~ m/,\s*-tls_used\s*,/;
my $noproxy = $no_proxy;
if ($line =~ m/,\s*-no_proxy\s*,(.*?)(,|$)/) {
$noproxy = $1;
} elsif ($server_host eq "127.0.0.1") {
# do connections to localhost (e.g., Mock server) without proxy
$line =~ s{-section,,}{-section,,-no_proxy,127.0.0.1,} ;
}
if ($line =~ m/,\s*-proxy\s*,/) {
next LOOP if $no_proxy && ($noproxy =~ $server_host);
} else {
$line =~ s{-section,,}{-section,,-proxy,$proxy,};
}
$line =~ s{-section,,}{-section,,-certout,$result_dir/test.cert.pem,};
$line =~ s{-section,,}{-config,../$test_config,-section,$server_name $aspect,};
my @fields = grep /\S/, split ",", $line;
s/^<EMPTY>$// for (@fields); # used for proxy=""
s/^\s+// for (@fields); # remove leading whitespace from elements
s/\s+$// for (@fields); # remove trailing whitespace from elements
s/^\"(\".*?\")\"$/$1/ for (@fields); # remove escaping from quotation marks from elements
my $expected_result = $fields[$column];
my $description = 1;
my $title = $fields[$description];
next LOOP if (!defined($expected_result)
|| ($expected_result ne 0 && $expected_result ne 1));
@fields = grep {$_ ne 'BLANK'} @fields[$description + 1 .. @fields - 1];
push @result, [$title, \@fields, $expected_result];
}
close($data);
return \@result;
}
sub start_mock_server {
my $args = $_[0]; # optional further CLI arguments
my $cmd = cmdstr(app([@app, '-config', 'server.cnf',
$args ? $args : ()]), display => 1);
print "Current directory is ".getcwd()."\n";
print "Launching mock server: $cmd\n";
die "Invalid port: $server_port" unless $server_port =~ m/^\d+$/;
- my $pid = open($server_fh, "$cmd|") or die "Trying to $cmd";
+ my $pid = open($server_fh, "$cmd 2>".result_dir()."/error.txt |") or die "Trying to $cmd";
print "Pid is: $pid\n";
if ($server_port == 0) {
# Find out the actual server port
while (<$server_fh>) {
print "Server output: $_";
next if m/using section/;
s/\R$//; # Better chomp
($server_port, $pid) = ($1, $2) if /^ACCEPT\s.*:(\d+) PID=(\d+)$/;
last; # Do not loop further to prevent hangs on server misbehavior
}
}
unless ($server_port > 0) {
stop_mock_server($pid);
return 0;
}
$server_tls = $kur_port = $pbm_port = $server_port;
return $pid;
}
sub stop_mock_server {
my $pid = $_[0];
print "Killing mock server with pid=$pid\n";
kill('KILL', $pid);
waitpid($pid, 0);
}
diff --git a/crypto/openssl/test/recipes/80-test_cmp_http_data/test_connection.csv b/crypto/openssl/test/recipes/80-test_cmp_http_data/test_connection.csv
index 33a572a29da1..cc012411ea5f 100644
--- a/crypto/openssl/test/recipes/80-test_cmp_http_data/test_connection.csv
+++ b/crypto/openssl/test/recipes/80-test_cmp_http_data/test_connection.csv
@@ -1,49 +1,49 @@
expected,description, -section,val, -server,val, -proxy,val, -no_proxy,val, -tls_used,noarg, -path,val, -msg_timeout,int, -total_timeout,int, -keep_alive,val
,Message transfer options:,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,
1,default config, -section,,,,,,,,BLANK,,,,BLANK,,BLANK,,BLANK,
-TBD,Domain name, -section,, -server,_SERVER_CN:_SERVER_PORT,,,,,,,,,,,,,,
-TBD,IP address, -section,, -server,_SERVER_IP:_SERVER_PORT,,,,,,,,,,,,,,
+1,disabled as not supported by some host IP configurations: server domain name, -section,, -server,localhost:_SERVER_PORT,,,,,,,,,,,,,,
+1,disabled as not supported by some host IP configurations: server IPv6 address, -section,, -server,[::1]:_SERVER_PORT,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,
0,wrong server, -section,, -server,xn--rksmrgs-5wao1o.example.com:_SERVER_PORT,,,,,BLANK,,,, -msg_timeout,1,BLANK,,BLANK,
0,wrong server port, -section,, -server,_SERVER_HOST:99,,,,,BLANK,,,, -msg_timeout,1,BLANK,,BLANK,
0,server default port, -section,, -server,_SERVER_HOST,,,,,BLANK,,,, -msg_timeout,1,BLANK,,BLANK,
0,server port out of range, -section,, -server,_SERVER_HOST:65536,,,,,BLANK,,,,BLANK,,BLANK,,BLANK,
0,server port negative, -section,, -server,_SERVER_HOST:-10,,,,,BLANK,,,,BLANK,,BLANK,,BLANK,
0,server missing argument, -section,, -server,,,,,,BLANK,,,,BLANK,,BLANK,,BLANK,
0,server with default port, -section,, -server,_SERVER_HOST,,,,,BLANK,,,,BLANK,,BLANK,,BLANK,
0,server port bad syntax: leading garbage, -section,, -server,_SERVER_HOST:x/+80,,,,,BLANK,,,,BLANK,,BLANK,,BLANK,
0,server port bad synatx: trailing garbage, -section,, -server,_SERVER_HOST:_SERVER_PORT+/x.,,,,,BLANK,,,,BLANK,,BLANK,,BLANK,
0,server with wrong port, -section,, -server,_SERVER_HOST:999,,,,,BLANK,,,,-msg_timeout,1,BLANK,,BLANK,
TBD,server IP address with TLS port, -section,, -server,_SERVER_IP:_SERVER_TLS,,,,,BLANK,,,,BLANK,,BLANK,,BLANK,
,,,,,,,,,,,,,,,,,,,
0,proxy port bad syntax: leading garbage, -section,, -server,_SERVER_HOST:_SERVER_PORT, -proxy,127.0.0.1:x*/8888, -no_proxy,nonmatch.com,BLANK,,,,-msg_timeout,1,BLANK,,BLANK,
0,proxy port out of range, -section,, -server,_SERVER_HOST:_SERVER_PORT, -proxy,127.0.0.1:65536, -no_proxy,nonmatch.com,BLANK,,,,-msg_timeout,1,BLANK,,BLANK,
0,proxy default port, -section,, -server,_SERVER_HOST:_SERVER_PORT, -proxy,127.0.0.1, -no_proxy,nonmatch.com,BLANK,,,,-msg_timeout,1,BLANK,,BLANK,
0,proxy missing argument, -section,, -server,_SERVER_HOST:_SERVER_PORT, -proxy,, -no_proxy,nonmatch.com,BLANK,,,,BLANK,,BLANK,,BLANK,
,,,,,,,,,,,,,,,,,,,
1,path explicit, -section,, -server,_SERVER_HOST:_SERVER_PORT,,,,,BLANK,, -path,_SERVER_PATH,BLANK,,BLANK,,BLANK,
1,path overrides -server path, -section,, -server,_SERVER_HOST:_SERVER_PORT/ignored,,,,,BLANK,, -path,_SERVER_PATH,BLANK,,BLANK,,BLANK,
1,path default -server path, -section,, -server,_SERVER_HOST:_SERVER_PORT/_SERVER_PATH,,,,,BLANK,, -path,"""",BLANK,,BLANK,,BLANK,
0,path missing argument, -section,,,,,,,,BLANK,, -path,,BLANK,,BLANK,,BLANK,
0,path wrong, -section,,,,,,,,BLANK,, -path,/publicweb/cmp/example,BLANK,,BLANK,,BLANK,
1,path with additional '/'s fine according to RFC 3986, -section,,,,,,,,BLANK,, -path,/_SERVER_PATH////,BLANK,,BLANK,,BLANK,
0,path mixed case, -section,,,,,,,,BLANK,, -path,pKiX/,BLANK,,BLANK,,BLANK,
0,path upper case, -section,,,,,,,,BLANK,, -path,PKIX/,BLANK,,BLANK,,BLANK,
,,,,,,,,,,,,,,,,,,,
0,msg_timeout missing argument, -section,,,,,,,,BLANK,,,, -msg_timeout,,BLANK,,BLANK,
0,msg_timeout negative, -section,,,,,,,,BLANK,,,, -msg_timeout,-5,BLANK,,BLANK,
1,msg_timeout 5, -section,,,,,,,,BLANK,,,, -msg_timeout,5,BLANK,,BLANK,
1,msg_timeout 0, -section,,,,,,,,BLANK,,,, -msg_timeout,0,BLANK,,BLANK,
,,,,,,,,,,,,,,,,,,,
0,total_timeout missing argument, -section,,,,,,,,BLANK,,,,BLANK,, -total_timeout,,BLANK,
0,total_timeout negative, -section,,,,,,,,BLANK,,,,BLANK,, -total_timeout,-5,BLANK,
1,total_timeout 10, -section,,,,,,,,BLANK,,,,BLANK,, -total_timeout,10,BLANK,
1,total_timeout 0, -section,,,,,,,,BLANK,,,,BLANK,, -total_timeout,0,BLANK,
,,,,,,,,,,,,,,,,,,,
0,keep_alive missing argument, -section,,,,,,,,BLANK,,,,BLANK,,BLANK,, -keep_alive,
0,keep_alive negative, -section,,,,,,,,BLANK,,,,BLANK,,BLANK,, -keep_alive,-1
1,keep_alive 0, -section,,,,,,,,BLANK,,,,BLANK,,BLANK,, -keep_alive,0
1,keep_alive 1, -section,,,,,,,,BLANK,,,,BLANK,,BLANK,, -keep_alive,1
1,keep_alive 2, -section,,,,,,,,BLANK,,,,BLANK,,BLANK,, -keep_alive,2
0,keep_alive 3, -section,,,,,,,,BLANK,,,,BLANK,,BLANK,, -keep_alive,3
diff --git a/crypto/openssl/test/recipes/80-test_cms.t b/crypto/openssl/test/recipes/80-test_cms.t
index 31f9fbd1280a..0e8b0259f1c2 100644
--- a/crypto/openssl/test/recipes/80-test_cms.t
+++ b/crypto/openssl/test/recipes/80-test_cms.t
@@ -1,1071 +1,1128 @@
#! /usr/bin/env perl
-# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
use strict;
use warnings;
use POSIX;
use File::Spec::Functions qw/catfile/;
use File::Compare qw/compare_text compare/;
use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file with data_file/;
use OpenSSL::Test::Utils;
BEGIN {
setup("test_cms");
}
use lib srctop_dir('Configurations');
use lib bldtop_dir('.');
my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
+my $old_fips = 0;
plan skip_all => "CMS is not supported by this OpenSSL build"
if disabled("cms");
my $provpath = bldtop_dir("providers");
# Some tests require legacy algorithms to be included.
my @legacyprov = ("-provider-path", $provpath,
"-provider", "default",
"-provider", "legacy" );
my @defaultprov = ("-provider-path", $provpath,
"-provider", "default");
my @config = ( );
my $provname = 'default';
my $datadir = srctop_dir("test", "recipes", "80-test_cms_data");
my $smdir = srctop_dir("test", "smime-certs");
my $smcont = srctop_file("test", "smcont.txt");
my $smcont_zero = srctop_file("test", "smcont_zero.txt");
my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
= disabled qw/des dh dsa ec ec2m rc2 zlib/;
$no_rc2 = 1 if disabled("legacy");
-plan tests => 19;
+plan tests => 20;
ok(run(test(["pkcs7_test"])), "test pkcs7");
unless ($no_fips) {
- @config = ( "-config", srctop_file("test", "fips-and-base.cnf") );
+ my $provconf = srctop_file("test", "fips-and-base.cnf");
+ @config = ( "-config", $provconf );
$provname = 'fips';
+
+ run(test(["fips_version_test", "-config", $provconf, "<3.4.0"]),
+ capture => 1, statusvar => $old_fips);
}
$ENV{OPENSSL_TEST_LIBCTX} = "1";
my @prov = ("-provider-path", $provpath,
@config,
"-provider", $provname);
my $smrsa1024 = catfile($smdir, "smrsa1024.pem");
my $smrsa1 = catfile($smdir, "smrsa1.pem");
my $smroot = catfile($smdir, "smroot.pem");
my @smime_pkcs7_tests = (
[ "signed content DER format, RSA key",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
"-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed detached content DER format, RSA key",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
"-signer", $smrsa1, "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt",
"-content", $smcont ],
\&final_compare
],
[ "signed content test streaming BER format, RSA",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
"-stream",
"-signer", $smrsa1, "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content DER format, DSA key",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
"-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed detached content DER format, DSA key",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
"-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt",
"-content", $smcont ],
\&final_compare
],
[ "signed detached content DER format, add RSA signer (with DSA existing)",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
"-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
[ "{cmd1}", @prov, "-resign", "-in", "{output}.cms", "-inform", "DER", "-outform", "DER",
"-signer", $smrsa1, "-out", "{output}2.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt",
"-content", $smcont ],
\&final_compare
],
[ "signed content test streaming BER format, DSA key",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
"-nodetach", "-stream",
"-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming BER format, 2 DSA and 2 RSA keys",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
"-nodetach", "-stream",
"-signer", $smrsa1,
"-signer", catfile($smdir, "smrsa2.pem"),
"-signer", catfile($smdir, "smdsa1.pem"),
"-signer", catfile($smdir, "smdsa2.pem"),
"-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming BER format, 2 DSA and 2 RSA keys, no attributes",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
"-noattr", "-nodetach", "-stream",
"-signer", $smrsa1,
"-signer", catfile($smdir, "smrsa2.pem"),
"-signer", catfile($smdir, "smdsa1.pem"),
"-signer", catfile($smdir, "smdsa2.pem"),
"-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content S/MIME format, RSA key SHA1",
[ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-md", "sha1",
"-certfile", $smroot,
"-signer", $smrsa1, "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed zero-length content S/MIME format, RSA key SHA1",
[ "{cmd1}", @defaultprov, "-sign", "-in", $smcont_zero, "-md", "sha1",
"-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&zero_compare
],
[ "signed content test streaming S/MIME format, 2 DSA and 2 RSA keys",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
"-signer", $smrsa1,
"-signer", catfile($smdir, "smrsa2.pem"),
"-signer", catfile($smdir, "smdsa1.pem"),
"-signer", catfile($smdir, "smdsa2.pem"),
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming multipart S/MIME format, 2 DSA and 2 RSA keys",
[ "{cmd1}", @prov, "-sign", "-in", $smcont,
"-signer", $smrsa1,
"-signer", catfile($smdir, "smrsa2.pem"),
"-signer", catfile($smdir, "smdsa1.pem"),
"-signer", catfile($smdir, "smdsa2.pem"),
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, DES, 3 recipients",
[ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
$smrsa1,
catfile($smdir, "smrsa2.pem"),
catfile($smdir, "smrsa3.pem") ],
[ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, DES, 3 recipients, 3rd used",
[ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
$smrsa1,
catfile($smdir, "smrsa2.pem"),
catfile($smdir, "smrsa3.pem") ],
[ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa3.pem"),
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, DES, 3 recipients, cert and key files used",
[ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
$smrsa1,
catfile($smdir, "smrsa2.pem"),
catfile($smdir, "smrsa3-cert.pem") ],
[ "{cmd2}", @defaultprov, "-decrypt",
"-recip", catfile($smdir, "smrsa3-cert.pem"),
"-inkey", catfile($smdir, "smrsa3-key.pem"),
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, AES-256 cipher, 3 recipients",
[ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
"-aes256", "-stream", "-out", "{output}.cms",
$smrsa1,
catfile($smdir, "smrsa2.pem"),
catfile($smdir, "smrsa3.pem") ],
[ "{cmd2}", @prov, "-decrypt", "-recip", $smrsa1,
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
);
my @smime_cms_tests = (
[ "signed content test streaming BER format, 2 DSA and 2 RSA keys, keyid",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
"-nodetach", "-keyid",
"-signer", $smrsa1,
"-signer", catfile($smdir, "smrsa2.pem"),
"-signer", catfile($smdir, "smdsa1.pem"),
"-signer", catfile($smdir, "smdsa2.pem"),
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming PEM format, 2 DSA and 2 RSA keys",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
"-signer", $smrsa1,
"-signer", catfile($smdir, "smrsa2.pem"),
"-signer", catfile($smdir, "smdsa1.pem"),
"-signer", catfile($smdir, "smdsa2.pem"),
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content MIME format, RSA key, signed receipt request",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
"-signer", $smrsa1,
"-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
"-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed receipt MIME format, RSA key",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
"-signer", $smrsa1,
"-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
"-out", "{output}.cms" ],
[ "{cmd1}", @prov, "-sign_receipt", "-in", "{output}.cms",
"-signer", catfile($smdir, "smrsa2.pem"), "-out", "{output}2.cms" ],
[ "{cmd2}", @prov, "-verify_receipt", "{output}2.cms", "-in", "{output}.cms",
"-CAfile", $smroot ]
],
[ "enveloped content test streaming S/MIME format, DES, 3 recipients, keyid",
[ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms", "-keyid",
$smrsa1,
catfile($smdir, "smrsa2.pem"),
catfile($smdir, "smrsa3.pem") ],
[ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming PEM format, AES-256-CBC cipher, KEK",
[ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
"-stream", "-out", "{output}.cms",
"-secretkey", "000102030405060708090A0B0C0D0E0F",
"-secretkeyid", "C0FEE0" ],
[ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
"-inform", "PEM",
"-secretkey", "000102030405060708090A0B0C0D0E0F",
"-secretkeyid", "C0FEE0" ],
\&final_compare
],
[ "enveloped content test streaming PEM format, AES-256-GCM cipher, KEK",
[ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes-128-gcm",
"-stream", "-out", "{output}.cms",
"-secretkey", "000102030405060708090A0B0C0D0E0F",
"-secretkeyid", "C0FEE0" ],
[ "{cmd2}", "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
"-inform", "PEM",
"-secretkey", "000102030405060708090A0B0C0D0E0F",
"-secretkeyid", "C0FEE0" ],
\&final_compare
],
[ "enveloped content test streaming PEM format, KEK, key only",
[ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
"-stream", "-out", "{output}.cms",
"-secretkey", "000102030405060708090A0B0C0D0E0F",
"-secretkeyid", "C0FEE0" ],
[ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
"-inform", "PEM",
"-secretkey", "000102030405060708090A0B0C0D0E0F" ],
\&final_compare
],
[ "data content test streaming PEM format",
[ "{cmd1}", @prov, "-data_create", "-in", $smcont, "-outform", "PEM",
"-nodetach", "-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-data_out", "-in", "{output}.cms", "-inform", "PEM",
"-out", "{output}.txt" ],
\&final_compare
],
[ "encrypted content test streaming PEM format, 128 bit RC2 key",
[ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
"-in", $smcont, "-outform", "PEM",
"-rc2", "-secretkey", "000102030405060708090A0B0C0D0E0F",
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
"-inform", "PEM",
"-secretkey", "000102030405060708090A0B0C0D0E0F",
"-out", "{output}.txt" ],
\&final_compare
],
[ "encrypted content test streaming PEM format, 40 bit RC2 key",
[ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
"-in", $smcont, "-outform", "PEM",
"-rc2", "-secretkey", "0001020304",
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
"-inform", "PEM",
"-secretkey", "0001020304", "-out", "{output}.txt" ],
\&final_compare
],
[ "encrypted content test streaming PEM format, triple DES key",
[ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
"-des3", "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
"-inform", "PEM",
"-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
"-out", "{output}.txt" ],
\&final_compare
],
[ "encrypted content test streaming PEM format, 128 bit AES key",
[ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
"-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
"-inform", "PEM",
"-secretkey", "000102030405060708090A0B0C0D0E0F",
"-out", "{output}.txt" ],
\&final_compare
],
+
+ [ "encrypted content test streaming PEM format -noout, 128 bit AES key",
+ [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
+ "-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
+ "-stream", "-noout" ],
+ [ "{cmd2}", @prov, "-help" ]
+ ],
);
my @smime_cms_cades_tests = (
[ "signed content DER format, RSA key, CAdES-BES compatible",
[ "{cmd1}", @prov, "-sign", "-cades", "-in", $smcont, "-outform", "DER",
"-nodetach",
"-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
[ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha256", "-in", $smcont, "-outform",
"DER", "-nodetach", "-certfile", $smroot,
"-signer", $smrsa1, "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content DER format, RSA key, SHA512 md, CAdES-BES compatible",
[ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha512", "-in", $smcont, "-outform",
"DER", "-nodetach", "-certfile", $smroot,
"-signer", $smrsa1, "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
[ "{cmd1}", @prov, "-sign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
"-in", $smcont, "-outform", "DER",
"-certfile", $smroot, "-signer", $smrsa1,
"-outform", "DER", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "resigned content DER format, RSA key, SHA256 md, CAdES-BES compatible",
[ "{cmd1}", @prov, "-sign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
"-in", $smcont, "-outform", "DER",
"-certfile", $smroot, "-signer", $smrsa1,
"-outform", "DER", "-out", "{output}.cms" ],
[ "{cmd1}", @prov, "-resign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
"-inform", "DER", "-in", "{output}.cms",
"-certfile", $smroot, "-signer", catfile($smdir, "smrsa2.pem"),
"-outform", "DER", "-out", "{output}2.cms" ],
[ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}2.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
);
my @smime_cms_cades_ko_tests = (
[ "sign content DER format, RSA key, not CAdES-BES compatible",
[ @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
"-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
"fail to verify token since requiring CAdES-BES compatibility",
[ @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
]
);
# cades options test - check that some combinations are rejected
my @smime_cms_cades_invalid_option_tests = (
[
[ "-cades", "-noattr" ],
],[
[ "-verify", "-cades", "-noattr" ],
],[
[ "-verify", "-cades", "-noverify" ],
],
);
my @smime_cms_comp_tests = (
[ "compressed content test streaming PEM format",
[ "{cmd1}", @prov, "-compress", "-in", $smcont, "-outform", "PEM", "-nodetach",
"-stream", "-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-uncompress", "-in", "{output}.cms", "-inform", "PEM",
"-out", "{output}.txt" ],
\&final_compare
]
);
my @smime_cms_param_tests = (
[ "signed content test streaming PEM format, RSA keys, PSS signature",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
"-signer", $smrsa1,
"-keyopt", "rsa_padding_mode:pss",
"-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=max",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
"-signer", $smrsa1,
"-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:max",
"-out", "{output}.cms" ],
sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 222; },
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming PEM format, RSA keys, PSS signature, no attributes",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
"-noattr", "-signer", $smrsa1,
"-keyopt", "rsa_padding_mode:pss",
"-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming PEM format, RSA keys, PSS signature, SHA384 MGF1",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
"-signer", $smrsa1,
"-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_mgf1_md:sha384",
"-out", "{output}.cms" ],
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=16",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
"-signer", $smrsa1, "-md", "sha256",
"-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:16",
"-out", "{output}.cms" ],
sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 16; },
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=digest",
[ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
"-signer", $smrsa1, "-md", "sha256",
"-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:digest",
"-out", "{output}.cms" ],
# digest is SHA-256, which produces 32 bytes of output
sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 32; },
[ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
"-CAfile", $smroot, "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, DES, OAEP default parameters",
[ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
"-recip", $smrsa1,
"-keyopt", "rsa_padding_mode:oaep" ],
[ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, DES, OAEP SHA256",
[ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
"-recip", $smrsa1,
"-keyopt", "rsa_padding_mode:oaep",
"-keyopt", "rsa_oaep_md:sha256" ],
[ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, DES, ECDH",
[ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
"-recip", catfile($smdir, "smec1.pem") ],
[ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, DES, ECDH, 2 recipients, key only used",
[ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
catfile($smdir, "smec1.pem"),
catfile($smdir, "smec3.pem") ],
[ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smec3.pem"),
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, ECDH, DES, key identifier",
[ "{cmd1}", @defaultprov, "-encrypt", "-keyid", "-in", $smcont,
"-stream", "-out", "{output}.cms",
"-recip", catfile($smdir, "smec1.pem") ],
[ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, ECDH, AES-128-CBC, SHA256 KDF",
[ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
"-recip", catfile($smdir, "smec1.pem"), "-aes128",
"-keyopt", "ecdh_kdf_md:sha256" ],
+ sub { my %opts = @_; smimeType_matches("$opts{output}.cms", "enveloped-data"); },
[ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, ECDH, AES-128-GCM cipher, SHA256 KDF",
[ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
"-recip", catfile($smdir, "smec1.pem"), "-aes-128-gcm", "-keyopt", "ecdh_kdf_md:sha256" ],
+ sub { my %opts = @_; smimeType_matches("$opts{output}.cms", "authEnveloped-data"); },
[ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
],
[ "enveloped content test streaming S/MIME format, ECDH, K-283, cofactor DH",
[ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
"-stream", "-out", "{output}.cms",
"-recip", catfile($smdir, "smec2.pem"), "-aes128",
"-keyopt", "ecdh_kdf_md:sha256", "-keyopt", "ecdh_cofactor_mode:1" ],
[ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smec2.pem"),
"-in", "{output}.cms", "-out", "{output}.txt" ],
\&final_compare
- ],
-
- [ "enveloped content test streaming S/MIME format, X9.42 DH",
- [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
- "-stream", "-out", "{output}.cms",
- "-recip", catfile($smdir, "smdh.pem"), "-aes128" ],
- [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smdh.pem"),
- "-in", "{output}.cms", "-out", "{output}.txt" ],
- \&final_compare
]
);
+if ($no_fips || $old_fips) {
+ # Only SHA1 supported in dh_cms_encrypt()
+ push(@smime_cms_param_tests,
+ [ "enveloped content test streaming S/MIME format, X9.42 DH",
+ [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
+ "-stream", "-out", "{output}.cms",
+ "-recip", catfile($smdir, "smdh.pem"), "-aes128" ],
+ [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smdh.pem"),
+ "-in", "{output}.cms", "-out", "{output}.txt" ],
+ \&final_compare
+ ]
+ );
+}
+
my @contenttype_cms_test = (
[ "signed content test - check that content type is added to additional signerinfo, RSA keys",
[ "{cmd1}", @prov, "-sign", "-binary", "-nodetach", "-stream", "-in", $smcont,
"-outform", "DER", "-signer", $smrsa1, "-md", "SHA256",
"-out", "{output}.cms" ],
[ "{cmd1}", @prov, "-resign", "-binary", "-nodetach", "-in", "{output}.cms",
"-inform", "DER", "-outform", "DER",
"-signer", catfile($smdir, "smrsa2.pem"), "-md", "SHA256",
"-out", "{output}2.cms" ],
sub { my %opts = @_; contentType_matches("$opts{output}2.cms") == 2; },
[ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
"-CAfile", $smroot, "-out", "{output}.txt" ]
],
);
my @incorrect_attribute_cms_test = (
"bad_signtime_attr.cms",
"no_ct_attr.cms",
"no_md_attr.cms",
"ct_multiple_attr.cms"
);
# Runs a standard loop on the input array
sub runner_loop {
my %opts = ( @_ );
my $cnt1 = 0;
foreach (@{$opts{tests}}) {
$cnt1++;
$opts{output} = "$opts{prefix}-$cnt1";
SKIP: {
my $skip_reason = check_availability($$_[0]);
skip $skip_reason, 1 if $skip_reason;
my $ok = 1;
1 while unlink "$opts{output}.txt";
foreach (@$_[1..$#$_]) {
if (ref $_ eq 'CODE') {
$ok &&= $_->(%opts);
} else {
my @cmd = map {
my $x = $_;
while ($x =~ /\{([^\}]+)\}/) {
$x = $`.$opts{$1}.$' if exists $opts{$1};
}
$x;
} @$_;
diag "CMD: openssl ", join(" ", @cmd);
$ok &&= run(app(["openssl", @cmd]));
$opts{input} = $opts{output};
}
}
ok($ok, $$_[0]);
}
}
}
sub final_compare {
my %opts = @_;
diag "Comparing $smcont with $opts{output}.txt";
return compare_text($smcont, "$opts{output}.txt") == 0;
}
sub zero_compare {
my %opts = @_;
diag "Checking for zero-length file";
return (-e "$opts{output}.txt" && -z "$opts{output}.txt");
}
subtest "CMS => PKCS#7 compatibility tests\n" => sub {
plan tests => scalar @smime_pkcs7_tests;
runner_loop(prefix => 'cms2pkcs7', cmd1 => 'cms', cmd2 => 'smime',
tests => [ @smime_pkcs7_tests ]);
};
subtest "CMS <= PKCS#7 compatibility tests\n" => sub {
plan tests => scalar @smime_pkcs7_tests;
runner_loop(prefix => 'pkcs72cms', cmd1 => 'smime', cmd2 => 'cms',
tests => [ @smime_pkcs7_tests ]);
};
subtest "CMS <=> CMS consistency tests\n" => sub {
plan tests => (scalar @smime_pkcs7_tests) + (scalar @smime_cms_tests);
runner_loop(prefix => 'cms2cms-1', cmd1 => 'cms', cmd2 => 'cms',
tests => [ @smime_pkcs7_tests ]);
runner_loop(prefix => 'cms2cms-2', cmd1 => 'cms', cmd2 => 'cms',
tests => [ @smime_cms_tests ]);
};
subtest "CMS <=> CMS consistency tests, modified key parameters\n" => sub {
plan tests =>
(scalar @smime_cms_param_tests) + (scalar @smime_cms_comp_tests);
runner_loop(prefix => 'cms2cms-mod', cmd1 => 'cms', cmd2 => 'cms',
tests => [ @smime_cms_param_tests ]);
SKIP: {
skip("Zlib not supported: compression tests skipped",
scalar @smime_cms_comp_tests)
if $no_zlib;
runner_loop(prefix => 'cms2cms-comp', cmd1 => 'cms', cmd2 => 'cms',
tests => [ @smime_cms_comp_tests ]);
}
};
# Returns the number of matches of a Content Type Attribute in a binary file.
sub contentType_matches {
# Read in a binary file
my ($in) = @_;
open (HEX_IN, "$in") or die("open failed for $in : $!");
binmode(HEX_IN);
local $/;
my $str = <HEX_IN>;
# Find ASN1 data for a Content Type Attribute (with a OID of PKCS7 data)
my @c = $str =~ /\x30\x18\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x03\x31\x0B\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x07\x01/gs;
close(HEX_IN);
return scalar(@c);
}
+# Returns 1 if the smime-type matches the passed parameter, otherwise 0.
+sub smimeType_matches {
+ my ($in, $expected_smime_type) = @_;
+
+ # Read the text file
+ open(my $fh, '<', $in) or die("open failed for $in : $!");
+ local $/;
+ my $content = <$fh>;
+ close($fh);
+
+ # Extract the Content-Type line with the smime-type attribute
+ if ($content =~ /Content-Type:\s*application\/pkcs7-mime.*smime-type=([^\s;]+)/) {
+ my $smime_type = $1;
+
+ # Compare the extracted smime-type with the expected value
+ return ($smime_type eq $expected_smime_type) ? 1 : 0;
+ }
+
+ # If no smime-type is found, return 0
+ return 0;
+}
+
sub rsapssSaltlen {
my ($in) = @_;
my $exit = 0;
my @asn1parse = run(app(["openssl", "asn1parse", "-in", $in, "-dump"]),
capture => 1,
statusvar => $exit);
return -1 if $exit != 0;
my $pssparam_offset = -1;
while ($_ = shift @asn1parse) {
chomp;
next unless /:rsassaPss/;
# This line contains :rsassaPss, the next line contains a raw dump of the
# RSA_PSS_PARAMS sequence; obtain its offset
$_ = shift @asn1parse;
if (/^\s*(\d+):/) {
$pssparam_offset = int($1);
}
}
if ($pssparam_offset == -1) {
note "Failed to determine RSA_PSS_PARAM offset in CMS. " +
"Was the file correctly signed with RSASSA-PSS?";
return -1;
}
my @pssparam = run(app(["openssl", "asn1parse", "-in", $in,
"-strparse", $pssparam_offset]),
capture => 1,
statusvar => $exit);
return -1 if $exit != 0;
my $saltlen = -1;
# Can't use asn1parse -item RSA_PSS_PARAMS here, because that's deprecated.
# This assumes the salt length is the last field, which may possibly be
# incorrect if there is a non-standard trailer field, but there almost never
# is in PSS.
if ($pssparam[-1] =~ /prim:\s+INTEGER\s+:([A-Fa-f0-9]+)/) {
$saltlen = hex($1);
}
if ($saltlen == -1) {
note "Failed to determine salt length from RSA_PSS_PARAM struct. " +
"Was the file correctly signed with RSASSA-PSS?";
return -1;
}
return $saltlen;
}
subtest "CMS Check the content type attribute is added for additional signers\n" => sub {
plan tests => (scalar @contenttype_cms_test);
runner_loop(prefix => 'cms2cms-added', cmd1 => 'cms', cmd2 => 'cms',
tests => [ @contenttype_cms_test ]);
};
subtest "CMS Check that bad attributes fail when verifying signers\n" => sub {
plan tests =>
(scalar @incorrect_attribute_cms_test);
my $cnt = 0;
foreach my $name (@incorrect_attribute_cms_test) {
my $out = "incorrect-$cnt.txt";
ok(!run(app(["openssl", "cms", @prov, "-verify", "-in",
catfile($datadir, $name), "-inform", "DER", "-CAfile",
$smroot, "-out", $out ])),
$name);
}
};
subtest "CMS Check that bad encryption algorithm fails\n" => sub {
plan tests => 1;
SKIP: {
skip "DES or Legacy isn't supported in this build", 1
if disabled("des") || disabled("legacy");
my $out = "smtst.txt";
ok(!run(app(["openssl", "cms", @legacyprov, "-encrypt",
"-in", $smcont,
"-stream", "-recip", $smrsa1,
"-des-ede3",
"-out", $out ])),
"Decrypt message from OpenSSL 1.1.1");
}
};
subtest "CMS Decrypt message encrypted with OpenSSL 1.1.1\n" => sub {
plan tests => 1;
SKIP: {
skip "EC or DES isn't supported in this build", 1
if disabled("ec") || disabled("des");
my $out = "smtst.txt";
ok(run(app(["openssl", "cms", @defaultprov, "-decrypt",
"-inkey", catfile($smdir, "smec3.pem"),
"-in", catfile($datadir, "ciphertext_from_1_1_1.cms"),
"-out", $out ]))
&& compare_text($smcont, $out) == 0,
"Decrypt message from OpenSSL 1.1.1");
}
};
subtest "CAdES <=> CAdES consistency tests\n" => sub {
plan tests => (scalar @smime_cms_cades_tests);
runner_loop(prefix => 'cms-cades', cmd1 => 'cms', cmd2 => 'cms',
tests => [ @smime_cms_cades_tests ]);
};
subtest "CAdES; cms incompatible arguments tests\n" => sub {
plan tests => (scalar @smime_cms_cades_invalid_option_tests);
foreach (@smime_cms_cades_invalid_option_tests) {
ok(!run(app(["openssl", "cms", @{$$_[0]} ] )));
}
};
subtest "CAdES ko tests\n" => sub {
plan tests => 2 * scalar @smime_cms_cades_ko_tests;
foreach (@smime_cms_cades_ko_tests) {
SKIP: {
my $skip_reason = check_availability($$_[0]);
skip $skip_reason, 1 if $skip_reason;
ok(run(app(["openssl", "cms", @{$$_[1]}])), $$_[0]);
ok(!run(app(["openssl", "cms", @{$$_[3]}])), $$_[2]);
}
}
};
subtest "CMS binary input tests\n" => sub {
my $input = srctop_file("test", "smcont.bin");
my $signed = "smcont.signed";
my $verified = "smcont.verified";
plan tests => 11;
ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
"-binary", "-in", $input, "-out", $signed])),
"sign binary input with -binary");
ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
"-binary", "-in", $signed, "-out", $verified])),
"verify binary input with -binary");
is(compare($input, $verified), 0, "binary input retained with -binary");
ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
"-in", $input, "-out", $signed.".nobin"])),
"sign binary input without -binary");
ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
"-in", $signed.".nobin", "-out", $verified.".nobin"])),
"verify binary input without -binary");
is(compare($input, $verified.".nobin"), 1, "binary input not retained without -binary");
ok(!run(app(["openssl", "cms", "-verify", "-CAfile", $smroot, "-crlfeol",
"-binary", "-in", $signed, "-out", $verified.".crlfeol"])),
"verify binary input wrong crlfeol");
ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
"-crlfeol",
"-binary", "-in", $input, "-out", $signed.".crlf"])),
"sign binary input with -binary -crlfeol");
ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot, "-crlfeol",
"-binary", "-in", $signed.".crlf", "-out", $verified.".crlf"])),
"verify binary input with -binary -crlfeol");
is(compare($input, $verified.".crlf"), 0,
"binary input retained with -binary -crlfeol");
ok(!run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
"-binary", "-in", $signed.".crlf", "-out", $verified.".crlf2"])),
"verify binary input with -binary missing -crlfeol");
};
# Test case for missing MD algorithm (must not segfault)
with({ exit_checker => sub { return shift == 4; } },
sub {
ok(run(app(['openssl', 'smime', '-verify', '-noverify',
'-inform', 'PEM',
'-in', data_file("pkcs7-md4.pem"),
])),
"Check failure of EVP_DigestInit is handled correctly");
});
sub check_availability {
my $tnam = shift;
return "$tnam: skipped, EC disabled\n"
if ($no_ec && $tnam =~ /ECDH/);
return "$tnam: skipped, ECDH disabled\n"
if ($no_ec && $tnam =~ /ECDH/);
return "$tnam: skipped, EC2M disabled\n"
if ($no_ec2m && $tnam =~ /K-283/);
return "$tnam: skipped, DH disabled\n"
if ($no_dh && $tnam =~ /X9\.42/);
return "$tnam: skipped, RC2 disabled\n"
if ($no_rc2 && $tnam =~ /RC2/);
return "$tnam: skipped, DES disabled\n"
if ($no_des && $tnam =~ /DES/);
return "$tnam: skipped, DSA disabled\n"
if ($no_dsa && $tnam =~ / DSA/);
return "";
}
# Test case for the locking problem reported in #19643.
# This will fail if the fix is in and deadlock on Windows (and possibly
# other platforms) if not.
ok(!run(app(['openssl', 'cms', '-verify',
'-CAfile', srctop_file("test/certs", "pkitsta.pem"),
'-policy', 'anyPolicy',
'-in', srctop_file("test/smime-eml",
"SignedInvalidMappingFromanyPolicyTest7.eml")
])),
"issue#19643");
+# Check that kari encryption with originator does not segfault
+with({ exit_checker => sub { return shift == 3; } },
+ sub {
+ SKIP: {
+ skip "EC is not supported in this build", 1 if $no_ec;
+
+ ok(run(app(['openssl', 'cms', '-encrypt',
+ '-in', srctop_file("test", "smcont.txt"), '-aes128',
+ '-recip', catfile($smdir, "smec1.pem"),
+ '-originator', catfile($smdir, "smec3.pem"),
+ '-inkey', catfile($smdir, "smec3.pem")
+ ])),
+ "Check failure for currently not supported kari encryption with static originator");
+ }
+ });
+
# Check that we get the expected failure return code
with({ exit_checker => sub { return shift == 6; } },
sub {
ok(run(app(['openssl', 'cms', '-encrypt',
'-in', srctop_file("test", "smcont.txt"),
'-aes128', '-stream', '-recip',
srctop_file("test/smime-certs", "badrsa.pem"),
])),
"Check failure during BIO setup with -stream is handled correctly");
});
# Test case for return value mis-check reported in #21986
with({ exit_checker => sub { return shift == 3; } },
sub {
SKIP: {
skip "DSA is not supported in this build", 1 if $no_dsa;
ok(run(app(['openssl', 'cms', '-sign',
'-in', srctop_file("test", "smcont.txt"),
'-signer', srctop_file("test/smime-certs", "smdsa1.pem"),
'-md', 'SHAKE256'])),
"issue#21986");
}
});
# Test for problem reported in #22225
with({ exit_checker => sub { return shift == 3; } },
sub {
ok(run(app(['openssl', 'cms', '-encrypt',
'-in', srctop_file("test", "smcont.txt"),
'-aes-256-ctr', '-recip',
catfile($smdir, "smec1.pem"),
])),
"Check for failure when cipher does not have an assigned OID (issue#22225)");
});
# Test encrypt to three recipients, and decrypt using key-only;
# i.e. do not follow the recommended practice of providing the
# recipient cert in the decrypt op.
#
# Use RSAES-OAEP for key-transport, not RSAES-PKCS-v1_5.
#
# Because the cert is not provided during decrypt, all RSA ciphertexts
# are decrypted in turn, and when/if there is a valid decryption, it
# is assumed the correct content-key has been recovered.
#
# That process may fail with RSAES-PKCS-v1_5 b/c there is a
# non-negligible chance that decrypting a random input using
# RSAES-PKCS-v1_5 can result in a valid plaintext (so two content-keys
# could be recovered and the wrong one might be used).
#
# See https://github.com/openssl/project/issues/380
subtest "encrypt to three recipients with RSA-OAEP, key only decrypt" => sub {
plan tests => 3;
my $pt = srctop_file("test", "smcont.txt");
my $ct = "smtst.cms";
my $ptpt = "smtst.txt";
ok(run(app(['openssl', 'cms',
@defaultprov,
'-encrypt', '-aes128',
'-in', $pt,
'-out', $ct,
'-stream',
'-recip', catfile($smdir, "smrsa1.pem"),
'-keyopt', 'rsa_padding_mode:oaep',
'-recip', catfile($smdir, "smrsa2.pem"),
'-keyopt', 'rsa_padding_mode:oaep',
'-recip', catfile($smdir, "smrsa3-cert.pem"),
'-keyopt', 'rsa_padding_mode:oaep',
])),
"encrypt to three recipients with RSA-OAEP (avoid openssl/project issue#380)");
ok(run(app(['openssl', 'cms',
@defaultprov,
'-decrypt', '-aes128',
'-in', $ct,
'-out', $ptpt,
'-inkey', catfile($smdir, "smrsa3-key.pem"),
])),
"decrypt with key only");
is(compare($pt, $ptpt), 0, "compare original message with decrypted ciphertext");
};
diff --git a/crypto/openssl/test/sslapitest.c b/crypto/openssl/test/sslapitest.c
index 97cf0f3ef092..368b15f22b72 100644
--- a/crypto/openssl/test/sslapitest.c
+++ b/crypto/openssl/test/sslapitest.c
@@ -1,11441 +1,11442 @@
/*
- * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/*
* We need access to the deprecated low level HMAC APIs for legacy purposes
* when the deprecated calls are not hidden
*/
#ifndef OPENSSL_NO_DEPRECATED_3_0
# define OPENSSL_SUPPRESS_DEPRECATED
#endif
#include <stdio.h>
#include <string.h>
#include <openssl/opensslconf.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/ocsp.h>
#include <openssl/srp.h>
#include <openssl/txt_db.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/core_names.h>
#include <openssl/core_dispatch.h>
#include <openssl/provider.h>
#include <openssl/param_build.h>
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include "helpers/ssltestlib.h"
#include "testutil.h"
#include "testutil/output.h"
#include "internal/nelem.h"
#include "internal/ktls.h"
#include "../ssl/ssl_local.h"
#include "filterprov.h"
#undef OSSL_NO_USABLE_TLS1_3
#if defined(OPENSSL_NO_TLS1_3) \
|| (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH))
/*
* If we don't have ec or dh then there are no built-in groups that are usable
* with TLSv1.3
*/
# define OSSL_NO_USABLE_TLS1_3
#endif
/* Defined in tls-provider.c */
int tls_provider_init(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *in,
const OSSL_DISPATCH **out,
void **provctx);
static OSSL_LIB_CTX *libctx = NULL;
static OSSL_PROVIDER *defctxnull = NULL;
#ifndef OSSL_NO_USABLE_TLS1_3
static SSL_SESSION *clientpsk = NULL;
static SSL_SESSION *serverpsk = NULL;
static const char *pskid = "Identity";
static const char *srvid;
static int use_session_cb(SSL *ssl, const EVP_MD *md, const unsigned char **id,
size_t *idlen, SSL_SESSION **sess);
static int find_session_cb(SSL *ssl, const unsigned char *identity,
size_t identity_len, SSL_SESSION **sess);
static int use_session_cb_cnt = 0;
static int find_session_cb_cnt = 0;
static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize);
#endif
static char *certsdir = NULL;
static char *cert = NULL;
static char *privkey = NULL;
static char *cert2 = NULL;
static char *privkey2 = NULL;
static char *cert1024 = NULL;
static char *privkey1024 = NULL;
static char *cert3072 = NULL;
static char *privkey3072 = NULL;
static char *cert4096 = NULL;
static char *privkey4096 = NULL;
static char *cert8192 = NULL;
static char *privkey8192 = NULL;
static char *srpvfile = NULL;
static char *tmpfilename = NULL;
static char *dhfile = NULL;
static int is_fips = 0;
#define LOG_BUFFER_SIZE 2048
static char server_log_buffer[LOG_BUFFER_SIZE + 1] = {0};
static size_t server_log_buffer_index = 0;
static char client_log_buffer[LOG_BUFFER_SIZE + 1] = {0};
static size_t client_log_buffer_index = 0;
static int error_writing_log = 0;
#ifndef OPENSSL_NO_OCSP
static const unsigned char orespder[] = "Dummy OCSP Response";
static int ocsp_server_called = 0;
static int ocsp_client_called = 0;
static int cdummyarg = 1;
static X509 *ocspcert = NULL;
#endif
#define NUM_EXTRA_CERTS 40
#define CLIENT_VERSION_LEN 2
/*
* This structure is used to validate that the correct number of log messages
* of various types are emitted when emitting secret logs.
*/
struct sslapitest_log_counts {
unsigned int rsa_key_exchange_count;
unsigned int master_secret_count;
unsigned int client_early_secret_count;
unsigned int client_handshake_secret_count;
unsigned int server_handshake_secret_count;
unsigned int client_application_secret_count;
unsigned int server_application_secret_count;
unsigned int early_exporter_secret_count;
unsigned int exporter_secret_count;
};
static int hostname_cb(SSL *s, int *al, void *arg)
{
const char *hostname = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
if (hostname != NULL && (strcmp(hostname, "goodhost") == 0
|| strcmp(hostname, "altgoodhost") == 0))
return SSL_TLSEXT_ERR_OK;
return SSL_TLSEXT_ERR_NOACK;
}
static void client_keylog_callback(const SSL *ssl, const char *line)
{
int line_length = strlen(line);
/* If the log doesn't fit, error out. */
if (client_log_buffer_index + line_length > sizeof(client_log_buffer) - 1) {
TEST_info("Client log too full");
error_writing_log = 1;
return;
}
strcat(client_log_buffer, line);
client_log_buffer_index += line_length;
client_log_buffer[client_log_buffer_index++] = '\n';
}
static void server_keylog_callback(const SSL *ssl, const char *line)
{
int line_length = strlen(line);
/* If the log doesn't fit, error out. */
if (server_log_buffer_index + line_length > sizeof(server_log_buffer) - 1) {
TEST_info("Server log too full");
error_writing_log = 1;
return;
}
strcat(server_log_buffer, line);
server_log_buffer_index += line_length;
server_log_buffer[server_log_buffer_index++] = '\n';
}
static int compare_hex_encoded_buffer(const char *hex_encoded,
size_t hex_length,
const uint8_t *raw,
size_t raw_length)
{
size_t i, j;
char hexed[3];
if (!TEST_size_t_eq(raw_length * 2, hex_length))
return 1;
for (i = j = 0; i < raw_length && j + 1 < hex_length; i++, j += 2) {
- sprintf(hexed, "%02x", raw[i]);
+ BIO_snprintf(hexed, sizeof(hexed), "%02x", raw[i]);
if (!TEST_int_eq(hexed[0], hex_encoded[j])
|| !TEST_int_eq(hexed[1], hex_encoded[j + 1]))
return 1;
}
return 0;
}
static int test_keylog_output(char *buffer, const SSL *ssl,
const SSL_SESSION *session,
struct sslapitest_log_counts *expected)
{
char *token = NULL;
unsigned char actual_client_random[SSL3_RANDOM_SIZE] = {0};
size_t client_random_size = SSL3_RANDOM_SIZE;
unsigned char actual_master_key[SSL_MAX_MASTER_KEY_LENGTH] = {0};
size_t master_key_size = SSL_MAX_MASTER_KEY_LENGTH;
unsigned int rsa_key_exchange_count = 0;
unsigned int master_secret_count = 0;
unsigned int client_early_secret_count = 0;
unsigned int client_handshake_secret_count = 0;
unsigned int server_handshake_secret_count = 0;
unsigned int client_application_secret_count = 0;
unsigned int server_application_secret_count = 0;
unsigned int early_exporter_secret_count = 0;
unsigned int exporter_secret_count = 0;
for (token = strtok(buffer, " \n"); token != NULL;
token = strtok(NULL, " \n")) {
if (strcmp(token, "RSA") == 0) {
/*
* Premaster secret. Tokens should be: 16 ASCII bytes of
* hex-encoded encrypted secret, then the hex-encoded pre-master
* secret.
*/
if (!TEST_ptr(token = strtok(NULL, " \n")))
return 0;
if (!TEST_size_t_eq(strlen(token), 16))
return 0;
if (!TEST_ptr(token = strtok(NULL, " \n")))
return 0;
/*
* We can't sensibly check the log because the premaster secret is
* transient, and OpenSSL doesn't keep hold of it once the master
* secret is generated.
*/
rsa_key_exchange_count++;
} else if (strcmp(token, "CLIENT_RANDOM") == 0) {
/*
* Master secret. Tokens should be: 64 ASCII bytes of hex-encoded
* client random, then the hex-encoded master secret.
*/
client_random_size = SSL_get_client_random(ssl,
actual_client_random,
SSL3_RANDOM_SIZE);
if (!TEST_size_t_eq(client_random_size, SSL3_RANDOM_SIZE))
return 0;
if (!TEST_ptr(token = strtok(NULL, " \n")))
return 0;
if (!TEST_size_t_eq(strlen(token), 64))
return 0;
if (!TEST_false(compare_hex_encoded_buffer(token, 64,
actual_client_random,
client_random_size)))
return 0;
if (!TEST_ptr(token = strtok(NULL, " \n")))
return 0;
master_key_size = SSL_SESSION_get_master_key(session,
actual_master_key,
master_key_size);
if (!TEST_size_t_ne(master_key_size, 0))
return 0;
if (!TEST_false(compare_hex_encoded_buffer(token, strlen(token),
actual_master_key,
master_key_size)))
return 0;
master_secret_count++;
} else if (strcmp(token, "CLIENT_EARLY_TRAFFIC_SECRET") == 0
|| strcmp(token, "CLIENT_HANDSHAKE_TRAFFIC_SECRET") == 0
|| strcmp(token, "SERVER_HANDSHAKE_TRAFFIC_SECRET") == 0
|| strcmp(token, "CLIENT_TRAFFIC_SECRET_0") == 0
|| strcmp(token, "SERVER_TRAFFIC_SECRET_0") == 0
|| strcmp(token, "EARLY_EXPORTER_SECRET") == 0
|| strcmp(token, "EXPORTER_SECRET") == 0) {
/*
* TLSv1.3 secret. Tokens should be: 64 ASCII bytes of hex-encoded
* client random, and then the hex-encoded secret. In this case,
* we treat all of these secrets identically and then just
* distinguish between them when counting what we saw.
*/
if (strcmp(token, "CLIENT_EARLY_TRAFFIC_SECRET") == 0)
client_early_secret_count++;
else if (strcmp(token, "CLIENT_HANDSHAKE_TRAFFIC_SECRET") == 0)
client_handshake_secret_count++;
else if (strcmp(token, "SERVER_HANDSHAKE_TRAFFIC_SECRET") == 0)
server_handshake_secret_count++;
else if (strcmp(token, "CLIENT_TRAFFIC_SECRET_0") == 0)
client_application_secret_count++;
else if (strcmp(token, "SERVER_TRAFFIC_SECRET_0") == 0)
server_application_secret_count++;
else if (strcmp(token, "EARLY_EXPORTER_SECRET") == 0)
early_exporter_secret_count++;
else if (strcmp(token, "EXPORTER_SECRET") == 0)
exporter_secret_count++;
client_random_size = SSL_get_client_random(ssl,
actual_client_random,
SSL3_RANDOM_SIZE);
if (!TEST_size_t_eq(client_random_size, SSL3_RANDOM_SIZE))
return 0;
if (!TEST_ptr(token = strtok(NULL, " \n")))
return 0;
if (!TEST_size_t_eq(strlen(token), 64))
return 0;
if (!TEST_false(compare_hex_encoded_buffer(token, 64,
actual_client_random,
client_random_size)))
return 0;
if (!TEST_ptr(token = strtok(NULL, " \n")))
return 0;
} else {
TEST_info("Unexpected token %s\n", token);
return 0;
}
}
/* Got what we expected? */
if (!TEST_size_t_eq(rsa_key_exchange_count,
expected->rsa_key_exchange_count)
|| !TEST_size_t_eq(master_secret_count,
expected->master_secret_count)
|| !TEST_size_t_eq(client_early_secret_count,
expected->client_early_secret_count)
|| !TEST_size_t_eq(client_handshake_secret_count,
expected->client_handshake_secret_count)
|| !TEST_size_t_eq(server_handshake_secret_count,
expected->server_handshake_secret_count)
|| !TEST_size_t_eq(client_application_secret_count,
expected->client_application_secret_count)
|| !TEST_size_t_eq(server_application_secret_count,
expected->server_application_secret_count)
|| !TEST_size_t_eq(early_exporter_secret_count,
expected->early_exporter_secret_count)
|| !TEST_size_t_eq(exporter_secret_count,
expected->exporter_secret_count))
return 0;
return 1;
}
#if !defined(OPENSSL_NO_TLS1_2) || defined(OSSL_NO_USABLE_TLS1_3)
static int test_keylog(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
struct sslapitest_log_counts expected;
/* Clean up logging space */
memset(&expected, 0, sizeof(expected));
memset(client_log_buffer, 0, sizeof(client_log_buffer));
memset(server_log_buffer, 0, sizeof(server_log_buffer));
client_log_buffer_index = 0;
server_log_buffer_index = 0;
error_writing_log = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
return 0;
/* We cannot log the master secret for TLSv1.3, so we should forbid it. */
SSL_CTX_set_options(cctx, SSL_OP_NO_TLSv1_3);
SSL_CTX_set_options(sctx, SSL_OP_NO_TLSv1_3);
/* We also want to ensure that we use RSA-based key exchange. */
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "RSA")))
goto end;
if (!TEST_true(SSL_CTX_get_keylog_callback(cctx) == NULL)
|| !TEST_true(SSL_CTX_get_keylog_callback(sctx) == NULL))
goto end;
SSL_CTX_set_keylog_callback(cctx, client_keylog_callback);
if (!TEST_true(SSL_CTX_get_keylog_callback(cctx)
== client_keylog_callback))
goto end;
SSL_CTX_set_keylog_callback(sctx, server_keylog_callback);
if (!TEST_true(SSL_CTX_get_keylog_callback(sctx)
== server_keylog_callback))
goto end;
/* Now do a handshake and check that the logs have been written to. */
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(error_writing_log)
|| !TEST_int_gt(client_log_buffer_index, 0)
|| !TEST_int_gt(server_log_buffer_index, 0))
goto end;
/*
* Now we want to test that our output data was vaguely sensible. We
* do that by using strtok and confirming that we have more or less the
* data we expect. For both client and server, we expect to see one master
* secret. The client should also see an RSA key exchange.
*/
expected.rsa_key_exchange_count = 1;
expected.master_secret_count = 1;
if (!TEST_true(test_keylog_output(client_log_buffer, clientssl,
SSL_get_session(clientssl), &expected)))
goto end;
expected.rsa_key_exchange_count = 0;
if (!TEST_true(test_keylog_output(server_log_buffer, serverssl,
SSL_get_session(serverssl), &expected)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
static int test_keylog_no_master_key(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
SSL_SESSION *sess = NULL;
int testresult = 0;
struct sslapitest_log_counts expected;
unsigned char buf[1];
size_t readbytes, written;
/* Clean up logging space */
memset(&expected, 0, sizeof(expected));
memset(client_log_buffer, 0, sizeof(client_log_buffer));
memset(server_log_buffer, 0, sizeof(server_log_buffer));
client_log_buffer_index = 0;
server_log_buffer_index = 0;
error_writing_log = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey))
|| !TEST_true(SSL_CTX_set_max_early_data(sctx,
SSL3_RT_MAX_PLAIN_LENGTH)))
return 0;
if (!TEST_true(SSL_CTX_get_keylog_callback(cctx) == NULL)
|| !TEST_true(SSL_CTX_get_keylog_callback(sctx) == NULL))
goto end;
SSL_CTX_set_keylog_callback(cctx, client_keylog_callback);
if (!TEST_true(SSL_CTX_get_keylog_callback(cctx)
== client_keylog_callback))
goto end;
SSL_CTX_set_keylog_callback(sctx, server_keylog_callback);
if (!TEST_true(SSL_CTX_get_keylog_callback(sctx)
== server_keylog_callback))
goto end;
/* Now do a handshake and check that the logs have been written to. */
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(error_writing_log))
goto end;
/*
* Now we want to test that our output data was vaguely sensible. For this
* test, we expect no CLIENT_RANDOM entry because it doesn't make sense for
* TLSv1.3, but we do expect both client and server to emit keys.
*/
expected.client_handshake_secret_count = 1;
expected.server_handshake_secret_count = 1;
expected.client_application_secret_count = 1;
expected.server_application_secret_count = 1;
expected.exporter_secret_count = 1;
if (!TEST_true(test_keylog_output(client_log_buffer, clientssl,
SSL_get_session(clientssl), &expected))
|| !TEST_true(test_keylog_output(server_log_buffer, serverssl,
SSL_get_session(serverssl),
&expected)))
goto end;
/* Terminate old session and resume with early data. */
sess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* Reset key log */
memset(client_log_buffer, 0, sizeof(client_log_buffer));
memset(server_log_buffer, 0, sizeof(server_log_buffer));
client_log_buffer_index = 0;
server_log_buffer_index = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, sess))
/* Here writing 0 length early data is enough. */
|| !TEST_true(SSL_write_early_data(clientssl, NULL, 0, &written))
|| !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_ERROR)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED)
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl)))
goto end;
/* In addition to the previous entries, expect early secrets. */
expected.client_early_secret_count = 1;
expected.early_exporter_secret_count = 1;
if (!TEST_true(test_keylog_output(client_log_buffer, clientssl,
SSL_get_session(clientssl), &expected))
|| !TEST_true(test_keylog_output(server_log_buffer, serverssl,
SSL_get_session(serverssl),
&expected)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif
static int verify_retry_cb(X509_STORE_CTX *ctx, void *arg)
{
int res = X509_verify_cert(ctx);
int idx = SSL_get_ex_data_X509_STORE_CTX_idx();
SSL *ssl;
/* this should not happen but check anyway */
if (idx < 0
|| (ssl = X509_STORE_CTX_get_ex_data(ctx, idx)) == NULL)
return 0;
if (res == 0 && X509_STORE_CTX_get_error(ctx) ==
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
/* indicate SSL_ERROR_WANT_RETRY_VERIFY */
return SSL_set_retry_verify(ssl);
return res;
}
static int test_client_cert_verify_cb(void)
{
/* server key, cert, chain, and root */
char *skey = test_mk_file_path(certsdir, "leaf.key");
char *leaf = test_mk_file_path(certsdir, "leaf.pem");
char *int2 = test_mk_file_path(certsdir, "subinterCA.pem");
char *int1 = test_mk_file_path(certsdir, "interCA.pem");
char *root = test_mk_file_path(certsdir, "rootCA.pem");
X509 *crt1 = NULL, *crt2 = NULL;
STACK_OF(X509) *server_chain;
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, NULL, NULL)))
goto end;
if (!TEST_int_eq(SSL_CTX_use_certificate_chain_file(sctx, leaf), 1)
|| !TEST_int_eq(SSL_CTX_use_PrivateKey_file(sctx, skey,
SSL_FILETYPE_PEM), 1)
|| !TEST_int_eq(SSL_CTX_check_private_key(sctx), 1))
goto end;
if (!TEST_true(SSL_CTX_load_verify_locations(cctx, root, NULL)))
goto end;
SSL_CTX_set_verify(cctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_cert_verify_callback(cctx, verify_retry_cb, NULL);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
/* attempt SSL_connect() with incomplete server chain */
if (!TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_RETRY_VERIFY)))
goto end;
/* application provides intermediate certs needed to verify server cert */
if (!TEST_ptr((crt1 = load_cert_pem(int1, libctx)))
|| !TEST_ptr((crt2 = load_cert_pem(int2, libctx)))
|| !TEST_ptr((server_chain = SSL_get_peer_cert_chain(clientssl))))
goto end;
/* add certs in reverse order to demonstrate real chain building */
if (!TEST_true(sk_X509_push(server_chain, crt1)))
goto end;
crt1 = NULL;
if (!TEST_true(sk_X509_push(server_chain, crt2)))
goto end;
crt2 = NULL;
/* continue SSL_connect(), must now succeed with completed server chain */
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
testresult = 1;
end:
X509_free(crt1);
X509_free(crt2);
if (clientssl != NULL) {
SSL_shutdown(clientssl);
SSL_free(clientssl);
}
if (serverssl != NULL) {
SSL_shutdown(serverssl);
SSL_free(serverssl);
}
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
OPENSSL_free(skey);
OPENSSL_free(leaf);
OPENSSL_free(int2);
OPENSSL_free(int1);
OPENSSL_free(root);
return testresult;
}
static int test_ssl_build_cert_chain(void)
{
int ret = 0;
SSL_CTX *ssl_ctx = NULL;
SSL *ssl = NULL;
char *skey = test_mk_file_path(certsdir, "leaf.key");
char *leaf_chain = test_mk_file_path(certsdir, "leaf-chain.pem");
if (!TEST_ptr(ssl_ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method())))
goto end;
if (!TEST_ptr(ssl = SSL_new(ssl_ctx)))
goto end;
/* leaf_chain contains leaf + subinterCA + interCA + rootCA */
if (!TEST_int_eq(SSL_use_certificate_chain_file(ssl, leaf_chain), 1)
|| !TEST_int_eq(SSL_use_PrivateKey_file(ssl, skey, SSL_FILETYPE_PEM), 1)
|| !TEST_int_eq(SSL_check_private_key(ssl), 1))
goto end;
if (!TEST_true(SSL_build_cert_chain(ssl, SSL_BUILD_CHAIN_FLAG_NO_ROOT
| SSL_BUILD_CHAIN_FLAG_CHECK)))
goto end;
ret = 1;
end:
SSL_free(ssl);
SSL_CTX_free(ssl_ctx);
OPENSSL_free(leaf_chain);
OPENSSL_free(skey);
return ret;
}
static int get_password_cb(char *buf, int size, int rw_flag, void *userdata)
{
static const char pass[] = "testpass";
if (!TEST_int_eq(size, PEM_BUFSIZE))
return -1;
memcpy(buf, pass, sizeof(pass) - 1);
return sizeof(pass) - 1;
}
static int test_ssl_ctx_build_cert_chain(void)
{
int ret = 0;
SSL_CTX *ctx = NULL;
char *skey = test_mk_file_path(certsdir, "leaf-encrypted.key");
char *leaf_chain = test_mk_file_path(certsdir, "leaf-chain.pem");
if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method())))
goto end;
SSL_CTX_set_default_passwd_cb(ctx, get_password_cb);
/* leaf_chain contains leaf + subinterCA + interCA + rootCA */
if (!TEST_int_eq(SSL_CTX_use_certificate_chain_file(ctx, leaf_chain), 1)
|| !TEST_int_eq(SSL_CTX_use_PrivateKey_file(ctx, skey,
SSL_FILETYPE_PEM), 1)
|| !TEST_int_eq(SSL_CTX_check_private_key(ctx), 1))
goto end;
if (!TEST_true(SSL_CTX_build_cert_chain(ctx, SSL_BUILD_CHAIN_FLAG_NO_ROOT
| SSL_BUILD_CHAIN_FLAG_CHECK)))
goto end;
ret = 1;
end:
SSL_CTX_free(ctx);
OPENSSL_free(leaf_chain);
OPENSSL_free(skey);
return ret;
}
#ifndef OPENSSL_NO_TLS1_2
static int full_client_hello_callback(SSL *s, int *al, void *arg)
{
int *ctr = arg;
const unsigned char *p;
int *exts;
/* We only configure two ciphers, but the SCSV is added automatically. */
#ifdef OPENSSL_NO_EC
const unsigned char expected_ciphers[] = {0x00, 0x9d, 0x00, 0xff};
#else
const unsigned char expected_ciphers[] = {0x00, 0x9d, 0xc0,
0x2c, 0x00, 0xff};
#endif
const int expected_extensions[] = {
#ifndef OPENSSL_NO_EC
11, 10,
#endif
35, 22, 23, 13};
size_t len;
/* Make sure we can defer processing and get called back. */
if ((*ctr)++ == 0)
return SSL_CLIENT_HELLO_RETRY;
len = SSL_client_hello_get0_ciphers(s, &p);
if (!TEST_mem_eq(p, len, expected_ciphers, sizeof(expected_ciphers))
|| !TEST_size_t_eq(
SSL_client_hello_get0_compression_methods(s, &p), 1)
|| !TEST_int_eq(*p, 0))
return SSL_CLIENT_HELLO_ERROR;
if (!SSL_client_hello_get1_extensions_present(s, &exts, &len))
return SSL_CLIENT_HELLO_ERROR;
if (len != OSSL_NELEM(expected_extensions) ||
memcmp(exts, expected_extensions, len * sizeof(*exts)) != 0) {
printf("ClientHello callback expected extensions mismatch\n");
OPENSSL_free(exts);
return SSL_CLIENT_HELLO_ERROR;
}
OPENSSL_free(exts);
return SSL_CLIENT_HELLO_SUCCESS;
}
static int test_client_hello_cb(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testctr = 0, testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
SSL_CTX_set_client_hello_cb(sctx, full_client_hello_callback, &testctr);
/* The gimpy cipher list we configure can't do TLS 1.3. */
SSL_CTX_set_max_proto_version(cctx, TLS1_2_VERSION);
if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
"AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_CLIENT_HELLO_CB))
/*
* Passing a -1 literal is a hack since
* the real value was lost.
* */
|| !TEST_int_eq(SSL_get_error(serverssl, -1),
SSL_ERROR_WANT_CLIENT_HELLO_CB)
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static int test_no_ems(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
if (!create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(),
TLS1_VERSION, TLS1_2_VERSION,
&sctx, &cctx, cert, privkey)) {
printf("Unable to create SSL_CTX pair\n");
goto end;
}
SSL_CTX_set_options(sctx, SSL_OP_NO_EXTENDED_MASTER_SECRET);
if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
printf("Unable to create SSL objects\n");
goto end;
}
if (!create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) {
printf("Creating SSL connection failed\n");
goto end;
}
if (SSL_get_extms_support(serverssl)) {
printf("Server reports Extended Master Secret support\n");
goto end;
}
if (SSL_get_extms_support(clientssl)) {
printf("Client reports Extended Master Secret support\n");
goto end;
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Very focused test to exercise a single case in the server-side state
* machine, when the ChangeCipherState message needs to actually change
* from one cipher to a different cipher (i.e., not changing from null
* encryption to real encryption).
*/
static int test_ccs_change_cipher(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
SSL_SESSION *sess = NULL, *sesspre, *sesspost;
int testresult = 0;
int i;
unsigned char buf;
size_t readbytes;
/*
* Create a conection so we can resume and potentially (but not) use
* a different cipher in the second connection.
*/
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION, TLS1_2_VERSION,
&sctx, &cctx, cert, privkey))
|| !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_cipher_list(clientssl, "AES128-GCM-SHA256"))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_ptr(sesspre = SSL_get0_session(serverssl))
|| !TEST_ptr(sess = SSL_get1_session(clientssl)))
goto end;
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
/* Resume, preferring a different cipher. Our server will force the
* same cipher to be used as the initial handshake. */
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, sess))
|| !TEST_true(SSL_set_cipher_list(clientssl, "AES256-GCM-SHA384:AES128-GCM-SHA256"))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl))
|| !TEST_true(SSL_session_reused(serverssl))
|| !TEST_ptr(sesspost = SSL_get0_session(serverssl))
|| !TEST_ptr_eq(sesspre, sesspost)
|| !TEST_int_eq(TLS1_CK_RSA_WITH_AES_128_GCM_SHA256,
SSL_CIPHER_get_id(SSL_get_current_cipher(clientssl))))
goto end;
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
/*
* Now create a fresh connection and try to renegotiate a different
* cipher on it.
*/
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_cipher_list(clientssl, "AES128-GCM-SHA256"))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_ptr(sesspre = SSL_get0_session(serverssl))
|| !TEST_true(SSL_set_cipher_list(clientssl, "AES256-GCM-SHA384"))
|| !TEST_true(SSL_renegotiate(clientssl))
|| !TEST_true(SSL_renegotiate_pending(clientssl)))
goto end;
/* Actually drive the renegotiation. */
for (i = 0; i < 3; i++) {
if (SSL_read_ex(clientssl, &buf, sizeof(buf), &readbytes) > 0) {
if (!TEST_ulong_eq(readbytes, 0))
goto end;
} else if (!TEST_int_eq(SSL_get_error(clientssl, 0),
SSL_ERROR_WANT_READ)) {
goto end;
}
if (SSL_read_ex(serverssl, &buf, sizeof(buf), &readbytes) > 0) {
if (!TEST_ulong_eq(readbytes, 0))
goto end;
} else if (!TEST_int_eq(SSL_get_error(serverssl, 0),
SSL_ERROR_WANT_READ)) {
goto end;
}
}
/* sesspre and sesspost should be different since the cipher changed. */
if (!TEST_false(SSL_renegotiate_pending(clientssl))
|| !TEST_false(SSL_session_reused(clientssl))
|| !TEST_false(SSL_session_reused(serverssl))
|| !TEST_ptr(sesspost = SSL_get0_session(serverssl))
|| !TEST_ptr_ne(sesspre, sesspost)
|| !TEST_int_eq(TLS1_CK_RSA_WITH_AES_256_GCM_SHA384,
SSL_CIPHER_get_id(SSL_get_current_cipher(clientssl))))
goto end;
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
SSL_SESSION_free(sess);
return testresult;
}
#endif
static int add_large_cert_chain(SSL_CTX *sctx)
{
BIO *certbio = NULL;
X509 *chaincert = NULL;
int certlen;
int ret = 0;
int i;
if (!TEST_ptr(certbio = BIO_new_file(cert, "r")))
goto end;
if (!TEST_ptr(chaincert = X509_new_ex(libctx, NULL)))
goto end;
if (PEM_read_bio_X509(certbio, &chaincert, NULL, NULL) == NULL)
goto end;
BIO_free(certbio);
certbio = NULL;
/*
* We assume the supplied certificate is big enough so that if we add
* NUM_EXTRA_CERTS it will make the overall message large enough. The
* default buffer size is requested to be 16k, but due to the way BUF_MEM
* works, it ends up allocating a little over 21k (16 * 4/3). So, in this
* test we need to have a message larger than that.
*/
certlen = i2d_X509(chaincert, NULL);
OPENSSL_assert(certlen * NUM_EXTRA_CERTS >
(SSL3_RT_MAX_PLAIN_LENGTH * 4) / 3);
for (i = 0; i < NUM_EXTRA_CERTS; i++) {
if (!X509_up_ref(chaincert))
goto end;
if (!SSL_CTX_add_extra_chain_cert(sctx, chaincert)) {
X509_free(chaincert);
goto end;
}
}
ret = 1;
end:
BIO_free(certbio);
X509_free(chaincert);
return ret;
}
static int execute_test_large_message(const SSL_METHOD *smeth,
const SSL_METHOD *cmeth,
int min_version, int max_version,
int read_ahead)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, smeth, cmeth, min_version,
max_version, &sctx, &cctx, cert,
privkey)))
goto end;
#ifdef OPENSSL_NO_DTLS1_2
if (smeth == DTLS_server_method()) {
/*
* Default sigalgs are SHA1 based in <DTLS1.2 which is in security
* level 0
*/
if (!TEST_true(SSL_CTX_set_cipher_list(sctx, "DEFAULT:@SECLEVEL=0"))
|| !TEST_true(SSL_CTX_set_cipher_list(cctx,
"DEFAULT:@SECLEVEL=0")))
goto end;
}
#endif
if (read_ahead) {
/*
* Test that read_ahead works correctly when dealing with large
* records
*/
SSL_CTX_set_read_ahead(cctx, 1);
}
if (!add_large_cert_chain(sctx))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
/*
* Calling SSL_clear() first is not required but this tests that SSL_clear()
* doesn't leak.
*/
if (!TEST_true(SSL_clear(serverssl)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_KTLS) && \
!(defined(OSSL_NO_USABLE_TLS1_3) && defined(OPENSSL_NO_TLS1_2))
/* sock must be connected */
static int ktls_chk_platform(int sock)
{
if (!ktls_enable(sock))
return 0;
return 1;
}
static int ping_pong_query(SSL *clientssl, SSL *serverssl)
{
static char count = 1;
unsigned char cbuf[16000] = {0};
unsigned char sbuf[16000];
size_t err = 0;
char crec_wseq_before[SEQ_NUM_SIZE];
char crec_wseq_after[SEQ_NUM_SIZE];
char crec_rseq_before[SEQ_NUM_SIZE];
char crec_rseq_after[SEQ_NUM_SIZE];
char srec_wseq_before[SEQ_NUM_SIZE];
char srec_wseq_after[SEQ_NUM_SIZE];
char srec_rseq_before[SEQ_NUM_SIZE];
char srec_rseq_after[SEQ_NUM_SIZE];
cbuf[0] = count++;
memcpy(crec_wseq_before, &clientssl->rlayer.write_sequence, SEQ_NUM_SIZE);
memcpy(crec_rseq_before, &clientssl->rlayer.read_sequence, SEQ_NUM_SIZE);
memcpy(srec_wseq_before, &serverssl->rlayer.write_sequence, SEQ_NUM_SIZE);
memcpy(srec_rseq_before, &serverssl->rlayer.read_sequence, SEQ_NUM_SIZE);
if (!TEST_true(SSL_write(clientssl, cbuf, sizeof(cbuf)) == sizeof(cbuf)))
goto end;
while ((err = SSL_read(serverssl, &sbuf, sizeof(sbuf))) != sizeof(sbuf)) {
if (SSL_get_error(serverssl, err) != SSL_ERROR_WANT_READ) {
goto end;
}
}
if (!TEST_true(SSL_write(serverssl, sbuf, sizeof(sbuf)) == sizeof(sbuf)))
goto end;
while ((err = SSL_read(clientssl, &cbuf, sizeof(cbuf))) != sizeof(cbuf)) {
if (SSL_get_error(clientssl, err) != SSL_ERROR_WANT_READ) {
goto end;
}
}
memcpy(crec_wseq_after, &clientssl->rlayer.write_sequence, SEQ_NUM_SIZE);
memcpy(crec_rseq_after, &clientssl->rlayer.read_sequence, SEQ_NUM_SIZE);
memcpy(srec_wseq_after, &serverssl->rlayer.write_sequence, SEQ_NUM_SIZE);
memcpy(srec_rseq_after, &serverssl->rlayer.read_sequence, SEQ_NUM_SIZE);
/* verify the payload */
if (!TEST_mem_eq(cbuf, sizeof(cbuf), sbuf, sizeof(sbuf)))
goto end;
/*
* If ktls is used then kernel sequences are used instead of
* OpenSSL sequences
*/
if (!BIO_get_ktls_send(clientssl->wbio)) {
if (!TEST_mem_ne(crec_wseq_before, SEQ_NUM_SIZE,
crec_wseq_after, SEQ_NUM_SIZE))
goto end;
} else {
if (!TEST_mem_eq(crec_wseq_before, SEQ_NUM_SIZE,
crec_wseq_after, SEQ_NUM_SIZE))
goto end;
}
if (!BIO_get_ktls_send(serverssl->wbio)) {
if (!TEST_mem_ne(srec_wseq_before, SEQ_NUM_SIZE,
srec_wseq_after, SEQ_NUM_SIZE))
goto end;
} else {
if (!TEST_mem_eq(srec_wseq_before, SEQ_NUM_SIZE,
srec_wseq_after, SEQ_NUM_SIZE))
goto end;
}
if (!BIO_get_ktls_recv(clientssl->wbio)) {
if (!TEST_mem_ne(crec_rseq_before, SEQ_NUM_SIZE,
crec_rseq_after, SEQ_NUM_SIZE))
goto end;
} else {
if (!TEST_mem_eq(crec_rseq_before, SEQ_NUM_SIZE,
crec_rseq_after, SEQ_NUM_SIZE))
goto end;
}
if (!BIO_get_ktls_recv(serverssl->wbio)) {
if (!TEST_mem_ne(srec_rseq_before, SEQ_NUM_SIZE,
srec_rseq_after, SEQ_NUM_SIZE))
goto end;
} else {
if (!TEST_mem_eq(srec_rseq_before, SEQ_NUM_SIZE,
srec_rseq_after, SEQ_NUM_SIZE))
goto end;
}
return 1;
end:
return 0;
}
static int execute_test_ktls(int cis_ktls, int sis_ktls,
int tls_version, const char *cipher)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int ktls_used = 0, testresult = 0;
int cfd = -1, sfd = -1;
int rx_supported;
if (!TEST_true(create_test_sockets(&cfd, &sfd)))
goto end;
/* Skip this test if the platform does not support ktls */
if (!ktls_chk_platform(cfd)) {
testresult = TEST_skip("Kernel does not support KTLS");
goto end;
}
if (is_fips && strstr(cipher, "CHACHA") != NULL) {
testresult = TEST_skip("CHACHA is not supported in FIPS");
goto end;
}
/* Create a session based on SHA-256 */
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
tls_version, tls_version,
&sctx, &cctx, cert, privkey)))
goto end;
if (tls_version == TLS1_3_VERSION) {
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx, cipher))
|| !TEST_true(SSL_CTX_set_ciphersuites(sctx, cipher)))
goto end;
} else {
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, cipher))
|| !TEST_true(SSL_CTX_set_cipher_list(sctx, cipher)))
goto end;
}
if (!TEST_true(create_ssl_objects2(sctx, cctx, &serverssl,
&clientssl, sfd, cfd)))
goto end;
if (cis_ktls) {
if (!TEST_true(SSL_set_options(clientssl, SSL_OP_ENABLE_KTLS)))
goto end;
}
if (sis_ktls) {
if (!TEST_true(SSL_set_options(serverssl, SSL_OP_ENABLE_KTLS)))
goto end;
}
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
/*
* The running kernel may not support a given cipher suite
* or direction, so just check that KTLS isn't used when it
* isn't enabled.
*/
if (!cis_ktls) {
if (!TEST_false(BIO_get_ktls_send(clientssl->wbio)))
goto end;
} else {
if (BIO_get_ktls_send(clientssl->wbio))
ktls_used = 1;
}
if (!sis_ktls) {
if (!TEST_false(BIO_get_ktls_send(serverssl->wbio)))
goto end;
} else {
if (BIO_get_ktls_send(serverssl->wbio))
ktls_used = 1;
}
#if defined(OPENSSL_NO_KTLS_RX)
rx_supported = 0;
#else
rx_supported = (tls_version != TLS1_3_VERSION);
#endif
if (!cis_ktls || !rx_supported) {
if (!TEST_false(BIO_get_ktls_recv(clientssl->rbio)))
goto end;
} else {
if (BIO_get_ktls_send(clientssl->rbio))
ktls_used = 1;
}
if (!sis_ktls || !rx_supported) {
if (!TEST_false(BIO_get_ktls_recv(serverssl->rbio)))
goto end;
} else {
if (BIO_get_ktls_send(serverssl->rbio))
ktls_used = 1;
}
if ((cis_ktls || sis_ktls) && !ktls_used) {
testresult = TEST_skip("KTLS not supported for %s cipher %s",
tls_version == TLS1_3_VERSION ? "TLS 1.3" :
"TLS 1.2", cipher);
goto end;
}
if (!TEST_true(ping_pong_query(clientssl, serverssl)))
goto end;
testresult = 1;
end:
if (clientssl) {
SSL_shutdown(clientssl);
SSL_free(clientssl);
}
if (serverssl) {
SSL_shutdown(serverssl);
SSL_free(serverssl);
}
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
serverssl = clientssl = NULL;
if (cfd != -1)
close(cfd);
if (sfd != -1)
close(sfd);
return testresult;
}
#define SENDFILE_SZ (16 * 4096)
#define SENDFILE_CHUNK (4 * 4096)
#define min(a,b) ((a) > (b) ? (b) : (a))
static int execute_test_ktls_sendfile(int tls_version, const char *cipher)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
unsigned char *buf, *buf_dst;
BIO *out = NULL, *in = NULL;
int cfd = -1, sfd = -1, ffd, err;
ssize_t chunk_size = 0;
off_t chunk_off = 0;
int testresult = 0;
FILE *ffdp;
buf = OPENSSL_zalloc(SENDFILE_SZ);
buf_dst = OPENSSL_zalloc(SENDFILE_SZ);
if (!TEST_ptr(buf) || !TEST_ptr(buf_dst)
|| !TEST_true(create_test_sockets(&cfd, &sfd)))
goto end;
/* Skip this test if the platform does not support ktls */
if (!ktls_chk_platform(sfd)) {
testresult = TEST_skip("Kernel does not support KTLS");
goto end;
}
if (is_fips && strstr(cipher, "CHACHA") != NULL) {
testresult = TEST_skip("CHACHA is not supported in FIPS");
goto end;
}
/* Create a session based on SHA-256 */
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
tls_version, tls_version,
&sctx, &cctx, cert, privkey)))
goto end;
if (tls_version == TLS1_3_VERSION) {
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx, cipher))
|| !TEST_true(SSL_CTX_set_ciphersuites(sctx, cipher)))
goto end;
} else {
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, cipher))
|| !TEST_true(SSL_CTX_set_cipher_list(sctx, cipher)))
goto end;
}
if (!TEST_true(create_ssl_objects2(sctx, cctx, &serverssl,
&clientssl, sfd, cfd)))
goto end;
if (!TEST_true(SSL_set_options(serverssl, SSL_OP_ENABLE_KTLS)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
if (!BIO_get_ktls_send(serverssl->wbio)) {
testresult = TEST_skip("Failed to enable KTLS for %s cipher %s",
tls_version == TLS1_3_VERSION ? "TLS 1.3" :
"TLS 1.2", cipher);
goto end;
}
if (!TEST_int_gt(RAND_bytes_ex(libctx, buf, SENDFILE_SZ, 0), 0))
goto end;
out = BIO_new_file(tmpfilename, "wb");
if (!TEST_ptr(out))
goto end;
if (BIO_write(out, buf, SENDFILE_SZ) != SENDFILE_SZ)
goto end;
BIO_free(out);
out = NULL;
in = BIO_new_file(tmpfilename, "rb");
BIO_get_fp(in, &ffdp);
ffd = fileno(ffdp);
while (chunk_off < SENDFILE_SZ) {
chunk_size = min(SENDFILE_CHUNK, SENDFILE_SZ - chunk_off);
while ((err = SSL_sendfile(serverssl,
ffd,
chunk_off,
chunk_size,
0)) != chunk_size) {
if (SSL_get_error(serverssl, err) != SSL_ERROR_WANT_WRITE)
goto end;
}
while ((err = SSL_read(clientssl,
buf_dst + chunk_off,
chunk_size)) != chunk_size) {
if (SSL_get_error(clientssl, err) != SSL_ERROR_WANT_READ)
goto end;
}
/* verify the payload */
if (!TEST_mem_eq(buf_dst + chunk_off,
chunk_size,
buf + chunk_off,
chunk_size))
goto end;
chunk_off += chunk_size;
}
testresult = 1;
end:
if (clientssl) {
SSL_shutdown(clientssl);
SSL_free(clientssl);
}
if (serverssl) {
SSL_shutdown(serverssl);
SSL_free(serverssl);
}
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
serverssl = clientssl = NULL;
BIO_free(out);
BIO_free(in);
if (cfd != -1)
close(cfd);
if (sfd != -1)
close(sfd);
OPENSSL_free(buf);
OPENSSL_free(buf_dst);
return testresult;
}
static struct ktls_test_cipher {
int tls_version;
const char *cipher;
} ktls_test_ciphers[] = {
# if !defined(OPENSSL_NO_TLS1_2)
# ifdef OPENSSL_KTLS_AES_GCM_128
{ TLS1_2_VERSION, "AES128-GCM-SHA256" },
# endif
# ifdef OPENSSL_KTLS_AES_CCM_128
{ TLS1_2_VERSION, "AES128-CCM"},
# endif
# ifdef OPENSSL_KTLS_AES_GCM_256
{ TLS1_2_VERSION, "AES256-GCM-SHA384"},
# endif
# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
# ifndef OPENSSL_NO_EC
{ TLS1_2_VERSION, "ECDHE-RSA-CHACHA20-POLY1305"},
# endif
# endif
# endif
# if !defined(OSSL_NO_USABLE_TLS1_3)
# ifdef OPENSSL_KTLS_AES_GCM_128
{ TLS1_3_VERSION, "TLS_AES_128_GCM_SHA256" },
# endif
# ifdef OPENSSL_KTLS_AES_CCM_128
{ TLS1_3_VERSION, "TLS_AES_128_CCM_SHA256" },
# endif
# ifdef OPENSSL_KTLS_AES_GCM_256
{ TLS1_3_VERSION, "TLS_AES_256_GCM_SHA384" },
# endif
# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
{ TLS1_3_VERSION, "TLS_CHACHA20_POLY1305_SHA256" },
# endif
# endif
};
#define NUM_KTLS_TEST_CIPHERS \
(sizeof(ktls_test_ciphers) / sizeof(ktls_test_ciphers[0]))
static int test_ktls(int test)
{
struct ktls_test_cipher *cipher;
int cis_ktls, sis_ktls;
OPENSSL_assert(test / 4 < (int)NUM_KTLS_TEST_CIPHERS);
cipher = &ktls_test_ciphers[test / 4];
cis_ktls = (test & 1) != 0;
sis_ktls = (test & 2) != 0;
return execute_test_ktls(cis_ktls, sis_ktls, cipher->tls_version,
cipher->cipher);
}
static int test_ktls_sendfile(int tst)
{
struct ktls_test_cipher *cipher;
OPENSSL_assert(tst < (int)NUM_KTLS_TEST_CIPHERS);
cipher = &ktls_test_ciphers[tst];
return execute_test_ktls_sendfile(cipher->tls_version, cipher->cipher);
}
#endif
static int test_large_message_tls(void)
{
return execute_test_large_message(TLS_server_method(), TLS_client_method(),
TLS1_VERSION, 0, 0);
}
static int test_large_message_tls_read_ahead(void)
{
return execute_test_large_message(TLS_server_method(), TLS_client_method(),
TLS1_VERSION, 0, 1);
}
#ifndef OPENSSL_NO_DTLS
static int test_large_message_dtls(void)
{
# ifdef OPENSSL_NO_DTLS1_2
/* Not supported in the FIPS provider */
if (is_fips)
return 1;
# endif
/*
* read_ahead is not relevant to DTLS because DTLS always acts as if
* read_ahead is set.
*/
return execute_test_large_message(DTLS_server_method(),
DTLS_client_method(),
DTLS1_VERSION, 0, 0);
}
#endif
/*
* Test we can successfully send the maximum amount of application data. We
* test each protocol version individually, each with and without EtM enabled.
* TLSv1.3 doesn't use EtM so technically it is redundant to test both but it is
* simpler this way. We also test all combinations with and without the
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS option which affects the size of the
* underlying buffer.
*/
static int test_large_app_data(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0, prot;
unsigned char *msg, *buf = NULL;
size_t written, readbytes;
const SSL_METHOD *smeth = TLS_server_method();
const SSL_METHOD *cmeth = TLS_client_method();
switch (tst >> 2) {
case 0:
#ifndef OSSL_NO_USABLE_TLS1_3
prot = TLS1_3_VERSION;
break;
#else
return 1;
#endif
case 1:
#ifndef OPENSSL_NO_TLS1_2
prot = TLS1_2_VERSION;
break;
#else
return 1;
#endif
case 2:
#ifndef OPENSSL_NO_TLS1_1
prot = TLS1_1_VERSION;
break;
#else
return 1;
#endif
case 3:
#ifndef OPENSSL_NO_TLS1
prot = TLS1_VERSION;
break;
#else
return 1;
#endif
case 4:
#ifndef OPENSSL_NO_SSL3
prot = SSL3_VERSION;
break;
#else
return 1;
#endif
case 5:
#ifndef OPENSSL_NO_DTLS1_2
prot = DTLS1_2_VERSION;
smeth = DTLS_server_method();
cmeth = DTLS_client_method();
break;
#else
return 1;
#endif
case 6:
#ifndef OPENSSL_NO_DTLS1
prot = DTLS1_VERSION;
smeth = DTLS_server_method();
cmeth = DTLS_client_method();
break;
#else
return 1;
#endif
default:
/* Shouldn't happen */
return 0;
}
if ((prot < TLS1_2_VERSION || prot == DTLS1_VERSION) && is_fips)
return 1;
/* Maximal sized message of zeros */
msg = OPENSSL_zalloc(SSL3_RT_MAX_PLAIN_LENGTH);
if (!TEST_ptr(msg))
goto end;
buf = OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH + 1);
if (!TEST_ptr(buf))
goto end;
/* Set whole buffer to all bits set */
memset(buf, 0xff, SSL3_RT_MAX_PLAIN_LENGTH + 1);
if (!TEST_true(create_ssl_ctx_pair(libctx, smeth, cmeth, prot, prot,
&sctx, &cctx, cert, privkey)))
goto end;
if (prot < TLS1_2_VERSION || prot == DTLS1_VERSION) {
/* Older protocol versions need SECLEVEL=0 due to SHA1 usage */
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "DEFAULT:@SECLEVEL=0"))
|| !TEST_true(SSL_CTX_set_cipher_list(sctx,
"DEFAULT:@SECLEVEL=0")))
goto end;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
if ((tst & 1) != 0) {
/* Setting this option gives us a minimally sized underlying buffer */
if (!TEST_true(SSL_set_options(serverssl,
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
|| !TEST_true(SSL_set_options(clientssl,
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)))
goto end;
}
if ((tst & 2) != 0) {
/*
* Setting this option means the MAC is added before encryption
* giving us a larger record for the encryption process
*/
if (!TEST_true(SSL_set_options(serverssl, SSL_OP_NO_ENCRYPT_THEN_MAC))
|| !TEST_true(SSL_set_options(clientssl,
SSL_OP_NO_ENCRYPT_THEN_MAC)))
goto end;
}
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
if (!TEST_true(SSL_write_ex(clientssl, msg, SSL3_RT_MAX_PLAIN_LENGTH,
&written))
|| !TEST_size_t_eq(written, SSL3_RT_MAX_PLAIN_LENGTH))
goto end;
/* We provide a buffer slightly larger than what we are actually expecting */
if (!TEST_true(SSL_read_ex(serverssl, buf, SSL3_RT_MAX_PLAIN_LENGTH + 1,
&readbytes)))
goto end;
if (!TEST_mem_eq(msg, written, buf, readbytes))
goto end;
testresult = 1;
end:
OPENSSL_free(msg);
OPENSSL_free(buf);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3) \
|| !defined(OPENSSL_NO_DTLS)
static int execute_cleanse_plaintext(const SSL_METHOD *smeth,
const SSL_METHOD *cmeth,
int min_version, int max_version)
{
size_t i;
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL3_RECORD *rr;
void *zbuf;
static unsigned char cbuf[16000];
static unsigned char sbuf[16000];
if (!TEST_true(create_ssl_ctx_pair(libctx,
smeth, cmeth,
min_version, max_version,
&sctx, &cctx, cert,
privkey)))
goto end;
# ifdef OPENSSL_NO_DTLS1_2
if (smeth == DTLS_server_method()) {
/* Not supported in the FIPS provider */
if (is_fips) {
testresult = 1;
goto end;
};
/*
* Default sigalgs are SHA1 based in <DTLS1.2 which is in security
* level 0
*/
if (!TEST_true(SSL_CTX_set_cipher_list(sctx, "DEFAULT:@SECLEVEL=0"))
|| !TEST_true(SSL_CTX_set_cipher_list(cctx,
"DEFAULT:@SECLEVEL=0")))
goto end;
}
# endif
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(SSL_set_options(serverssl, SSL_OP_CLEANSE_PLAINTEXT)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
for (i = 0; i < sizeof(cbuf); i++) {
cbuf[i] = i & 0xff;
}
if (!TEST_int_eq(SSL_write(clientssl, cbuf, sizeof(cbuf)), sizeof(cbuf)))
goto end;
if (!TEST_int_eq(SSL_peek(serverssl, &sbuf, sizeof(sbuf)), sizeof(sbuf)))
goto end;
if (!TEST_mem_eq(cbuf, sizeof(cbuf), sbuf, sizeof(sbuf)))
goto end;
/*
* Since we called SSL_peek(), we know the data in the record
* layer is a plaintext record. We can gather the pointer to check
* for zeroization after SSL_read().
*/
rr = serverssl->rlayer.rrec;
zbuf = &rr->data[rr->off];
if (!TEST_int_eq(rr->length, sizeof(cbuf)))
goto end;
/*
* After SSL_peek() the plaintext must still be stored in the
* record.
*/
if (!TEST_mem_eq(cbuf, sizeof(cbuf), zbuf, sizeof(cbuf)))
goto end;
memset(sbuf, 0, sizeof(sbuf));
if (!TEST_int_eq(SSL_read(serverssl, &sbuf, sizeof(sbuf)), sizeof(sbuf)))
goto end;
if (!TEST_mem_eq(cbuf, sizeof(cbuf), sbuf, sizeof(cbuf)))
goto end;
/* Check if rbuf is cleansed */
memset(cbuf, 0, sizeof(cbuf));
if (!TEST_mem_eq(cbuf, sizeof(cbuf), zbuf, sizeof(cbuf)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif /*
* !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3)
* || !defined(OPENSSL_NO_DTLS)
*/
static int test_cleanse_plaintext(void)
{
#if !defined(OPENSSL_NO_TLS1_2)
if (!TEST_true(execute_cleanse_plaintext(TLS_server_method(),
TLS_client_method(),
TLS1_2_VERSION,
TLS1_2_VERSION)))
return 0;
#endif
#if !defined(OSSL_NO_USABLE_TLS1_3)
if (!TEST_true(execute_cleanse_plaintext(TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
TLS1_3_VERSION)))
return 0;
#endif
#if !defined(OPENSSL_NO_DTLS)
if (!TEST_true(execute_cleanse_plaintext(DTLS_server_method(),
DTLS_client_method(),
DTLS1_VERSION,
0)))
return 0;
#endif
return 1;
}
#ifndef OPENSSL_NO_OCSP
static int ocsp_server_cb(SSL *s, void *arg)
{
int *argi = (int *)arg;
unsigned char *copy = NULL;
STACK_OF(OCSP_RESPID) *ids = NULL;
OCSP_RESPID *id = NULL;
if (*argi == 2) {
/* In this test we are expecting exactly 1 OCSP_RESPID */
SSL_get_tlsext_status_ids(s, &ids);
if (ids == NULL || sk_OCSP_RESPID_num(ids) != 1)
return SSL_TLSEXT_ERR_ALERT_FATAL;
id = sk_OCSP_RESPID_value(ids, 0);
if (id == NULL || !OCSP_RESPID_match_ex(id, ocspcert, libctx, NULL))
return SSL_TLSEXT_ERR_ALERT_FATAL;
} else if (*argi != 1) {
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
if (!TEST_ptr(copy = OPENSSL_memdup(orespder, sizeof(orespder))))
return SSL_TLSEXT_ERR_ALERT_FATAL;
if (!TEST_true(SSL_set_tlsext_status_ocsp_resp(s, copy,
sizeof(orespder)))) {
OPENSSL_free(copy);
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
ocsp_server_called = 1;
return SSL_TLSEXT_ERR_OK;
}
static int ocsp_client_cb(SSL *s, void *arg)
{
int *argi = (int *)arg;
const unsigned char *respderin;
size_t len;
if (*argi != 1 && *argi != 2)
return 0;
len = SSL_get_tlsext_status_ocsp_resp(s, &respderin);
if (!TEST_mem_eq(orespder, len, respderin, len))
return 0;
ocsp_client_called = 1;
return 1;
}
static int test_tlsext_status_type(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
STACK_OF(OCSP_RESPID) *ids = NULL;
OCSP_RESPID *id = NULL;
BIO *certbio = NULL;
if (!create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(),
TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey))
return 0;
if (SSL_CTX_get_tlsext_status_type(cctx) != -1)
goto end;
/* First just do various checks getting and setting tlsext_status_type */
clientssl = SSL_new(cctx);
if (!TEST_int_eq(SSL_get_tlsext_status_type(clientssl), -1)
|| !TEST_true(SSL_set_tlsext_status_type(clientssl,
TLSEXT_STATUSTYPE_ocsp))
|| !TEST_int_eq(SSL_get_tlsext_status_type(clientssl),
TLSEXT_STATUSTYPE_ocsp))
goto end;
SSL_free(clientssl);
clientssl = NULL;
if (!SSL_CTX_set_tlsext_status_type(cctx, TLSEXT_STATUSTYPE_ocsp)
|| SSL_CTX_get_tlsext_status_type(cctx) != TLSEXT_STATUSTYPE_ocsp)
goto end;
clientssl = SSL_new(cctx);
if (SSL_get_tlsext_status_type(clientssl) != TLSEXT_STATUSTYPE_ocsp)
goto end;
SSL_free(clientssl);
clientssl = NULL;
/*
* Now actually do a handshake and check OCSP information is exchanged and
* the callbacks get called
*/
SSL_CTX_set_tlsext_status_cb(cctx, ocsp_client_cb);
SSL_CTX_set_tlsext_status_arg(cctx, &cdummyarg);
SSL_CTX_set_tlsext_status_cb(sctx, ocsp_server_cb);
SSL_CTX_set_tlsext_status_arg(sctx, &cdummyarg);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_true(ocsp_client_called)
|| !TEST_true(ocsp_server_called))
goto end;
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = NULL;
clientssl = NULL;
/* Try again but this time force the server side callback to fail */
ocsp_client_called = 0;
ocsp_server_called = 0;
cdummyarg = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
/* This should fail because the callback will fail */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(ocsp_client_called)
|| !TEST_false(ocsp_server_called))
goto end;
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = NULL;
clientssl = NULL;
/*
* This time we'll get the client to send an OCSP_RESPID that it will
* accept.
*/
ocsp_client_called = 0;
ocsp_server_called = 0;
cdummyarg = 2;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
/*
* We'll just use any old cert for this test - it doesn't have to be an OCSP
* specific one. We'll use the server cert.
*/
if (!TEST_ptr(certbio = BIO_new_file(cert, "r"))
|| !TEST_ptr(id = OCSP_RESPID_new())
|| !TEST_ptr(ids = sk_OCSP_RESPID_new_null())
|| !TEST_ptr(ocspcert = X509_new_ex(libctx, NULL))
|| !TEST_ptr(PEM_read_bio_X509(certbio, &ocspcert, NULL, NULL))
|| !TEST_true(OCSP_RESPID_set_by_key_ex(id, ocspcert, libctx, NULL))
|| !TEST_true(sk_OCSP_RESPID_push(ids, id)))
goto end;
id = NULL;
SSL_set_tlsext_status_ids(clientssl, ids);
/* Control has been transferred */
ids = NULL;
BIO_free(certbio);
certbio = NULL;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_true(ocsp_client_called)
|| !TEST_true(ocsp_server_called))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
sk_OCSP_RESPID_pop_free(ids, OCSP_RESPID_free);
OCSP_RESPID_free(id);
BIO_free(certbio);
X509_free(ocspcert);
ocspcert = NULL;
return testresult;
}
#endif
#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
static int new_called, remove_called, get_called;
static int new_session_cb(SSL *ssl, SSL_SESSION *sess)
{
new_called++;
/*
* sess has been up-refed for us, but we don't actually need it so free it
* immediately.
*/
SSL_SESSION_free(sess);
return 1;
}
static void remove_session_cb(SSL_CTX *ctx, SSL_SESSION *sess)
{
remove_called++;
}
static SSL_SESSION *get_sess_val = NULL;
static SSL_SESSION *get_session_cb(SSL *ssl, const unsigned char *id, int len,
int *copy)
{
get_called++;
*copy = 1;
return get_sess_val;
}
static int execute_test_session(int maxprot, int use_int_cache,
int use_ext_cache, long s_options)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl1 = NULL, *clientssl1 = NULL;
SSL *serverssl2 = NULL, *clientssl2 = NULL;
# ifndef OPENSSL_NO_TLS1_1
SSL *serverssl3 = NULL, *clientssl3 = NULL;
# endif
SSL_SESSION *sess1 = NULL, *sess2 = NULL;
int testresult = 0, numnewsesstick = 1;
new_called = remove_called = 0;
/* TLSv1.3 sends 2 NewSessionTickets */
if (maxprot == TLS1_3_VERSION)
numnewsesstick = 2;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
return 0;
/*
* Only allow the max protocol version so we can force a connection failure
* later
*/
SSL_CTX_set_min_proto_version(cctx, maxprot);
SSL_CTX_set_max_proto_version(cctx, maxprot);
/* Set up session cache */
if (use_ext_cache) {
SSL_CTX_sess_set_new_cb(cctx, new_session_cb);
SSL_CTX_sess_set_remove_cb(cctx, remove_session_cb);
}
if (use_int_cache) {
/* Also covers instance where both are set */
SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT);
} else {
SSL_CTX_set_session_cache_mode(cctx,
SSL_SESS_CACHE_CLIENT
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
}
if (s_options) {
SSL_CTX_set_options(sctx, s_options);
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl1, clientssl1,
SSL_ERROR_NONE))
|| !TEST_ptr(sess1 = SSL_get1_session(clientssl1)))
goto end;
/* Should fail because it should already be in the cache */
if (use_int_cache && !TEST_false(SSL_CTX_add_session(cctx, sess1)))
goto end;
if (use_ext_cache
&& (!TEST_int_eq(new_called, numnewsesstick)
|| !TEST_int_eq(remove_called, 0)))
goto end;
new_called = remove_called = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl2,
&clientssl2, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl2, sess1))
|| !TEST_true(create_ssl_connection(serverssl2, clientssl2,
SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl2)))
goto end;
if (maxprot == TLS1_3_VERSION) {
/*
* In TLSv1.3 we should have created a new session even though we have
* resumed. Since we attempted a resume we should also have removed the
* old ticket from the cache so that we try to only use tickets once.
*/
if (use_ext_cache
&& (!TEST_int_eq(new_called, 1)
|| !TEST_int_eq(remove_called, 1)))
goto end;
} else {
/*
* In TLSv1.2 we expect to have resumed so no sessions added or
* removed.
*/
if (use_ext_cache
&& (!TEST_int_eq(new_called, 0)
|| !TEST_int_eq(remove_called, 0)))
goto end;
}
SSL_SESSION_free(sess1);
if (!TEST_ptr(sess1 = SSL_get1_session(clientssl2)))
goto end;
shutdown_ssl_connection(serverssl2, clientssl2);
serverssl2 = clientssl2 = NULL;
new_called = remove_called = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl2,
&clientssl2, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl2, clientssl2,
SSL_ERROR_NONE)))
goto end;
if (!TEST_ptr(sess2 = SSL_get1_session(clientssl2)))
goto end;
if (use_ext_cache
&& (!TEST_int_eq(new_called, numnewsesstick)
|| !TEST_int_eq(remove_called, 0)))
goto end;
new_called = remove_called = 0;
/*
* This should clear sess2 from the cache because it is a "bad" session.
* See SSL_set_session() documentation.
*/
if (!TEST_true(SSL_set_session(clientssl2, sess1)))
goto end;
if (use_ext_cache
&& (!TEST_int_eq(new_called, 0) || !TEST_int_eq(remove_called, 1)))
goto end;
if (!TEST_ptr_eq(SSL_get_session(clientssl2), sess1))
goto end;
if (use_int_cache) {
/* Should succeeded because it should not already be in the cache */
if (!TEST_true(SSL_CTX_add_session(cctx, sess2))
|| !TEST_true(SSL_CTX_remove_session(cctx, sess2)))
goto end;
}
new_called = remove_called = 0;
/* This shouldn't be in the cache so should fail */
if (!TEST_false(SSL_CTX_remove_session(cctx, sess2)))
goto end;
if (use_ext_cache
&& (!TEST_int_eq(new_called, 0) || !TEST_int_eq(remove_called, 1)))
goto end;
# if !defined(OPENSSL_NO_TLS1_1)
new_called = remove_called = 0;
/* Force a connection failure */
SSL_CTX_set_max_proto_version(sctx, TLS1_1_VERSION);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl3,
&clientssl3, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl3, sess1))
/* This should fail because of the mismatched protocol versions */
|| !TEST_false(create_ssl_connection(serverssl3, clientssl3,
SSL_ERROR_NONE)))
goto end;
/* We should have automatically removed the session from the cache */
if (use_ext_cache
&& (!TEST_int_eq(new_called, 0) || !TEST_int_eq(remove_called, 1)))
goto end;
/* Should succeed because it should not already be in the cache */
if (use_int_cache && !TEST_true(SSL_CTX_add_session(cctx, sess2)))
goto end;
# endif
/* Now do some tests for server side caching */
if (use_ext_cache) {
SSL_CTX_sess_set_new_cb(cctx, NULL);
SSL_CTX_sess_set_remove_cb(cctx, NULL);
SSL_CTX_sess_set_new_cb(sctx, new_session_cb);
SSL_CTX_sess_set_remove_cb(sctx, remove_session_cb);
SSL_CTX_sess_set_get_cb(sctx, get_session_cb);
get_sess_val = NULL;
}
SSL_CTX_set_session_cache_mode(cctx, 0);
/* Internal caching is the default on the server side */
if (!use_int_cache)
SSL_CTX_set_session_cache_mode(sctx,
SSL_SESS_CACHE_SERVER
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
SSL_free(serverssl1);
SSL_free(clientssl1);
serverssl1 = clientssl1 = NULL;
SSL_free(serverssl2);
SSL_free(clientssl2);
serverssl2 = clientssl2 = NULL;
SSL_SESSION_free(sess1);
sess1 = NULL;
SSL_SESSION_free(sess2);
sess2 = NULL;
SSL_CTX_set_max_proto_version(sctx, maxprot);
if (maxprot == TLS1_2_VERSION)
SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET);
new_called = remove_called = get_called = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl1, clientssl1,
SSL_ERROR_NONE))
|| !TEST_ptr(sess1 = SSL_get1_session(clientssl1))
|| !TEST_ptr(sess2 = SSL_get1_session(serverssl1)))
goto end;
if (use_int_cache) {
if (maxprot == TLS1_3_VERSION && !use_ext_cache) {
/*
* In TLSv1.3 it should not have been added to the internal cache,
* except in the case where we also have an external cache (in that
* case it gets added to the cache in order to generate remove
* events after timeout).
*/
if (!TEST_false(SSL_CTX_remove_session(sctx, sess2)))
goto end;
} else {
/* Should fail because it should already be in the cache */
if (!TEST_false(SSL_CTX_add_session(sctx, sess2)))
goto end;
}
}
if (use_ext_cache) {
SSL_SESSION *tmp = sess2;
if (!TEST_int_eq(new_called, numnewsesstick)
|| !TEST_int_eq(remove_called, 0)
|| !TEST_int_eq(get_called, 0))
goto end;
/*
* Delete the session from the internal cache to force a lookup from
* the external cache. We take a copy first because
* SSL_CTX_remove_session() also marks the session as non-resumable.
*/
if (use_int_cache && maxprot != TLS1_3_VERSION) {
if (!TEST_ptr(tmp = SSL_SESSION_dup(sess2))
|| !TEST_true(sess2->owner != NULL)
|| !TEST_true(tmp->owner == NULL)
|| !TEST_true(SSL_CTX_remove_session(sctx, sess2)))
goto end;
SSL_SESSION_free(sess2);
}
sess2 = tmp;
}
new_called = remove_called = get_called = 0;
get_sess_val = sess2;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl2,
&clientssl2, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl2, sess1))
|| !TEST_true(create_ssl_connection(serverssl2, clientssl2,
SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl2)))
goto end;
if (use_ext_cache) {
if (!TEST_int_eq(remove_called, 0))
goto end;
if (maxprot == TLS1_3_VERSION) {
if (!TEST_int_eq(new_called, 1)
|| !TEST_int_eq(get_called, 0))
goto end;
} else {
if (!TEST_int_eq(new_called, 0)
|| !TEST_int_eq(get_called, 1))
goto end;
}
}
/*
* Make a small cache, force out all other sessions but
* sess2, try to add sess1, which should succeed. Then
* make sure it's there by checking the owners. Despite
* the timeouts, sess1 should have kicked out sess2
*/
/* Make sess1 expire before sess2 */
if (!TEST_long_gt(SSL_SESSION_set_time(sess1, 1000), 0)
|| !TEST_long_gt(SSL_SESSION_set_timeout(sess1, 1000), 0)
|| !TEST_long_gt(SSL_SESSION_set_time(sess2, 2000), 0)
|| !TEST_long_gt(SSL_SESSION_set_timeout(sess2, 2000), 0))
goto end;
if (!TEST_long_ne(SSL_CTX_sess_set_cache_size(sctx, 1), 0))
goto end;
/* Don't care about results - cache should only be sess2 at end */
SSL_CTX_add_session(sctx, sess1);
SSL_CTX_add_session(sctx, sess2);
/* Now add sess1, and make sure it remains, despite timeout */
if (!TEST_true(SSL_CTX_add_session(sctx, sess1))
|| !TEST_ptr(sess1->owner)
|| !TEST_ptr_null(sess2->owner))
goto end;
testresult = 1;
end:
SSL_free(serverssl1);
SSL_free(clientssl1);
SSL_free(serverssl2);
SSL_free(clientssl2);
# ifndef OPENSSL_NO_TLS1_1
SSL_free(serverssl3);
SSL_free(clientssl3);
# endif
SSL_SESSION_free(sess1);
SSL_SESSION_free(sess2);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif /* !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) */
static int test_session_with_only_int_cache(void)
{
#ifndef OSSL_NO_USABLE_TLS1_3
if (!execute_test_session(TLS1_3_VERSION, 1, 0, 0))
return 0;
#endif
#ifndef OPENSSL_NO_TLS1_2
return execute_test_session(TLS1_2_VERSION, 1, 0, 0);
#else
return 1;
#endif
}
static int test_session_with_only_ext_cache(void)
{
#ifndef OSSL_NO_USABLE_TLS1_3
if (!execute_test_session(TLS1_3_VERSION, 0, 1, 0))
return 0;
#endif
#ifndef OPENSSL_NO_TLS1_2
return execute_test_session(TLS1_2_VERSION, 0, 1, 0);
#else
return 1;
#endif
}
static int test_session_with_both_cache(void)
{
#ifndef OSSL_NO_USABLE_TLS1_3
if (!execute_test_session(TLS1_3_VERSION, 1, 1, 0))
return 0;
#endif
#ifndef OPENSSL_NO_TLS1_2
return execute_test_session(TLS1_2_VERSION, 1, 1, 0);
#else
return 1;
#endif
}
static int test_session_wo_ca_names(void)
{
#ifndef OSSL_NO_USABLE_TLS1_3
if (!execute_test_session(TLS1_3_VERSION, 1, 0, SSL_OP_DISABLE_TLSEXT_CA_NAMES))
return 0;
#endif
#ifndef OPENSSL_NO_TLS1_2
return execute_test_session(TLS1_2_VERSION, 1, 0, SSL_OP_DISABLE_TLSEXT_CA_NAMES);
#else
return 1;
#endif
}
#ifndef OSSL_NO_USABLE_TLS1_3
static SSL_SESSION *sesscache[6];
static int do_cache;
static int new_cachesession_cb(SSL *ssl, SSL_SESSION *sess)
{
if (do_cache) {
sesscache[new_called] = sess;
} else {
/* We don't need the reference to the session, so free it */
SSL_SESSION_free(sess);
}
new_called++;
return 1;
}
static int post_handshake_verify(SSL *sssl, SSL *cssl)
{
SSL_set_verify(sssl, SSL_VERIFY_PEER, NULL);
if (!TEST_true(SSL_verify_client_post_handshake(sssl)))
return 0;
/* Start handshake on the server and client */
if (!TEST_int_eq(SSL_do_handshake(sssl), 1)
|| !TEST_int_le(SSL_read(cssl, NULL, 0), 0)
|| !TEST_int_le(SSL_read(sssl, NULL, 0), 0)
|| !TEST_true(create_ssl_connection(sssl, cssl,
SSL_ERROR_NONE)))
return 0;
return 1;
}
static int setup_ticket_test(int stateful, int idx, SSL_CTX **sctx,
SSL_CTX **cctx)
{
int sess_id_ctx = 1;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
sctx, cctx, cert, privkey))
|| !TEST_true(SSL_CTX_set_num_tickets(*sctx, idx))
|| !TEST_true(SSL_CTX_set_session_id_context(*sctx,
(void *)&sess_id_ctx,
sizeof(sess_id_ctx))))
return 0;
if (stateful)
SSL_CTX_set_options(*sctx, SSL_OP_NO_TICKET);
SSL_CTX_set_session_cache_mode(*cctx, SSL_SESS_CACHE_CLIENT
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
SSL_CTX_sess_set_new_cb(*cctx, new_cachesession_cb);
return 1;
}
static int check_resumption(int idx, SSL_CTX *sctx, SSL_CTX *cctx, int succ)
{
SSL *serverssl = NULL, *clientssl = NULL;
int i;
/* Test that we can resume with all the tickets we got given */
for (i = 0; i < idx * 2; i++) {
new_called = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, sesscache[i])))
goto end;
SSL_set_post_handshake_auth(clientssl, 1);
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
/*
* Following a successful resumption we only get 1 ticket. After a
* failed one we should get idx tickets.
*/
if (succ) {
if (!TEST_true(SSL_session_reused(clientssl))
|| !TEST_int_eq(new_called, 1))
goto end;
} else {
if (!TEST_false(SSL_session_reused(clientssl))
|| !TEST_int_eq(new_called, idx))
goto end;
}
new_called = 0;
/* After a post-handshake authentication we should get 1 new ticket */
if (succ
&& (!post_handshake_verify(serverssl, clientssl)
|| !TEST_int_eq(new_called, 1)))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
SSL_SESSION_free(sesscache[i]);
sesscache[i] = NULL;
}
return 1;
end:
SSL_free(clientssl);
SSL_free(serverssl);
return 0;
}
static int test_tickets(int stateful, int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
size_t j;
/* idx is the test number, but also the number of tickets we want */
new_called = 0;
do_cache = 1;
if (!setup_ticket_test(stateful, idx, &sctx, &cctx))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
/* Check we got the number of tickets we were expecting */
|| !TEST_int_eq(idx, new_called))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
clientssl = serverssl = NULL;
sctx = cctx = NULL;
/*
* Now we try to resume with the tickets we previously created. The
* resumption attempt is expected to fail (because we're now using a new
* SSL_CTX). We should see idx number of tickets issued again.
*/
/* Stop caching sessions - just count them */
do_cache = 0;
if (!setup_ticket_test(stateful, idx, &sctx, &cctx))
goto end;
if (!check_resumption(idx, sctx, cctx, 0))
goto end;
/* Start again with caching sessions */
new_called = 0;
do_cache = 1;
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
sctx = cctx = NULL;
if (!setup_ticket_test(stateful, idx, &sctx, &cctx))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
SSL_set_post_handshake_auth(clientssl, 1);
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
/* Check we got the number of tickets we were expecting */
|| !TEST_int_eq(idx, new_called))
goto end;
/* After a post-handshake authentication we should get new tickets issued */
if (!post_handshake_verify(serverssl, clientssl)
|| !TEST_int_eq(idx * 2, new_called))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* Stop caching sessions - just count them */
do_cache = 0;
/*
* Check we can resume with all the tickets we created. This time around the
* resumptions should all be successful.
*/
if (!check_resumption(idx, sctx, cctx, 1))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
for (j = 0; j < OSSL_NELEM(sesscache); j++) {
SSL_SESSION_free(sesscache[j]);
sesscache[j] = NULL;
}
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static int test_stateless_tickets(int idx)
{
return test_tickets(0, idx);
}
static int test_stateful_tickets(int idx)
{
return test_tickets(1, idx);
}
static int test_psk_tickets(void)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
int sess_id_ctx = 1;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, NULL, NULL))
|| !TEST_true(SSL_CTX_set_session_id_context(sctx,
(void *)&sess_id_ctx,
sizeof(sess_id_ctx))))
goto end;
SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
SSL_CTX_set_psk_use_session_callback(cctx, use_session_cb);
SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb);
SSL_CTX_sess_set_new_cb(cctx, new_session_cb);
use_session_cb_cnt = 0;
find_session_cb_cnt = 0;
srvid = pskid;
new_called = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
clientpsk = serverpsk = create_a_psk(clientssl, SHA384_DIGEST_LENGTH);
if (!TEST_ptr(clientpsk))
goto end;
SSL_SESSION_up_ref(clientpsk);
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_int_eq(1, find_session_cb_cnt)
|| !TEST_int_eq(1, use_session_cb_cnt)
/* We should always get 1 ticket when using external PSK */
|| !TEST_int_eq(1, new_called))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
return testresult;
}
static int test_extra_tickets(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
BIO *bretry = BIO_new(bio_s_always_retry());
BIO *tmp = NULL;
int testresult = 0;
int stateful = 0;
size_t nbytes;
unsigned char c, buf[1];
new_called = 0;
do_cache = 1;
if (idx >= 3) {
idx -= 3;
stateful = 1;
}
if (!TEST_ptr(bretry) || !setup_ticket_test(stateful, idx, &sctx, &cctx))
goto end;
SSL_CTX_sess_set_new_cb(sctx, new_session_cb);
/* setup_ticket_test() uses new_cachesession_cb which we don't need. */
SSL_CTX_sess_set_new_cb(cctx, new_session_cb);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
/*
* Note that we have new_session_cb on both sctx and cctx, so new_called is
* incremented by both client and server.
*/
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
/* Check we got the number of tickets we were expecting */
|| !TEST_int_eq(idx * 2, new_called)
|| !TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_int_eq(idx * 2, new_called))
goto end;
/* Now try a (real) write to actually send the tickets */
c = '1';
if (!TEST_true(SSL_write_ex(serverssl, &c, 1, &nbytes))
|| !TEST_size_t_eq(1, nbytes)
|| !TEST_int_eq(idx * 2 + 2, new_called)
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
|| !TEST_int_eq(idx * 2 + 4, new_called)
|| !TEST_int_eq(sizeof(buf), nbytes)
|| !TEST_int_eq(c, buf[0])
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes)))
goto end;
/* Try with only requesting one new ticket, too */
c = '2';
new_called = 0;
if (!TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_true(SSL_write_ex(serverssl, &c, sizeof(c), &nbytes))
|| !TEST_size_t_eq(sizeof(c), nbytes)
|| !TEST_int_eq(1, new_called)
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
|| !TEST_int_eq(2, new_called)
|| !TEST_size_t_eq(sizeof(buf), nbytes)
|| !TEST_int_eq(c, buf[0]))
goto end;
/* Do it again but use dummy writes to drive the ticket generation */
c = '3';
new_called = 0;
if (!TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_true(SSL_write_ex(serverssl, &c, 0, &nbytes))
|| !TEST_size_t_eq(0, nbytes)
|| !TEST_int_eq(2, new_called)
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
|| !TEST_int_eq(4, new_called))
goto end;
/* Once more, but with SSL_do_handshake() to drive the ticket generation */
c = '4';
new_called = 0;
if (!TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_true(SSL_do_handshake(serverssl))
|| !TEST_int_eq(2, new_called)
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
|| !TEST_int_eq(4, new_called))
goto end;
/*
* Use the always-retry BIO to exercise the logic that forces ticket
* generation to wait until a record boundary.
*/
c = '5';
new_called = 0;
tmp = SSL_get_wbio(serverssl);
if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
tmp = NULL;
goto end;
}
SSL_set0_wbio(serverssl, bretry);
bretry = NULL;
if (!TEST_false(SSL_write_ex(serverssl, &c, 1, &nbytes))
|| !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_WANT_WRITE)
|| !TEST_size_t_eq(nbytes, 0))
goto end;
/* Restore a BIO that will let the write succeed */
SSL_set0_wbio(serverssl, tmp);
tmp = NULL;
/*
* These calls should just queue the request and not send anything
* even if we explicitly try to hit the state machine.
*/
if (!TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_int_eq(0, new_called)
|| !TEST_true(SSL_do_handshake(serverssl))
|| !TEST_int_eq(0, new_called))
goto end;
/* Re-do the write; still no tickets sent */
if (!TEST_true(SSL_write_ex(serverssl, &c, 1, &nbytes))
|| !TEST_size_t_eq(1, nbytes)
|| !TEST_int_eq(0, new_called)
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
|| !TEST_int_eq(0, new_called)
|| !TEST_int_eq(sizeof(buf), nbytes)
|| !TEST_int_eq(c, buf[0])
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes)))
goto end;
/* Even trying to hit the state machine now will still not send tickets */
if (!TEST_true(SSL_do_handshake(serverssl))
|| !TEST_int_eq(0, new_called))
goto end;
/* Now the *next* write should send the tickets */
c = '6';
if (!TEST_true(SSL_write_ex(serverssl, &c, 1, &nbytes))
|| !TEST_size_t_eq(1, nbytes)
|| !TEST_int_eq(2, new_called)
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
|| !TEST_int_eq(4, new_called)
|| !TEST_int_eq(sizeof(buf), nbytes)
|| !TEST_int_eq(c, buf[0])
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes)))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
testresult = 1;
end:
BIO_free(bretry);
BIO_free(tmp);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
clientssl = serverssl = NULL;
sctx = cctx = NULL;
return testresult;
}
#endif
#define USE_NULL 0
#define USE_BIO_1 1
#define USE_BIO_2 2
#define USE_DEFAULT 3
#define CONNTYPE_CONNECTION_SUCCESS 0
#define CONNTYPE_CONNECTION_FAIL 1
#define CONNTYPE_NO_CONNECTION 2
#define TOTAL_NO_CONN_SSL_SET_BIO_TESTS (3 * 3 * 3 * 3)
#define TOTAL_CONN_SUCCESS_SSL_SET_BIO_TESTS (2 * 2)
#if !defined(OSSL_NO_USABLE_TLS1_3) && !defined(OPENSSL_NO_TLS1_2)
# define TOTAL_CONN_FAIL_SSL_SET_BIO_TESTS (2 * 2)
#else
# define TOTAL_CONN_FAIL_SSL_SET_BIO_TESTS 0
#endif
#define TOTAL_SSL_SET_BIO_TESTS TOTAL_NO_CONN_SSL_SET_BIO_TESTS \
+ TOTAL_CONN_SUCCESS_SSL_SET_BIO_TESTS \
+ TOTAL_CONN_FAIL_SSL_SET_BIO_TESTS
static void setupbio(BIO **res, BIO *bio1, BIO *bio2, int type)
{
switch (type) {
case USE_NULL:
*res = NULL;
break;
case USE_BIO_1:
*res = bio1;
break;
case USE_BIO_2:
*res = bio2;
break;
}
}
/*
* Tests calls to SSL_set_bio() under various conditions.
*
* For the first 3 * 3 * 3 * 3 = 81 tests we do 2 calls to SSL_set_bio() with
* various combinations of valid BIOs or NULL being set for the rbio/wbio. We
* then do more tests where we create a successful connection first using our
* standard connection setup functions, and then call SSL_set_bio() with
* various combinations of valid BIOs or NULL. We then repeat these tests
* following a failed connection. In this last case we are looking to check that
* SSL_set_bio() functions correctly in the case where s->bbio is not NULL.
*/
static int test_ssl_set_bio(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
BIO *bio1 = NULL;
BIO *bio2 = NULL;
BIO *irbio = NULL, *iwbio = NULL, *nrbio = NULL, *nwbio = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int initrbio, initwbio, newrbio, newwbio, conntype;
int testresult = 0;
if (idx < TOTAL_NO_CONN_SSL_SET_BIO_TESTS) {
initrbio = idx % 3;
idx /= 3;
initwbio = idx % 3;
idx /= 3;
newrbio = idx % 3;
idx /= 3;
newwbio = idx % 3;
conntype = CONNTYPE_NO_CONNECTION;
} else {
idx -= TOTAL_NO_CONN_SSL_SET_BIO_TESTS;
initrbio = initwbio = USE_DEFAULT;
newrbio = idx % 2;
idx /= 2;
newwbio = idx % 2;
idx /= 2;
conntype = idx % 2;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
if (conntype == CONNTYPE_CONNECTION_FAIL) {
/*
* We won't ever get here if either TLSv1.3 or TLSv1.2 is disabled
* because we reduced the number of tests in the definition of
* TOTAL_CONN_FAIL_SSL_SET_BIO_TESTS to avoid this scenario. By setting
* mismatched protocol versions we will force a connection failure.
*/
SSL_CTX_set_min_proto_version(sctx, TLS1_3_VERSION);
SSL_CTX_set_max_proto_version(cctx, TLS1_2_VERSION);
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (initrbio == USE_BIO_1
|| initwbio == USE_BIO_1
|| newrbio == USE_BIO_1
|| newwbio == USE_BIO_1) {
if (!TEST_ptr(bio1 = BIO_new(BIO_s_mem())))
goto end;
}
if (initrbio == USE_BIO_2
|| initwbio == USE_BIO_2
|| newrbio == USE_BIO_2
|| newwbio == USE_BIO_2) {
if (!TEST_ptr(bio2 = BIO_new(BIO_s_mem())))
goto end;
}
if (initrbio != USE_DEFAULT) {
setupbio(&irbio, bio1, bio2, initrbio);
setupbio(&iwbio, bio1, bio2, initwbio);
SSL_set_bio(clientssl, irbio, iwbio);
/*
* We want to maintain our own refs to these BIO, so do an up ref for
* each BIO that will have ownership transferred in the SSL_set_bio()
* call
*/
if (irbio != NULL)
BIO_up_ref(irbio);
if (iwbio != NULL && iwbio != irbio)
BIO_up_ref(iwbio);
}
if (conntype != CONNTYPE_NO_CONNECTION
&& !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)
== (conntype == CONNTYPE_CONNECTION_SUCCESS)))
goto end;
setupbio(&nrbio, bio1, bio2, newrbio);
setupbio(&nwbio, bio1, bio2, newwbio);
/*
* We will (maybe) transfer ownership again so do more up refs.
* SSL_set_bio() has some really complicated ownership rules where BIOs have
* already been set!
*/
if (nrbio != NULL
&& nrbio != irbio
&& (nwbio != iwbio || nrbio != nwbio))
BIO_up_ref(nrbio);
if (nwbio != NULL
&& nwbio != nrbio
&& (nwbio != iwbio || (nwbio == iwbio && irbio == iwbio)))
BIO_up_ref(nwbio);
SSL_set_bio(clientssl, nrbio, nwbio);
testresult = 1;
end:
BIO_free(bio1);
BIO_free(bio2);
/*
* This test is checking that the ref counting for SSL_set_bio is correct.
* If we get here and we did too many frees then we will fail in the above
* functions.
*/
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
typedef enum { NO_BIO_CHANGE, CHANGE_RBIO, CHANGE_WBIO } bio_change_t;
static int execute_test_ssl_bio(int pop_ssl, bio_change_t change_bio)
{
BIO *sslbio = NULL, *membio1 = NULL, *membio2 = NULL;
SSL_CTX *ctx;
SSL *ssl = NULL;
int testresult = 0;
if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_method()))
|| !TEST_ptr(ssl = SSL_new(ctx))
|| !TEST_ptr(sslbio = BIO_new(BIO_f_ssl()))
|| !TEST_ptr(membio1 = BIO_new(BIO_s_mem())))
goto end;
BIO_set_ssl(sslbio, ssl, BIO_CLOSE);
/*
* If anything goes wrong here then we could leak memory.
*/
BIO_push(sslbio, membio1);
/* Verify changing the rbio/wbio directly does not cause leaks */
if (change_bio != NO_BIO_CHANGE) {
if (!TEST_ptr(membio2 = BIO_new(BIO_s_mem()))) {
ssl = NULL;
goto end;
}
if (change_bio == CHANGE_RBIO)
SSL_set0_rbio(ssl, membio2);
else
SSL_set0_wbio(ssl, membio2);
}
ssl = NULL;
if (pop_ssl)
BIO_pop(sslbio);
else
BIO_pop(membio1);
testresult = 1;
end:
BIO_free(membio1);
BIO_free(sslbio);
SSL_free(ssl);
SSL_CTX_free(ctx);
return testresult;
}
static int test_ssl_bio_pop_next_bio(void)
{
return execute_test_ssl_bio(0, NO_BIO_CHANGE);
}
static int test_ssl_bio_pop_ssl_bio(void)
{
return execute_test_ssl_bio(1, NO_BIO_CHANGE);
}
static int test_ssl_bio_change_rbio(void)
{
return execute_test_ssl_bio(0, CHANGE_RBIO);
}
static int test_ssl_bio_change_wbio(void)
{
return execute_test_ssl_bio(0, CHANGE_WBIO);
}
#if !defined(OPENSSL_NO_TLS1_2) || defined(OSSL_NO_USABLE_TLS1_3)
typedef struct {
/* The list of sig algs */
const int *list;
/* The length of the list */
size_t listlen;
/* A sigalgs list in string format */
const char *liststr;
/* Whether setting the list should succeed */
int valid;
/* Whether creating a connection with the list should succeed */
int connsuccess;
} sigalgs_list;
static const int validlist1[] = {NID_sha256, EVP_PKEY_RSA};
# ifndef OPENSSL_NO_EC
static const int validlist2[] = {NID_sha256, EVP_PKEY_RSA, NID_sha512, EVP_PKEY_EC};
static const int validlist3[] = {NID_sha512, EVP_PKEY_EC};
# endif
static const int invalidlist1[] = {NID_undef, EVP_PKEY_RSA};
static const int invalidlist2[] = {NID_sha256, NID_undef};
static const int invalidlist3[] = {NID_sha256, EVP_PKEY_RSA, NID_sha256};
static const int invalidlist4[] = {NID_sha256};
static const sigalgs_list testsigalgs[] = {
{validlist1, OSSL_NELEM(validlist1), NULL, 1, 1},
# ifndef OPENSSL_NO_EC
{validlist2, OSSL_NELEM(validlist2), NULL, 1, 1},
{validlist3, OSSL_NELEM(validlist3), NULL, 1, 0},
# endif
{NULL, 0, "RSA+SHA256", 1, 1},
# ifndef OPENSSL_NO_EC
{NULL, 0, "RSA+SHA256:ECDSA+SHA512", 1, 1},
{NULL, 0, "ECDSA+SHA512", 1, 0},
# endif
{invalidlist1, OSSL_NELEM(invalidlist1), NULL, 0, 0},
{invalidlist2, OSSL_NELEM(invalidlist2), NULL, 0, 0},
{invalidlist3, OSSL_NELEM(invalidlist3), NULL, 0, 0},
{invalidlist4, OSSL_NELEM(invalidlist4), NULL, 0, 0},
{NULL, 0, "RSA", 0, 0},
{NULL, 0, "SHA256", 0, 0},
{NULL, 0, "RSA+SHA256:SHA256", 0, 0},
{NULL, 0, "Invalid", 0, 0}
};
static int test_set_sigalgs(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
const sigalgs_list *curr;
int testctx;
/* Should never happen */
if (!TEST_size_t_le((size_t)idx, OSSL_NELEM(testsigalgs) * 2))
return 0;
testctx = ((size_t)idx < OSSL_NELEM(testsigalgs));
curr = testctx ? &testsigalgs[idx]
: &testsigalgs[idx - OSSL_NELEM(testsigalgs)];
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
return 0;
SSL_CTX_set_max_proto_version(cctx, TLS1_2_VERSION);
if (testctx) {
int ret;
if (curr->list != NULL)
ret = SSL_CTX_set1_sigalgs(cctx, curr->list, curr->listlen);
else
ret = SSL_CTX_set1_sigalgs_list(cctx, curr->liststr);
if (!ret) {
if (curr->valid)
TEST_info("Failure setting sigalgs in SSL_CTX (%d)\n", idx);
else
testresult = 1;
goto end;
}
if (!curr->valid) {
TEST_info("Not-failed setting sigalgs in SSL_CTX (%d)\n", idx);
goto end;
}
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
if (!testctx) {
int ret;
if (curr->list != NULL)
ret = SSL_set1_sigalgs(clientssl, curr->list, curr->listlen);
else
ret = SSL_set1_sigalgs_list(clientssl, curr->liststr);
if (!ret) {
if (curr->valid)
TEST_info("Failure setting sigalgs in SSL (%d)\n", idx);
else
testresult = 1;
goto end;
}
if (!curr->valid)
goto end;
}
if (!TEST_int_eq(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE),
curr->connsuccess))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
static int psk_client_cb_cnt = 0;
static int psk_server_cb_cnt = 0;
static int use_session_cb(SSL *ssl, const EVP_MD *md, const unsigned char **id,
size_t *idlen, SSL_SESSION **sess)
{
switch (++use_session_cb_cnt) {
case 1:
/* The first call should always have a NULL md */
if (md != NULL)
return 0;
break;
case 2:
/* The second call should always have an md */
if (md == NULL)
return 0;
break;
default:
/* We should only be called a maximum of twice */
return 0;
}
if (clientpsk != NULL)
SSL_SESSION_up_ref(clientpsk);
*sess = clientpsk;
*id = (const unsigned char *)pskid;
*idlen = strlen(pskid);
return 1;
}
#ifndef OPENSSL_NO_PSK
static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *id,
unsigned int max_id_len,
unsigned char *psk,
unsigned int max_psk_len)
{
unsigned int psklen = 0;
psk_client_cb_cnt++;
if (strlen(pskid) + 1 > max_id_len)
return 0;
/* We should only ever be called a maximum of twice per connection */
if (psk_client_cb_cnt > 2)
return 0;
if (clientpsk == NULL)
return 0;
/* We'll reuse the PSK we set up for TLSv1.3 */
if (SSL_SESSION_get_master_key(clientpsk, NULL, 0) > max_psk_len)
return 0;
psklen = SSL_SESSION_get_master_key(clientpsk, psk, max_psk_len);
strncpy(id, pskid, max_id_len);
return psklen;
}
#endif /* OPENSSL_NO_PSK */
static int find_session_cb(SSL *ssl, const unsigned char *identity,
size_t identity_len, SSL_SESSION **sess)
{
find_session_cb_cnt++;
/* We should only ever be called a maximum of twice per connection */
if (find_session_cb_cnt > 2)
return 0;
if (serverpsk == NULL)
return 0;
/* Identity should match that set by the client */
if (strlen(srvid) != identity_len
|| strncmp(srvid, (const char *)identity, identity_len) != 0) {
/* No PSK found, continue but without a PSK */
*sess = NULL;
return 1;
}
SSL_SESSION_up_ref(serverpsk);
*sess = serverpsk;
return 1;
}
#ifndef OPENSSL_NO_PSK
static unsigned int psk_server_cb(SSL *ssl, const char *identity,
unsigned char *psk, unsigned int max_psk_len)
{
unsigned int psklen = 0;
psk_server_cb_cnt++;
/* We should only ever be called a maximum of twice per connection */
if (find_session_cb_cnt > 2)
return 0;
if (serverpsk == NULL)
return 0;
/* Identity should match that set by the client */
if (strcmp(srvid, identity) != 0) {
return 0;
}
/* We'll reuse the PSK we set up for TLSv1.3 */
if (SSL_SESSION_get_master_key(serverpsk, NULL, 0) > max_psk_len)
return 0;
psklen = SSL_SESSION_get_master_key(serverpsk, psk, max_psk_len);
return psklen;
}
#endif /* OPENSSL_NO_PSK */
#define MSG1 "Hello"
#define MSG2 "World."
#define MSG3 "This"
#define MSG4 "is"
#define MSG5 "a"
#define MSG6 "test"
#define MSG7 "message."
#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01")
#define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02")
#define TLS13_CHACHA20_POLY1305_SHA256_BYTES ((const unsigned char *)"\x13\x03")
#define TLS13_AES_128_CCM_SHA256_BYTES ((const unsigned char *)"\x13\x04")
#define TLS13_AES_128_CCM_8_SHA256_BYTES ((const unsigned char *)"\x13\05")
static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize)
{
const SSL_CIPHER *cipher = NULL;
const unsigned char key[] = {
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, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f /* SHA384_DIGEST_LENGTH bytes */
};
SSL_SESSION *sess = NULL;
if (mdsize == SHA384_DIGEST_LENGTH) {
cipher = SSL_CIPHER_find(ssl, TLS13_AES_256_GCM_SHA384_BYTES);
} else if (mdsize == SHA256_DIGEST_LENGTH) {
/*
* Any ciphersuite using SHA256 will do - it will be compatible with
* the actual ciphersuite selected as long as it too is based on SHA256
*/
cipher = SSL_CIPHER_find(ssl, TLS13_AES_128_GCM_SHA256_BYTES);
} else {
/* Should not happen */
return NULL;
}
sess = SSL_SESSION_new();
if (!TEST_ptr(sess)
|| !TEST_ptr(cipher)
|| !TEST_true(SSL_SESSION_set1_master_key(sess, key, mdsize))
|| !TEST_true(SSL_SESSION_set_cipher(sess, cipher))
|| !TEST_true(
SSL_SESSION_set_protocol_version(sess,
TLS1_3_VERSION))) {
SSL_SESSION_free(sess);
return NULL;
}
return sess;
}
/*
* Helper method to setup objects for early data test. Caller frees objects on
* error.
*/
static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl,
SSL **serverssl, SSL_SESSION **sess, int idx,
size_t mdsize)
{
if (*sctx == NULL
&& !TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION, 0,
sctx, cctx, cert, privkey)))
return 0;
if (!TEST_true(SSL_CTX_set_max_early_data(*sctx, SSL3_RT_MAX_PLAIN_LENGTH)))
return 0;
if (idx == 1) {
/* When idx == 1 we repeat the tests with read_ahead set */
SSL_CTX_set_read_ahead(*cctx, 1);
SSL_CTX_set_read_ahead(*sctx, 1);
} else if (idx == 2) {
/* When idx == 2 we are doing early_data with a PSK. Set up callbacks */
SSL_CTX_set_psk_use_session_callback(*cctx, use_session_cb);
SSL_CTX_set_psk_find_session_callback(*sctx, find_session_cb);
use_session_cb_cnt = 0;
find_session_cb_cnt = 0;
srvid = pskid;
}
if (!TEST_true(create_ssl_objects(*sctx, *cctx, serverssl, clientssl,
NULL, NULL)))
return 0;
/*
* For one of the run throughs (doesn't matter which one), we'll try sending
* some SNI data in the initial ClientHello. This will be ignored (because
* there is no SNI cb set up by the server), so it should not impact
* early_data.
*/
if (idx == 1
&& !TEST_true(SSL_set_tlsext_host_name(*clientssl, "localhost")))
return 0;
if (idx == 2) {
clientpsk = create_a_psk(*clientssl, mdsize);
if (!TEST_ptr(clientpsk)
/*
* We just choose an arbitrary value for max_early_data which
* should be big enough for testing purposes.
*/
|| !TEST_true(SSL_SESSION_set_max_early_data(clientpsk,
0x100))
|| !TEST_true(SSL_SESSION_up_ref(clientpsk))) {
SSL_SESSION_free(clientpsk);
clientpsk = NULL;
return 0;
}
serverpsk = clientpsk;
if (sess != NULL) {
if (!TEST_true(SSL_SESSION_up_ref(clientpsk))) {
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
return 0;
}
*sess = clientpsk;
}
return 1;
}
if (sess == NULL)
return 1;
if (!TEST_true(create_ssl_connection(*serverssl, *clientssl,
SSL_ERROR_NONE)))
return 0;
*sess = SSL_get1_session(*clientssl);
SSL_shutdown(*clientssl);
SSL_shutdown(*serverssl);
SSL_free(*serverssl);
SSL_free(*clientssl);
*serverssl = *clientssl = NULL;
if (!TEST_true(create_ssl_objects(*sctx, *cctx, serverssl,
clientssl, NULL, NULL))
|| !TEST_true(SSL_set_session(*clientssl, *sess)))
return 0;
return 1;
}
static int check_early_data_timeout(time_t timer)
{
int res = 0;
/*
* Early data is time sensitive. We have an approx 8 second allowance
* between writing the early data and reading it. If we exceed that time
* then this test will fail. This can sometimes (rarely) occur in normal CI
* operation. We can try and detect this and just ignore the result of this
* test if it has taken too long. We assume anything over 7 seconds is too
* long
*/
timer = time(NULL) - timer;
if (timer >= 7)
res = TEST_skip("Test took too long, ignoring result");
return res;
}
static int test_early_data_read_write(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
unsigned char buf[20], data[1024];
size_t readbytes, written, eoedlen, rawread, rawwritten;
BIO *rbio;
time_t timer;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx,
SHA384_DIGEST_LENGTH)))
goto end;
/* Write and read some early data */
timer = time(NULL);
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_size_t_eq(written, strlen(MSG1)))
goto end;
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_SUCCESS)) {
testresult = check_early_data_timeout(timer);
goto end;
}
if (!TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED))
goto end;
/*
* Server should be able to write data, and client should be able to
* read it.
*/
if (!TEST_true(SSL_write_early_data(serverssl, MSG2, strlen(MSG2),
&written))
|| !TEST_size_t_eq(written, strlen(MSG2))
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
/* Even after reading normal data, client should be able write early data */
if (!TEST_true(SSL_write_early_data(clientssl, MSG3, strlen(MSG3),
&written))
|| !TEST_size_t_eq(written, strlen(MSG3)))
goto end;
/* Server should still be able read early data after writing data */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_SUCCESS)
|| !TEST_mem_eq(buf, readbytes, MSG3, strlen(MSG3)))
goto end;
/* Write more data from server and read it from client */
if (!TEST_true(SSL_write_early_data(serverssl, MSG4, strlen(MSG4),
&written))
|| !TEST_size_t_eq(written, strlen(MSG4))
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG4, strlen(MSG4)))
goto end;
/*
* If client writes normal data it should mean writing early data is no
* longer possible.
*/
if (!TEST_true(SSL_write_ex(clientssl, MSG5, strlen(MSG5), &written))
|| !TEST_size_t_eq(written, strlen(MSG5))
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_ACCEPTED))
goto end;
/*
* At this point the client has written EndOfEarlyData, ClientFinished and
* normal (fully protected) data. We are going to cause a delay between the
* arrival of EndOfEarlyData and ClientFinished. We read out all the data
* in the read BIO, and then just put back the EndOfEarlyData message.
*/
rbio = SSL_get_rbio(serverssl);
if (!TEST_true(BIO_read_ex(rbio, data, sizeof(data), &rawread))
|| !TEST_size_t_lt(rawread, sizeof(data))
|| !TEST_size_t_gt(rawread, SSL3_RT_HEADER_LENGTH))
goto end;
/* Record length is in the 4th and 5th bytes of the record header */
eoedlen = SSL3_RT_HEADER_LENGTH + (data[3] << 8 | data[4]);
if (!TEST_true(BIO_write_ex(rbio, data, eoedlen, &rawwritten))
|| !TEST_size_t_eq(rawwritten, eoedlen))
goto end;
/* Server should be told that there is no more early data */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_size_t_eq(readbytes, 0))
goto end;
/*
* Server has not finished init yet, so should still be able to write early
* data.
*/
if (!TEST_true(SSL_write_early_data(serverssl, MSG6, strlen(MSG6),
&written))
|| !TEST_size_t_eq(written, strlen(MSG6)))
goto end;
/* Push the ClientFinished and the normal data back into the server rbio */
if (!TEST_true(BIO_write_ex(rbio, data + eoedlen, rawread - eoedlen,
&rawwritten))
|| !TEST_size_t_eq(rawwritten, rawread - eoedlen))
goto end;
/* Server should be able to read normal data */
if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_size_t_eq(readbytes, strlen(MSG5)))
goto end;
/* Client and server should not be able to write/read early data now */
if (!TEST_false(SSL_write_early_data(clientssl, MSG6, strlen(MSG6),
&written)))
goto end;
ERR_clear_error();
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_ERROR))
goto end;
ERR_clear_error();
/* Client should be able to read the data sent by the server */
if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG6, strlen(MSG6)))
goto end;
/*
* Make sure we process the two NewSessionTickets. These arrive
* post-handshake. We attempt reads which we do not expect to return any
* data.
*/
if (!TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf),
&readbytes)))
goto end;
/* Server should be able to write normal data */
if (!TEST_true(SSL_write_ex(serverssl, MSG7, strlen(MSG7), &written))
|| !TEST_size_t_eq(written, strlen(MSG7))
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG7, strlen(MSG7)))
goto end;
SSL_SESSION_free(sess);
sess = SSL_get1_session(clientssl);
use_session_cb_cnt = 0;
find_session_cb_cnt = 0;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, sess)))
goto end;
/* Write and read some early data */
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_size_t_eq(written, strlen(MSG1))
|| !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_SUCCESS)
|| !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1)))
goto end;
if (!TEST_int_gt(SSL_connect(clientssl), 0)
|| !TEST_int_gt(SSL_accept(serverssl), 0))
goto end;
/* Client and server should not be able to write/read early data now */
if (!TEST_false(SSL_write_early_data(clientssl, MSG6, strlen(MSG6),
&written)))
goto end;
ERR_clear_error();
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_ERROR))
goto end;
ERR_clear_error();
/* Client and server should be able to write/read normal data */
if (!TEST_true(SSL_write_ex(clientssl, MSG5, strlen(MSG5), &written))
|| !TEST_size_t_eq(written, strlen(MSG5))
|| !TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_size_t_eq(readbytes, strlen(MSG5)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static int allow_ed_cb_called = 0;
static int allow_early_data_cb(SSL *s, void *arg)
{
int *usecb = (int *)arg;
allow_ed_cb_called++;
if (*usecb == 1)
return 0;
return 1;
}
/*
* idx == 0: Standard early_data setup
* idx == 1: early_data setup using read_ahead
* usecb == 0: Don't use a custom early data callback
* usecb == 1: Use a custom early data callback and reject the early data
* usecb == 2: Use a custom early data callback and accept the early data
* confopt == 0: Configure anti-replay directly
* confopt == 1: Configure anti-replay using SSL_CONF
*/
static int test_early_data_replay_int(int idx, int usecb, int confopt)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
size_t readbytes, written;
unsigned char buf[20];
time_t timer;
allow_ed_cb_called = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
return 0;
if (usecb > 0) {
if (confopt == 0) {
SSL_CTX_set_options(sctx, SSL_OP_NO_ANTI_REPLAY);
} else {
SSL_CONF_CTX *confctx = SSL_CONF_CTX_new();
if (!TEST_ptr(confctx))
goto end;
SSL_CONF_CTX_set_flags(confctx, SSL_CONF_FLAG_FILE
| SSL_CONF_FLAG_SERVER);
SSL_CONF_CTX_set_ssl_ctx(confctx, sctx);
if (!TEST_int_eq(SSL_CONF_cmd(confctx, "Options", "-AntiReplay"),
2)) {
SSL_CONF_CTX_free(confctx);
goto end;
}
SSL_CONF_CTX_free(confctx);
}
SSL_CTX_set_allow_early_data_cb(sctx, allow_early_data_cb, &usecb);
}
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx,
SHA384_DIGEST_LENGTH)))
goto end;
/*
* The server is configured to accept early data. Create a connection to
* "use up" the ticket
*/
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl)))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, sess)))
goto end;
/* Write and read some early data */
timer = time(NULL);
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_size_t_eq(written, strlen(MSG1)))
goto end;
if (usecb <= 1) {
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
/*
* The ticket was reused, so the we should have rejected the
* early data
*/
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_REJECTED))
goto end;
} else {
/* In this case the callback decides to accept the early data */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_SUCCESS)) {
testresult = check_early_data_timeout(timer);
goto end;
}
if (!TEST_mem_eq(MSG1, strlen(MSG1), buf, readbytes)
/*
* Server will have sent its flight so client can now send
* end of early data and complete its half of the handshake
*/
|| !TEST_int_gt(SSL_connect(clientssl), 0)
|| !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED))
goto end;
}
/* Complete the connection */
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
|| !TEST_int_eq(SSL_session_reused(clientssl), (usecb > 0) ? 1 : 0)
|| !TEST_int_eq(allow_ed_cb_called, usecb > 0 ? 1 : 0))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static int test_early_data_replay(int idx)
{
int ret = 1, usecb, confopt;
for (usecb = 0; usecb < 3; usecb++) {
for (confopt = 0; confopt < 2; confopt++)
ret &= test_early_data_replay_int(idx, usecb, confopt);
}
return ret;
}
static const char *ciphersuites[] = {
"TLS_AES_128_CCM_8_SHA256",
"TLS_AES_128_GCM_SHA256",
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_CCM_SHA256",
#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
"TLS_CHACHA20_POLY1305_SHA256"
#endif
};
/*
* Helper function to test that a server attempting to read early data can
* handle a connection from a client where the early data should be skipped.
* testtype: 0 == No HRR
* testtype: 1 == HRR
* testtype: 2 == HRR, invalid early_data sent after HRR
* testtype: 3 == recv_max_early_data set to 0
*/
static int early_data_skip_helper(int testtype, int cipher, int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
unsigned char buf[20];
size_t readbytes, written;
if (is_fips && cipher == 4)
return 1;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
if (cipher == 0) {
SSL_CTX_set_security_level(sctx, 0);
SSL_CTX_set_security_level(cctx, 0);
}
if (!TEST_true(SSL_CTX_set_ciphersuites(sctx, ciphersuites[cipher]))
|| !TEST_true(SSL_CTX_set_ciphersuites(cctx, ciphersuites[cipher])))
goto end;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx,
cipher == 2 ? SHA384_DIGEST_LENGTH
: SHA256_DIGEST_LENGTH)))
goto end;
if (testtype == 1 || testtype == 2) {
/* Force an HRR to occur */
#if defined(OPENSSL_NO_EC)
if (!TEST_true(SSL_set1_groups_list(serverssl, "ffdhe3072")))
goto end;
#else
if (!TEST_true(SSL_set1_groups_list(serverssl, "P-384")))
goto end;
#endif
} else if (idx == 2) {
/*
* We force early_data rejection by ensuring the PSK identity is
* unrecognised
*/
srvid = "Dummy Identity";
} else {
/*
* Deliberately corrupt the creation time. We take 20 seconds off the
* time. It could be any value as long as it is not within tolerance.
* This should mean the ticket is rejected.
*/
if (!TEST_true(SSL_SESSION_set_time(sess, (long)(time(NULL) - 20))))
goto end;
}
if (testtype == 3
&& !TEST_true(SSL_set_recv_max_early_data(serverssl, 0)))
goto end;
/* Write some early data */
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_size_t_eq(written, strlen(MSG1)))
goto end;
/* Server should reject the early data */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_size_t_eq(readbytes, 0)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_REJECTED))
goto end;
switch (testtype) {
case 0:
/* Nothing to do */
break;
case 1:
/*
* Finish off the handshake. We perform the same writes and reads as
* further down but we expect them to fail due to the incomplete
* handshake.
*/
if (!TEST_false(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
|| !TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf),
&readbytes)))
goto end;
break;
case 2:
{
BIO *wbio = SSL_get_wbio(clientssl);
/* A record that will appear as bad early_data */
const unsigned char bad_early_data[] = {
0x17, 0x03, 0x03, 0x00, 0x01, 0x00
};
/*
* We force the client to attempt a write. This will fail because
* we're still in the handshake. It will cause the second
* ClientHello to be sent.
*/
if (!TEST_false(SSL_write_ex(clientssl, MSG2, strlen(MSG2),
&written)))
goto end;
/*
* Inject some early_data after the second ClientHello. This should
* cause the server to fail
*/
if (!TEST_true(BIO_write_ex(wbio, bad_early_data,
sizeof(bad_early_data), &written)))
goto end;
}
/* fallthrough */
case 3:
/*
* This client has sent more early_data than we are willing to skip
* (case 3) or sent invalid early_data (case 2) so the connection should
* abort.
*/
if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_SSL))
goto end;
/* Connection has failed - nothing more to do */
testresult = 1;
goto end;
default:
TEST_error("Invalid test type");
goto end;
}
ERR_clear_error();
/*
* Should be able to send normal data despite rejection of early data. The
* early_data should be skipped.
*/
if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
|| !TEST_size_t_eq(written, strlen(MSG2))
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_REJECTED)
|| !TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
/*
* Failure to decrypt early data records should not leave spurious errors
* on the error stack
*/
if (!TEST_long_eq(ERR_peek_error(), 0))
goto end;
testresult = 1;
end:
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_SESSION_free(sess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test that a server attempting to read early data can handle a connection
* from a client where the early data is not acceptable.
*/
static int test_early_data_skip(int idx)
{
return early_data_skip_helper(0,
idx % OSSL_NELEM(ciphersuites),
idx / OSSL_NELEM(ciphersuites));
}
/*
* Test that a server attempting to read early data can handle a connection
* from a client where an HRR occurs.
*/
static int test_early_data_skip_hrr(int idx)
{
return early_data_skip_helper(1,
idx % OSSL_NELEM(ciphersuites),
idx / OSSL_NELEM(ciphersuites));
}
/*
* Test that a server attempting to read early data can handle a connection
* from a client where an HRR occurs and correctly fails if early_data is sent
* after the HRR
*/
static int test_early_data_skip_hrr_fail(int idx)
{
return early_data_skip_helper(2,
idx % OSSL_NELEM(ciphersuites),
idx / OSSL_NELEM(ciphersuites));
}
/*
* Test that a server attempting to read early data will abort if it tries to
* skip over too much.
*/
static int test_early_data_skip_abort(int idx)
{
return early_data_skip_helper(3,
idx % OSSL_NELEM(ciphersuites),
idx / OSSL_NELEM(ciphersuites));
}
/*
* Test that a server attempting to read early data can handle a connection
* from a client that doesn't send any.
*/
static int test_early_data_not_sent(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
unsigned char buf[20];
size_t readbytes, written;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx,
SHA384_DIGEST_LENGTH)))
goto end;
/* Write some data - should block due to handshake with server */
SSL_set_connect_state(clientssl);
if (!TEST_false(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)))
goto end;
/* Server should detect that early data has not been sent */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_size_t_eq(readbytes, 0)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_NOT_SENT)
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_NOT_SENT))
goto end;
/* Continue writing the message we started earlier */
if (!TEST_true(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written))
|| !TEST_size_t_eq(written, strlen(MSG1))
|| !TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1))
|| !SSL_write_ex(serverssl, MSG2, strlen(MSG2), &written)
|| !TEST_size_t_eq(written, strlen(MSG2)))
goto end;
if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static const char *servalpn;
static int alpn_select_cb(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg)
{
unsigned int protlen = 0;
const unsigned char *prot;
for (prot = in; prot < in + inlen; prot += protlen) {
protlen = *prot++;
if (in + inlen < prot + protlen)
return SSL_TLSEXT_ERR_NOACK;
if (protlen == strlen(servalpn)
&& memcmp(prot, servalpn, protlen) == 0) {
*out = prot;
*outlen = protlen;
return SSL_TLSEXT_ERR_OK;
}
}
return SSL_TLSEXT_ERR_NOACK;
}
/* Test that a PSK can be used to send early_data */
static int test_early_data_psk(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
unsigned char alpnlist[] = {
0x08, 'g', 'o', 'o', 'd', 'a', 'l', 'p', 'n', 0x07, 'b', 'a', 'd', 'a',
'l', 'p', 'n'
};
#define GOODALPNLEN 9
#define BADALPNLEN 8
#define GOODALPN (alpnlist)
#define BADALPN (alpnlist + GOODALPNLEN)
int err = 0;
unsigned char buf[20];
size_t readbytes, written;
int readearlyres = SSL_READ_EARLY_DATA_SUCCESS, connectres = 1;
int edstatus = SSL_EARLY_DATA_ACCEPTED;
/* We always set this up with a final parameter of "2" for PSK */
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, 2,
SHA384_DIGEST_LENGTH)))
goto end;
servalpn = "goodalpn";
/*
* Note: There is no test for inconsistent SNI with late client detection.
* This is because servers do not acknowledge SNI even if they are using
* it in a resumption handshake - so it is not actually possible for a
* client to detect a problem.
*/
switch (idx) {
case 0:
/* Set inconsistent SNI (early client detection) */
err = SSL_R_INCONSISTENT_EARLY_DATA_SNI;
if (!TEST_true(SSL_SESSION_set1_hostname(sess, "goodhost"))
|| !TEST_true(SSL_set_tlsext_host_name(clientssl, "badhost")))
goto end;
break;
case 1:
/* Set inconsistent ALPN (early client detection) */
err = SSL_R_INCONSISTENT_EARLY_DATA_ALPN;
/* SSL_set_alpn_protos returns 0 for success and 1 for failure */
if (!TEST_true(SSL_SESSION_set1_alpn_selected(sess, GOODALPN,
GOODALPNLEN))
|| !TEST_false(SSL_set_alpn_protos(clientssl, BADALPN,
BADALPNLEN)))
goto end;
break;
case 2:
/*
* Set invalid protocol version. Technically this affects PSKs without
* early_data too, but we test it here because it is similar to the
* SNI/ALPN consistency tests.
*/
err = SSL_R_BAD_PSK;
if (!TEST_true(SSL_SESSION_set_protocol_version(sess, TLS1_2_VERSION)))
goto end;
break;
case 3:
/*
* Set inconsistent SNI (server side). In this case the connection
* will succeed and accept early_data. In TLSv1.3 on the server side SNI
* is associated with each handshake - not the session. Therefore it
* should not matter that we used a different server name last time.
*/
SSL_SESSION_free(serverpsk);
serverpsk = SSL_SESSION_dup(clientpsk);
if (!TEST_ptr(serverpsk)
|| !TEST_true(SSL_SESSION_set1_hostname(serverpsk, "badhost")))
goto end;
/* Fall through */
case 4:
/* Set consistent SNI */
if (!TEST_true(SSL_SESSION_set1_hostname(sess, "goodhost"))
|| !TEST_true(SSL_set_tlsext_host_name(clientssl, "goodhost"))
|| !TEST_true(SSL_CTX_set_tlsext_servername_callback(sctx,
hostname_cb)))
goto end;
break;
case 5:
/*
* Set inconsistent ALPN (server detected). In this case the connection
* will succeed but reject early_data.
*/
servalpn = "badalpn";
edstatus = SSL_EARLY_DATA_REJECTED;
readearlyres = SSL_READ_EARLY_DATA_FINISH;
/* Fall through */
case 6:
/*
* Set consistent ALPN.
* SSL_set_alpn_protos returns 0 for success and 1 for failure. It
* accepts a list of protos (each one length prefixed).
* SSL_set1_alpn_selected accepts a single protocol (not length
* prefixed)
*/
if (!TEST_true(SSL_SESSION_set1_alpn_selected(sess, GOODALPN + 1,
GOODALPNLEN - 1))
|| !TEST_false(SSL_set_alpn_protos(clientssl, GOODALPN,
GOODALPNLEN)))
goto end;
SSL_CTX_set_alpn_select_cb(sctx, alpn_select_cb, NULL);
break;
case 7:
/* Set inconsistent ALPN (late client detection) */
SSL_SESSION_free(serverpsk);
serverpsk = SSL_SESSION_dup(clientpsk);
if (!TEST_ptr(serverpsk)
|| !TEST_true(SSL_SESSION_set1_alpn_selected(clientpsk,
BADALPN + 1,
BADALPNLEN - 1))
|| !TEST_true(SSL_SESSION_set1_alpn_selected(serverpsk,
GOODALPN + 1,
GOODALPNLEN - 1))
|| !TEST_false(SSL_set_alpn_protos(clientssl, alpnlist,
sizeof(alpnlist))))
goto end;
SSL_CTX_set_alpn_select_cb(sctx, alpn_select_cb, NULL);
edstatus = SSL_EARLY_DATA_ACCEPTED;
readearlyres = SSL_READ_EARLY_DATA_SUCCESS;
/* SSL_connect() call should fail */
connectres = -1;
break;
default:
TEST_error("Bad test index");
goto end;
}
SSL_set_connect_state(clientssl);
if (err != 0) {
if (!TEST_false(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_int_eq(SSL_get_error(clientssl, 0), SSL_ERROR_SSL)
|| !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), err))
goto end;
} else {
time_t timer = time(NULL);
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written)))
goto end;
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes), readearlyres)) {
testresult = check_early_data_timeout(timer);
goto end;
}
if ((readearlyres == SSL_READ_EARLY_DATA_SUCCESS
&& !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1)))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl), edstatus)
|| !TEST_int_eq(SSL_connect(clientssl), connectres))
goto end;
}
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test TLSv1.3 PSK can be used to send early_data with all 5 ciphersuites
* idx == 0: Test with TLS1_3_RFC_AES_128_GCM_SHA256
* idx == 1: Test with TLS1_3_RFC_AES_256_GCM_SHA384
* idx == 2: Test with TLS1_3_RFC_CHACHA20_POLY1305_SHA256,
* idx == 3: Test with TLS1_3_RFC_AES_128_CCM_SHA256
* idx == 4: Test with TLS1_3_RFC_AES_128_CCM_8_SHA256
*/
static int test_early_data_psk_with_all_ciphers(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
unsigned char buf[20];
size_t readbytes, written;
const SSL_CIPHER *cipher;
time_t timer;
const char *cipher_str[] = {
TLS1_3_RFC_AES_128_GCM_SHA256,
TLS1_3_RFC_AES_256_GCM_SHA384,
# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
TLS1_3_RFC_CHACHA20_POLY1305_SHA256,
# else
NULL,
# endif
TLS1_3_RFC_AES_128_CCM_SHA256,
TLS1_3_RFC_AES_128_CCM_8_SHA256
};
const unsigned char *cipher_bytes[] = {
TLS13_AES_128_GCM_SHA256_BYTES,
TLS13_AES_256_GCM_SHA384_BYTES,
# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
TLS13_CHACHA20_POLY1305_SHA256_BYTES,
# else
NULL,
# endif
TLS13_AES_128_CCM_SHA256_BYTES,
TLS13_AES_128_CCM_8_SHA256_BYTES
};
if (cipher_str[idx] == NULL)
return 1;
/* Skip ChaCha20Poly1305 as currently FIPS module does not support it */
if (idx == 2 && is_fips == 1)
return 1;
/* We always set this up with a final parameter of "2" for PSK */
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, 2,
SHA384_DIGEST_LENGTH)))
goto end;
if (!TEST_true(SSL_set_ciphersuites(clientssl, cipher_str[idx]))
|| !TEST_true(SSL_set_ciphersuites(serverssl, cipher_str[idx])))
goto end;
/*
* 'setupearly_data_test' creates only one instance of SSL_SESSION
* and assigns to both client and server with incremented reference
* and the same instance is updated in 'sess'.
* So updating ciphersuite in 'sess' which will get reflected in
* PSK handshake using psk use sess and find sess cb.
*/
cipher = SSL_CIPHER_find(clientssl, cipher_bytes[idx]);
if (!TEST_ptr(cipher) || !TEST_true(SSL_SESSION_set_cipher(sess, cipher)))
goto end;
SSL_set_connect_state(clientssl);
timer = time(NULL);
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written)))
goto end;
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_SUCCESS)) {
testresult = check_early_data_timeout(timer);
goto end;
}
if (!TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED)
|| !TEST_int_eq(SSL_connect(clientssl), 1)
|| !TEST_int_eq(SSL_accept(serverssl), 1))
goto end;
/* Send some normal data from client to server */
if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
|| !TEST_size_t_eq(written, strlen(MSG2)))
goto end;
if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
if (clientssl != NULL)
SSL_shutdown(clientssl);
if (serverssl != NULL)
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test that a server that doesn't try to read early data can handle a
* client sending some.
*/
static int test_early_data_not_expected(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
unsigned char buf[20];
size_t readbytes, written;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, idx,
SHA384_DIGEST_LENGTH)))
goto end;
/* Write some early data */
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written)))
goto end;
/*
* Server should skip over early data and then block waiting for client to
* continue handshake
*/
if (!TEST_int_le(SSL_accept(serverssl), 0)
|| !TEST_int_gt(SSL_connect(clientssl), 0)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_REJECTED)
|| !TEST_int_gt(SSL_accept(serverssl), 0)
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_REJECTED))
goto end;
/* Send some normal data from client to server */
if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
|| !TEST_size_t_eq(written, strlen(MSG2)))
goto end;
if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
# ifndef OPENSSL_NO_TLS1_2
/*
* Test that a server attempting to read early data can handle a connection
* from a TLSv1.2 client.
*/
static int test_early_data_tls1_2(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
unsigned char buf[20];
size_t readbytes, written;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, NULL, idx,
SHA384_DIGEST_LENGTH)))
goto end;
/* Write some data - should block due to handshake with server */
SSL_set_max_proto_version(clientssl, TLS1_2_VERSION);
SSL_set_connect_state(clientssl);
if (!TEST_false(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)))
goto end;
/*
* Server should do TLSv1.2 handshake. First it will block waiting for more
* messages from client after ServerDone. Then SSL_read_early_data should
* finish and detect that early data has not been sent
*/
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_ERROR))
goto end;
/*
* Continue writing the message we started earlier. Will still block waiting
* for the CCS/Finished from server
*/
if (!TEST_false(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written))
|| !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_FINISH)
|| !TEST_size_t_eq(readbytes, 0)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_NOT_SENT))
goto end;
/* Continue writing the message we started earlier */
if (!TEST_true(SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written))
|| !TEST_size_t_eq(written, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(clientssl),
SSL_EARLY_DATA_NOT_SENT)
|| !TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1))
|| !TEST_true(SSL_write_ex(serverssl, MSG2, strlen(MSG2), &written))
|| !TEST_size_t_eq(written, strlen(MSG2))
|| !SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)
|| !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
# endif /* OPENSSL_NO_TLS1_2 */
/*
* Test configuring the TLSv1.3 ciphersuites
*
* Test 0: Set a default ciphersuite in the SSL_CTX (no explicit cipher_list)
* Test 1: Set a non-default ciphersuite in the SSL_CTX (no explicit cipher_list)
* Test 2: Set a default ciphersuite in the SSL (no explicit cipher_list)
* Test 3: Set a non-default ciphersuite in the SSL (no explicit cipher_list)
* Test 4: Set a default ciphersuite in the SSL_CTX (SSL_CTX cipher_list)
* Test 5: Set a non-default ciphersuite in the SSL_CTX (SSL_CTX cipher_list)
* Test 6: Set a default ciphersuite in the SSL (SSL_CTX cipher_list)
* Test 7: Set a non-default ciphersuite in the SSL (SSL_CTX cipher_list)
* Test 8: Set a default ciphersuite in the SSL (SSL cipher_list)
* Test 9: Set a non-default ciphersuite in the SSL (SSL cipher_list)
*/
static int test_set_ciphersuite(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey))
|| !TEST_true(SSL_CTX_set_ciphersuites(sctx,
"TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256")))
goto end;
if (idx >=4 && idx <= 7) {
/* SSL_CTX explicit cipher list */
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "AES256-GCM-SHA384")))
goto end;
}
if (idx == 0 || idx == 4) {
/* Default ciphersuite */
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx,
"TLS_AES_128_GCM_SHA256")))
goto end;
} else if (idx == 1 || idx == 5) {
/* Non default ciphersuite */
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx,
"TLS_AES_128_CCM_SHA256")))
goto end;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
if (idx == 8 || idx == 9) {
/* SSL explicit cipher list */
if (!TEST_true(SSL_set_cipher_list(clientssl, "AES256-GCM-SHA384")))
goto end;
}
if (idx == 2 || idx == 6 || idx == 8) {
/* Default ciphersuite */
if (!TEST_true(SSL_set_ciphersuites(clientssl,
"TLS_AES_128_GCM_SHA256")))
goto end;
} else if (idx == 3 || idx == 7 || idx == 9) {
/* Non default ciphersuite */
if (!TEST_true(SSL_set_ciphersuites(clientssl,
"TLS_AES_128_CCM_SHA256")))
goto end;
}
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static int test_ciphersuite_change(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
SSL_SESSION *clntsess = NULL;
int testresult = 0;
const SSL_CIPHER *aes_128_gcm_sha256 = NULL;
/* Create a session based on SHA-256 */
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey))
|| !TEST_true(SSL_CTX_set_ciphersuites(sctx,
"TLS_AES_128_GCM_SHA256:"
"TLS_AES_256_GCM_SHA384:"
"TLS_AES_128_CCM_SHA256"))
|| !TEST_true(SSL_CTX_set_ciphersuites(cctx,
"TLS_AES_128_GCM_SHA256"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
clntsess = SSL_get1_session(clientssl);
/* Save for later */
aes_128_gcm_sha256 = SSL_SESSION_get0_cipher(clntsess);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* Check we can resume a session with a different SHA-256 ciphersuite */
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx,
"TLS_AES_128_CCM_SHA256"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl)))
goto end;
SSL_SESSION_free(clntsess);
clntsess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/*
* Check attempting to resume a SHA-256 session with no SHA-256 ciphersuites
* succeeds but does not resume.
*/
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx, "TLS_AES_256_GCM_SHA384"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_SSL))
|| !TEST_false(SSL_session_reused(clientssl)))
goto end;
SSL_SESSION_free(clntsess);
clntsess = NULL;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* Create a session based on SHA384 */
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx, "TLS_AES_256_GCM_SHA384"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
clntsess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx,
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384"))
|| !TEST_true(SSL_CTX_set_ciphersuites(sctx,
"TLS_AES_256_GCM_SHA384"))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
/*
* We use SSL_ERROR_WANT_READ below so that we can pause the
* connection after the initial ClientHello has been sent to
* enable us to make some session changes.
*/
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ)))
goto end;
/* Trick the client into thinking this session is for a different digest */
clntsess->cipher = aes_128_gcm_sha256;
clntsess->cipher_id = clntsess->cipher->id;
/*
* Continue the previously started connection. Server has selected a SHA-384
* ciphersuite, but client thinks the session is for SHA-256, so it should
* bail out.
*/
if (!TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_SSL))
|| !TEST_int_eq(ERR_GET_REASON(ERR_get_error()),
SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED))
goto end;
testresult = 1;
end:
SSL_SESSION_free(clntsess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test TLSv1.3 Key exchange
* Test 0 = Test all ECDHE Key exchange with TLSv1.3 client and server
* Test 1 = Test NID_X9_62_prime256v1 with TLSv1.3 client and server
* Test 2 = Test NID_secp384r1 with TLSv1.3 client and server
* Test 3 = Test NID_secp521r1 with TLSv1.3 client and server
* Test 4 = Test NID_X25519 with TLSv1.3 client and server
* Test 5 = Test NID_X448 with TLSv1.3 client and server
* Test 6 = Test all FFDHE Key exchange with TLSv1.3 client and server
* Test 7 = Test NID_ffdhe2048 with TLSv1.3 client and server
* Test 8 = Test NID_ffdhe3072 with TLSv1.3 client and server
* Test 9 = Test NID_ffdhe4096 with TLSv1.3 client and server
* Test 10 = Test NID_ffdhe6144 with TLSv1.3 client and server
* Test 11 = Test NID_ffdhe8192 with TLSv1.3 client and server
* Test 12 = Test all ECDHE with TLSv1.2 client and server
* Test 13 = Test all FFDHE with TLSv1.2 client and server
*/
# ifndef OPENSSL_NO_EC
static int ecdhe_kexch_groups[] = {NID_X9_62_prime256v1, NID_secp384r1,
NID_secp521r1, NID_X25519, NID_X448};
# endif
# ifndef OPENSSL_NO_DH
static int ffdhe_kexch_groups[] = {NID_ffdhe2048, NID_ffdhe3072, NID_ffdhe4096,
NID_ffdhe6144, NID_ffdhe8192};
# endif
static int test_key_exchange(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
int kexch_alg;
int *kexch_groups = &kexch_alg;
int kexch_groups_size = 1;
int max_version = TLS1_3_VERSION;
char *kexch_name0 = NULL;
switch (idx) {
# ifndef OPENSSL_NO_EC
# ifndef OPENSSL_NO_TLS1_2
case 12:
max_version = TLS1_2_VERSION;
# endif
/* Fall through */
case 0:
kexch_groups = ecdhe_kexch_groups;
kexch_groups_size = OSSL_NELEM(ecdhe_kexch_groups);
kexch_name0 = "secp256r1";
break;
case 1:
kexch_alg = NID_X9_62_prime256v1;
kexch_name0 = "secp256r1";
break;
case 2:
kexch_alg = NID_secp384r1;
kexch_name0 = "secp384r1";
break;
case 3:
kexch_alg = NID_secp521r1;
kexch_name0 = "secp521r1";
break;
case 4:
if (is_fips)
return TEST_skip("X25519 might not be supported by fips provider.");
kexch_alg = NID_X25519;
kexch_name0 = "x25519";
break;
case 5:
if (is_fips)
return TEST_skip("X448 might not be supported by fips provider.");
kexch_alg = NID_X448;
kexch_name0 = "x448";
break;
# endif
# ifndef OPENSSL_NO_DH
# ifndef OPENSSL_NO_TLS1_2
case 13:
max_version = TLS1_2_VERSION;
kexch_name0 = "ffdhe2048";
# endif
/* Fall through */
case 6:
kexch_groups = ffdhe_kexch_groups;
kexch_groups_size = OSSL_NELEM(ffdhe_kexch_groups);
kexch_name0 = "ffdhe2048";
break;
case 7:
kexch_alg = NID_ffdhe2048;
kexch_name0 = "ffdhe2048";
break;
case 8:
kexch_alg = NID_ffdhe3072;
kexch_name0 = "ffdhe3072";
break;
case 9:
kexch_alg = NID_ffdhe4096;
kexch_name0 = "ffdhe4096";
break;
case 10:
kexch_alg = NID_ffdhe6144;
kexch_name0 = "ffdhe6144";
break;
case 11:
kexch_alg = NID_ffdhe8192;
kexch_name0 = "ffdhe8192";
break;
# endif
default:
/* We're skipping this test */
return 1;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION,
max_version, &sctx, &cctx, cert,
privkey)))
goto end;
if (!TEST_true(SSL_CTX_set_ciphersuites(sctx,
TLS1_3_RFC_AES_128_GCM_SHA256)))
goto end;
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx,
TLS1_3_RFC_AES_128_GCM_SHA256)))
goto end;
if (!TEST_true(SSL_CTX_set_cipher_list(sctx,
TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":"
TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256))
|| !TEST_true(SSL_CTX_set_dh_auto(sctx, 1)))
goto end;
/*
* Must include an EC ciphersuite so that we send supported groups in
* TLSv1.2
*/
# ifndef OPENSSL_NO_TLS1_2
if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":"
TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256)))
goto end;
# endif
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(SSL_set1_groups(serverssl, kexch_groups, kexch_groups_size))
|| !TEST_true(SSL_set1_groups(clientssl, kexch_groups, kexch_groups_size)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
/*
* If Handshake succeeds the negotiated kexch alg should be the first one in
* configured, except in the case of FFDHE groups (idx 13), which are
* TLSv1.3 only so we expect no shared group to exist.
*/
if (!TEST_int_eq(SSL_get_shared_group(serverssl, 0),
idx == 13 ? 0 : kexch_groups[0]))
goto end;
if (!TEST_str_eq(SSL_group_to_name(serverssl, kexch_groups[0]),
kexch_name0))
goto end;
/* We don't implement RFC 7919 named groups for TLS 1.2. */
if (idx != 13) {
if (!TEST_int_eq(SSL_get_negotiated_group(serverssl), kexch_groups[0]))
goto end;
if (!TEST_int_eq(SSL_get_negotiated_group(clientssl), kexch_groups[0]))
goto end;
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
# if !defined(OPENSSL_NO_TLS1_2) \
&& !defined(OPENSSL_NO_EC) \
&& !defined(OPENSSL_NO_DH)
static int set_ssl_groups(SSL *serverssl, SSL *clientssl, int clientmulti,
int isecdhe, int idx)
{
int kexch_alg;
int *kexch_groups = &kexch_alg;
int numec, numff;
numec = OSSL_NELEM(ecdhe_kexch_groups);
numff = OSSL_NELEM(ffdhe_kexch_groups);
if (isecdhe)
kexch_alg = ecdhe_kexch_groups[idx];
else
kexch_alg = ffdhe_kexch_groups[idx];
if (clientmulti) {
if (!TEST_true(SSL_set1_groups(serverssl, kexch_groups, 1)))
return 0;
if (isecdhe) {
if (!TEST_true(SSL_set1_groups(clientssl, ecdhe_kexch_groups,
numec)))
return 0;
} else {
if (!TEST_true(SSL_set1_groups(clientssl, ffdhe_kexch_groups,
numff)))
return 0;
}
} else {
if (!TEST_true(SSL_set1_groups(clientssl, kexch_groups, 1)))
return 0;
if (isecdhe) {
if (!TEST_true(SSL_set1_groups(serverssl, ecdhe_kexch_groups,
numec)))
return 0;
} else {
if (!TEST_true(SSL_set1_groups(serverssl, ffdhe_kexch_groups,
numff)))
return 0;
}
}
return 1;
}
/*-
* Test the SSL_get_negotiated_group() API across a battery of scenarios.
* Run through both the ECDHE and FFDHE group lists used in the previous
* test, for both TLS 1.2 and TLS 1.3, negotiating each group in turn,
* confirming the expected result; then perform a resumption handshake
* while offering the same group list, and another resumption handshake
* offering a different group list. The returned value should be the
* negotiated group for the initial handshake; for TLS 1.3 resumption
* handshakes the returned value will be negotiated on the resumption
* handshake itself, but for TLS 1.2 resumption handshakes the value will
* be cached in the session from the original handshake, regardless of what
* was offered in the resumption ClientHello.
*
* Using E for the number of EC groups and F for the number of FF groups:
* E tests of ECDHE with TLS 1.3, server only has one group
* F tests of FFDHE with TLS 1.3, server only has one group
* E tests of ECDHE with TLS 1.2, server only has one group
* F tests of FFDHE with TLS 1.2, server only has one group
* E tests of ECDHE with TLS 1.3, client sends only one group
* F tests of FFDHE with TLS 1.3, client sends only one group
* E tests of ECDHE with TLS 1.2, client sends only one group
* F tests of FFDHE with TLS 1.2, client sends only one group
*/
static int test_negotiated_group(int idx)
{
int clientmulti, istls13, isecdhe, numec, numff, numgroups;
int expectednid;
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
SSL_SESSION *origsess = NULL;
int testresult = 0;
int kexch_alg;
int max_version = TLS1_3_VERSION;
numec = OSSL_NELEM(ecdhe_kexch_groups);
numff = OSSL_NELEM(ffdhe_kexch_groups);
numgroups = numec + numff;
clientmulti = (idx < 2 * numgroups);
idx = idx % (2 * numgroups);
istls13 = (idx < numgroups);
idx = idx % numgroups;
isecdhe = (idx < numec);
if (!isecdhe)
idx -= numec;
/* Now 'idx' is an index into ecdhe_kexch_groups or ffdhe_kexch_groups */
if (isecdhe)
kexch_alg = ecdhe_kexch_groups[idx];
else
kexch_alg = ffdhe_kexch_groups[idx];
/* We expect nothing for the unimplemented TLS 1.2 FFDHE named groups */
if (!istls13 && !isecdhe)
expectednid = NID_undef;
else
expectednid = kexch_alg;
if (is_fips && (kexch_alg == NID_X25519 || kexch_alg == NID_X448))
return TEST_skip("X25519 and X448 might not be available in fips provider.");
if (!istls13)
max_version = TLS1_2_VERSION;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION,
max_version, &sctx, &cctx, cert,
privkey)))
goto end;
/*
* Force (EC)DHE ciphers for TLS 1.2.
* Be sure to enable auto tmp DH so that FFDHE can succeed.
*/
if (!TEST_true(SSL_CTX_set_cipher_list(sctx,
TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":"
TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256))
|| !TEST_true(SSL_CTX_set_dh_auto(sctx, 1)))
goto end;
if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":"
TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256)))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(set_ssl_groups(serverssl, clientssl, clientmulti, isecdhe,
idx)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
/* Initial handshake; always the configured one */
if (!TEST_uint_eq(SSL_get_negotiated_group(clientssl), expectednid)
|| !TEST_uint_eq(SSL_get_negotiated_group(serverssl), expectednid))
goto end;
if (!TEST_ptr((origsess = SSL_get1_session(clientssl))))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* First resumption attempt; use the same config as initial handshake */
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, origsess))
|| !TEST_true(set_ssl_groups(serverssl, clientssl, clientmulti,
isecdhe, idx)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl)))
goto end;
/* Still had better agree, since nothing changed... */
if (!TEST_uint_eq(SSL_get_negotiated_group(clientssl), expectednid)
|| !TEST_uint_eq(SSL_get_negotiated_group(serverssl), expectednid))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/*-
* Second resumption attempt
* The party that picks one group changes it, which we effectuate by
* changing 'idx' and updating what we expect.
*/
if (idx == 0)
idx = 1;
else
idx--;
if (istls13) {
if (isecdhe)
expectednid = ecdhe_kexch_groups[idx];
else
expectednid = ffdhe_kexch_groups[idx];
/* Verify that we are changing what we expect. */
if (!TEST_int_ne(expectednid, kexch_alg))
goto end;
} else {
/* TLS 1.2 only supports named groups for ECDHE. */
if (isecdhe)
expectednid = kexch_alg;
else
expectednid = 0;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, origsess))
|| !TEST_true(set_ssl_groups(serverssl, clientssl, clientmulti,
isecdhe, idx)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl)))
goto end;
/* Check that we get what we expected */
if (!TEST_uint_eq(SSL_get_negotiated_group(clientssl), expectednid)
|| !TEST_uint_eq(SSL_get_negotiated_group(serverssl), expectednid))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
SSL_SESSION_free(origsess);
return testresult;
}
# endif /* !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_DH) */
/*
* Test TLSv1.3 Cipher Suite
* Test 0 = Set TLS1.3 cipher on context
* Test 1 = Set TLS1.3 cipher on SSL
* Test 2 = Set TLS1.3 and TLS1.2 cipher on context
* Test 3 = Set TLS1.3 and TLS1.2 cipher on SSL
*/
static int test_tls13_ciphersuite(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
static const struct {
const char *ciphername;
int fipscapable;
} t13_ciphers[] = {
{ TLS1_3_RFC_AES_128_GCM_SHA256, 1 },
{ TLS1_3_RFC_AES_256_GCM_SHA384, 1 },
{ TLS1_3_RFC_AES_128_CCM_SHA256, 1 },
# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
{ TLS1_3_RFC_CHACHA20_POLY1305_SHA256, 0 },
{ TLS1_3_RFC_AES_256_GCM_SHA384
":" TLS1_3_RFC_CHACHA20_POLY1305_SHA256, 0 },
# endif
{ TLS1_3_RFC_AES_128_CCM_8_SHA256 ":" TLS1_3_RFC_AES_128_CCM_SHA256, 1 }
};
const char *t13_cipher = NULL;
const char *t12_cipher = NULL;
const char *negotiated_scipher;
const char *negotiated_ccipher;
int set_at_ctx = 0;
int set_at_ssl = 0;
int testresult = 0;
int max_ver;
size_t i;
switch (idx) {
case 0:
set_at_ctx = 1;
break;
case 1:
set_at_ssl = 1;
break;
case 2:
set_at_ctx = 1;
t12_cipher = TLS1_TXT_RSA_WITH_AES_128_SHA256;
break;
case 3:
set_at_ssl = 1;
t12_cipher = TLS1_TXT_RSA_WITH_AES_128_SHA256;
break;
}
for (max_ver = TLS1_2_VERSION; max_ver <= TLS1_3_VERSION; max_ver++) {
# ifdef OPENSSL_NO_TLS1_2
if (max_ver == TLS1_2_VERSION)
continue;
# endif
for (i = 0; i < OSSL_NELEM(t13_ciphers); i++) {
if (is_fips && !t13_ciphers[i].fipscapable)
continue;
t13_cipher = t13_ciphers[i].ciphername;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION, max_ver,
&sctx, &cctx, cert, privkey)))
goto end;
if (set_at_ctx) {
if (!TEST_true(SSL_CTX_set_ciphersuites(sctx, t13_cipher))
|| !TEST_true(SSL_CTX_set_ciphersuites(cctx, t13_cipher)))
goto end;
if (t12_cipher != NULL) {
if (!TEST_true(SSL_CTX_set_cipher_list(sctx, t12_cipher))
|| !TEST_true(SSL_CTX_set_cipher_list(cctx,
t12_cipher)))
goto end;
}
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
if (set_at_ssl) {
if (!TEST_true(SSL_set_ciphersuites(serverssl, t13_cipher))
|| !TEST_true(SSL_set_ciphersuites(clientssl, t13_cipher)))
goto end;
if (t12_cipher != NULL) {
if (!TEST_true(SSL_set_cipher_list(serverssl, t12_cipher))
|| !TEST_true(SSL_set_cipher_list(clientssl,
t12_cipher)))
goto end;
}
}
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
negotiated_scipher = SSL_CIPHER_get_name(SSL_get_current_cipher(
serverssl));
negotiated_ccipher = SSL_CIPHER_get_name(SSL_get_current_cipher(
clientssl));
if (!TEST_str_eq(negotiated_scipher, negotiated_ccipher))
goto end;
/*
* TEST_strn_eq is used below because t13_cipher can contain
* multiple ciphersuites
*/
if (max_ver == TLS1_3_VERSION
&& !TEST_strn_eq(t13_cipher, negotiated_scipher,
strlen(negotiated_scipher)))
goto end;
# ifndef OPENSSL_NO_TLS1_2
/* Below validation is not done when t12_cipher is NULL */
if (max_ver == TLS1_2_VERSION && t12_cipher != NULL
&& !TEST_str_eq(t12_cipher, negotiated_scipher))
goto end;
# endif
SSL_free(serverssl);
serverssl = NULL;
SSL_free(clientssl);
clientssl = NULL;
SSL_CTX_free(sctx);
sctx = NULL;
SSL_CTX_free(cctx);
cctx = NULL;
}
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test TLSv1.3 PSKs
* Test 0 = Test new style callbacks
* Test 1 = Test both new and old style callbacks
* Test 2 = Test old style callbacks
* Test 3 = Test old style callbacks with no certificate
*/
static int test_tls13_psk(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
const SSL_CIPHER *cipher = NULL;
const unsigned char key[] = {
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, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
};
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, idx == 3 ? NULL : cert,
idx == 3 ? NULL : privkey)))
goto end;
if (idx != 3) {
/*
* We use a ciphersuite with SHA256 to ease testing old style PSK
* callbacks which will always default to SHA256. This should not be
* necessary if we have no cert/priv key. In that case the server should
* prefer SHA256 automatically.
*/
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx,
"TLS_AES_128_GCM_SHA256")))
goto end;
} else {
/*
* As noted above the server should prefer SHA256 automatically. However
* we are careful not to offer TLS_CHACHA20_POLY1305_SHA256 so this same
* code works even if we are testing with only the FIPS provider loaded.
*/
if (!TEST_true(SSL_CTX_set_ciphersuites(cctx,
"TLS_AES_256_GCM_SHA384:"
"TLS_AES_128_GCM_SHA256")))
goto end;
}
/*
* Test 0: New style callbacks only
* Test 1: New and old style callbacks (only the new ones should be used)
* Test 2: Old style callbacks only
*/
if (idx == 0 || idx == 1) {
SSL_CTX_set_psk_use_session_callback(cctx, use_session_cb);
SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb);
}
#ifndef OPENSSL_NO_PSK
if (idx >= 1) {
SSL_CTX_set_psk_client_callback(cctx, psk_client_cb);
SSL_CTX_set_psk_server_callback(sctx, psk_server_cb);
}
#endif
srvid = pskid;
use_session_cb_cnt = 0;
find_session_cb_cnt = 0;
psk_client_cb_cnt = 0;
psk_server_cb_cnt = 0;
if (idx != 3) {
/*
* Check we can create a connection if callback decides not to send a
* PSK
*/
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(SSL_session_reused(clientssl))
|| !TEST_false(SSL_session_reused(serverssl)))
goto end;
if (idx == 0 || idx == 1) {
if (!TEST_true(use_session_cb_cnt == 1)
|| !TEST_true(find_session_cb_cnt == 0)
/*
* If no old style callback then below should be 0
* otherwise 1
*/
|| !TEST_true(psk_client_cb_cnt == idx)
|| !TEST_true(psk_server_cb_cnt == 0))
goto end;
} else {
if (!TEST_true(use_session_cb_cnt == 0)
|| !TEST_true(find_session_cb_cnt == 0)
|| !TEST_true(psk_client_cb_cnt == 1)
|| !TEST_true(psk_server_cb_cnt == 0))
goto end;
}
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
use_session_cb_cnt = psk_client_cb_cnt = 0;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
/* Create the PSK */
cipher = SSL_CIPHER_find(clientssl, TLS13_AES_128_GCM_SHA256_BYTES);
clientpsk = SSL_SESSION_new();
if (!TEST_ptr(clientpsk)
|| !TEST_ptr(cipher)
|| !TEST_true(SSL_SESSION_set1_master_key(clientpsk, key,
sizeof(key)))
|| !TEST_true(SSL_SESSION_set_cipher(clientpsk, cipher))
|| !TEST_true(SSL_SESSION_set_protocol_version(clientpsk,
TLS1_3_VERSION))
|| !TEST_true(SSL_SESSION_up_ref(clientpsk)))
goto end;
serverpsk = clientpsk;
/* Check we can create a connection and the PSK is used */
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl))
|| !TEST_true(SSL_session_reused(serverssl)))
goto end;
if (idx == 0 || idx == 1) {
if (!TEST_true(use_session_cb_cnt == 1)
|| !TEST_true(find_session_cb_cnt == 1)
|| !TEST_true(psk_client_cb_cnt == 0)
|| !TEST_true(psk_server_cb_cnt == 0))
goto end;
} else {
if (!TEST_true(use_session_cb_cnt == 0)
|| !TEST_true(find_session_cb_cnt == 0)
|| !TEST_true(psk_client_cb_cnt == 1)
|| !TEST_true(psk_server_cb_cnt == 1))
goto end;
}
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
use_session_cb_cnt = find_session_cb_cnt = 0;
psk_client_cb_cnt = psk_server_cb_cnt = 0;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
/* Force an HRR */
#if defined(OPENSSL_NO_EC)
if (!TEST_true(SSL_set1_groups_list(serverssl, "ffdhe3072")))
goto end;
#else
if (!TEST_true(SSL_set1_groups_list(serverssl, "P-384")))
goto end;
#endif
/*
* Check we can create a connection, the PSK is used and the callbacks are
* called twice.
*/
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl))
|| !TEST_true(SSL_session_reused(serverssl)))
goto end;
if (idx == 0 || idx == 1) {
if (!TEST_true(use_session_cb_cnt == 2)
|| !TEST_true(find_session_cb_cnt == 2)
|| !TEST_true(psk_client_cb_cnt == 0)
|| !TEST_true(psk_server_cb_cnt == 0))
goto end;
} else {
if (!TEST_true(use_session_cb_cnt == 0)
|| !TEST_true(find_session_cb_cnt == 0)
|| !TEST_true(psk_client_cb_cnt == 2)
|| !TEST_true(psk_server_cb_cnt == 2))
goto end;
}
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
use_session_cb_cnt = find_session_cb_cnt = 0;
psk_client_cb_cnt = psk_server_cb_cnt = 0;
if (idx != 3) {
/*
* Check that if the server rejects the PSK we can still connect, but with
* a full handshake
*/
srvid = "Dummy Identity";
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(SSL_session_reused(clientssl))
|| !TEST_false(SSL_session_reused(serverssl)))
goto end;
if (idx == 0 || idx == 1) {
if (!TEST_true(use_session_cb_cnt == 1)
|| !TEST_true(find_session_cb_cnt == 1)
|| !TEST_true(psk_client_cb_cnt == 0)
/*
* If no old style callback then below should be 0
* otherwise 1
*/
|| !TEST_true(psk_server_cb_cnt == idx))
goto end;
} else {
if (!TEST_true(use_session_cb_cnt == 0)
|| !TEST_true(find_session_cb_cnt == 0)
|| !TEST_true(psk_client_cb_cnt == 1)
|| !TEST_true(psk_server_cb_cnt == 1))
goto end;
}
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
}
testresult = 1;
end:
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static unsigned char cookie_magic_value[] = "cookie magic";
static int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
unsigned int *cookie_len)
{
/*
* Not suitable as a real cookie generation function but good enough for
* testing!
*/
memcpy(cookie, cookie_magic_value, sizeof(cookie_magic_value) - 1);
*cookie_len = sizeof(cookie_magic_value) - 1;
return 1;
}
static int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
unsigned int cookie_len)
{
if (cookie_len == sizeof(cookie_magic_value) - 1
&& memcmp(cookie, cookie_magic_value, cookie_len) == 0)
return 1;
return 0;
}
static 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;
}
static int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
size_t cookie_len)
{
return verify_cookie_callback(ssl, cookie, cookie_len);
}
static int test_stateless(void)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
/* The arrival of CCS messages can confuse the test */
SSL_CTX_clear_options(cctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
/* Send the first ClientHello */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ))
/*
* This should fail with a -1 return because we have no callbacks
* set up
*/
|| !TEST_int_eq(SSL_stateless(serverssl), -1))
goto end;
/* Fatal error so abandon the connection from this client */
SSL_free(clientssl);
clientssl = NULL;
/* Set up the cookie generation and verification callbacks */
SSL_CTX_set_stateless_cookie_generate_cb(sctx, generate_stateless_cookie_callback);
SSL_CTX_set_stateless_cookie_verify_cb(sctx, verify_stateless_cookie_callback);
/*
* Create a new connection from the client (we can reuse the server SSL
* object).
*/
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
/* Send the first ClientHello */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ))
/* This should fail because there is no cookie */
|| !TEST_int_eq(SSL_stateless(serverssl), 0))
goto end;
/* Abandon the connection from this client */
SSL_free(clientssl);
clientssl = NULL;
/*
* Now create a connection from a new client but with the same server SSL
* object
*/
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
/* Send the first ClientHello */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ))
/* This should fail because there is no cookie */
|| !TEST_int_eq(SSL_stateless(serverssl), 0)
/* Send the second ClientHello */
|| !TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_WANT_READ))
/* This should succeed because a cookie is now present */
|| !TEST_int_eq(SSL_stateless(serverssl), 1)
/* Complete the connection */
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif /* OSSL_NO_USABLE_TLS1_3 */
static int clntaddoldcb = 0;
static int clntparseoldcb = 0;
static int srvaddoldcb = 0;
static int srvparseoldcb = 0;
static int clntaddnewcb = 0;
static int clntparsenewcb = 0;
static int srvaddnewcb = 0;
static int srvparsenewcb = 0;
static int snicb = 0;
#define TEST_EXT_TYPE1 0xff00
static int old_add_cb(SSL *s, unsigned int ext_type, const unsigned char **out,
size_t *outlen, int *al, void *add_arg)
{
int *server = (int *)add_arg;
unsigned char *data;
if (SSL_is_server(s))
srvaddoldcb++;
else
clntaddoldcb++;
if (*server != SSL_is_server(s)
|| (data = OPENSSL_malloc(sizeof(*data))) == NULL)
return -1;
*data = 1;
*out = data;
*outlen = sizeof(char);
return 1;
}
static void old_free_cb(SSL *s, unsigned int ext_type, const unsigned char *out,
void *add_arg)
{
OPENSSL_free((unsigned char *)out);
}
static int old_parse_cb(SSL *s, unsigned int ext_type, const unsigned char *in,
size_t inlen, int *al, void *parse_arg)
{
int *server = (int *)parse_arg;
if (SSL_is_server(s))
srvparseoldcb++;
else
clntparseoldcb++;
if (*server != SSL_is_server(s)
|| inlen != sizeof(char)
|| *in != 1)
return -1;
return 1;
}
static int new_add_cb(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)
{
int *server = (int *)add_arg;
unsigned char *data;
if (SSL_is_server(s))
srvaddnewcb++;
else
clntaddnewcb++;
if (*server != SSL_is_server(s)
|| (data = OPENSSL_malloc(sizeof(*data))) == NULL)
return -1;
*data = 1;
*out = data;
*outlen = sizeof(*data);
return 1;
}
static void new_free_cb(SSL *s, unsigned int ext_type, unsigned int context,
const unsigned char *out, void *add_arg)
{
OPENSSL_free((unsigned char *)out);
}
static int new_parse_cb(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)
{
int *server = (int *)parse_arg;
if (SSL_is_server(s))
srvparsenewcb++;
else
clntparsenewcb++;
if (*server != SSL_is_server(s)
|| inlen != sizeof(char) || *in != 1)
return -1;
return 1;
}
static int sni_cb(SSL *s, int *al, void *arg)
{
SSL_CTX *ctx = (SSL_CTX *)arg;
if (SSL_set_SSL_CTX(s, ctx) == NULL) {
*al = SSL_AD_INTERNAL_ERROR;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
snicb++;
return SSL_TLSEXT_ERR_OK;
}
static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
return 1;
}
/*
* Custom call back tests.
* Test 0: Old style callbacks in TLSv1.2
* Test 1: New style callbacks in TLSv1.2
* Test 2: New style callbacks in TLSv1.2 with SNI
* Test 3: New style callbacks in TLSv1.3. Extensions in CH and EE
* Test 4: New style callbacks in TLSv1.3. Extensions in CH, SH, EE, Cert + NST
* Test 5: New style callbacks in TLSv1.3. Extensions in CR + Client Cert
*/
static int test_custom_exts(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
static int server = 1;
static int client = 0;
SSL_SESSION *sess = NULL;
unsigned int context;
#if defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3)
/* Skip tests for TLSv1.2 and below in this case */
if (tst < 3)
return 1;
#endif
/* Reset callback counters */
clntaddoldcb = clntparseoldcb = srvaddoldcb = srvparseoldcb = 0;
clntaddnewcb = clntparsenewcb = srvaddnewcb = srvparsenewcb = 0;
snicb = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
if (tst == 2
&& !TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), NULL,
TLS1_VERSION, 0,
&sctx2, NULL, cert, privkey)))
goto end;
if (tst < 3) {
SSL_CTX_set_options(cctx, SSL_OP_NO_TLSv1_3);
SSL_CTX_set_options(sctx, SSL_OP_NO_TLSv1_3);
if (sctx2 != NULL)
SSL_CTX_set_options(sctx2, SSL_OP_NO_TLSv1_3);
}
if (tst == 5) {
context = SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
| SSL_EXT_TLS1_3_CERTIFICATE;
SSL_CTX_set_verify(sctx,
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
verify_cb);
if (!TEST_int_eq(SSL_CTX_use_certificate_file(cctx, cert,
SSL_FILETYPE_PEM), 1)
|| !TEST_int_eq(SSL_CTX_use_PrivateKey_file(cctx, privkey,
SSL_FILETYPE_PEM), 1)
|| !TEST_int_eq(SSL_CTX_check_private_key(cctx), 1))
goto end;
} else if (tst == 4) {
context = SSL_EXT_CLIENT_HELLO
| SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
| SSL_EXT_TLS1_3_CERTIFICATE
| SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
} else {
context = SSL_EXT_CLIENT_HELLO
| SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
}
/* Create a client side custom extension */
if (tst == 0) {
if (!TEST_true(SSL_CTX_add_client_custom_ext(cctx, TEST_EXT_TYPE1,
old_add_cb, old_free_cb,
&client, old_parse_cb,
&client)))
goto end;
} else {
if (!TEST_true(SSL_CTX_add_custom_ext(cctx, TEST_EXT_TYPE1, context,
new_add_cb, new_free_cb,
&client, new_parse_cb, &client)))
goto end;
}
/* Should not be able to add duplicates */
if (!TEST_false(SSL_CTX_add_client_custom_ext(cctx, TEST_EXT_TYPE1,
old_add_cb, old_free_cb,
&client, old_parse_cb,
&client))
|| !TEST_false(SSL_CTX_add_custom_ext(cctx, TEST_EXT_TYPE1,
context, new_add_cb,
new_free_cb, &client,
new_parse_cb, &client)))
goto end;
/* Create a server side custom extension */
if (tst == 0) {
if (!TEST_true(SSL_CTX_add_server_custom_ext(sctx, TEST_EXT_TYPE1,
old_add_cb, old_free_cb,
&server, old_parse_cb,
&server)))
goto end;
} else {
if (!TEST_true(SSL_CTX_add_custom_ext(sctx, TEST_EXT_TYPE1, context,
new_add_cb, new_free_cb,
&server, new_parse_cb, &server)))
goto end;
if (sctx2 != NULL
&& !TEST_true(SSL_CTX_add_custom_ext(sctx2, TEST_EXT_TYPE1,
context, new_add_cb,
new_free_cb, &server,
new_parse_cb, &server)))
goto end;
}
/* Should not be able to add duplicates */
if (!TEST_false(SSL_CTX_add_server_custom_ext(sctx, TEST_EXT_TYPE1,
old_add_cb, old_free_cb,
&server, old_parse_cb,
&server))
|| !TEST_false(SSL_CTX_add_custom_ext(sctx, TEST_EXT_TYPE1,
context, new_add_cb,
new_free_cb, &server,
new_parse_cb, &server)))
goto end;
if (tst == 2) {
/* Set up SNI */
if (!TEST_true(SSL_CTX_set_tlsext_servername_callback(sctx, sni_cb))
|| !TEST_true(SSL_CTX_set_tlsext_servername_arg(sctx, sctx2)))
goto end;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
if (tst == 0) {
if (clntaddoldcb != 1
|| clntparseoldcb != 1
|| srvaddoldcb != 1
|| srvparseoldcb != 1)
goto end;
} else if (tst == 1 || tst == 2 || tst == 3) {
if (clntaddnewcb != 1
|| clntparsenewcb != 1
|| srvaddnewcb != 1
|| srvparsenewcb != 1
|| (tst != 2 && snicb != 0)
|| (tst == 2 && snicb != 1))
goto end;
} else if (tst == 5) {
if (clntaddnewcb != 1
|| clntparsenewcb != 1
|| srvaddnewcb != 1
|| srvparsenewcb != 1)
goto end;
} else {
/* In this case there 2 NewSessionTicket messages created */
if (clntaddnewcb != 1
|| clntparsenewcb != 5
|| srvaddnewcb != 5
|| srvparsenewcb != 1)
goto end;
}
sess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
if (tst == 3 || tst == 5) {
/* We don't bother with the resumption aspects for these tests */
testresult = 1;
goto end;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, sess))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
/*
* For a resumed session we expect to add the ClientHello extension. For the
* old style callbacks we ignore it on the server side because they set
* SSL_EXT_IGNORE_ON_RESUMPTION. The new style callbacks do not ignore
* them.
*/
if (tst == 0) {
if (clntaddoldcb != 2
|| clntparseoldcb != 1
|| srvaddoldcb != 1
|| srvparseoldcb != 1)
goto end;
} else if (tst == 1 || tst == 2 || tst == 3) {
if (clntaddnewcb != 2
|| clntparsenewcb != 2
|| srvaddnewcb != 2
|| srvparsenewcb != 2)
goto end;
} else {
/*
* No Certificate message extensions in the resumption handshake,
* 2 NewSessionTickets in the initial handshake, 1 in the resumption
*/
if (clntaddnewcb != 2
|| clntparsenewcb != 8
|| srvaddnewcb != 8
|| srvparsenewcb != 2)
goto end;
}
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx2);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3)
#define SYNTHV1CONTEXT (SSL_EXT_TLS1_2_AND_BELOW_ONLY \
| SSL_EXT_CLIENT_HELLO \
| SSL_EXT_TLS1_2_SERVER_HELLO \
| SSL_EXT_IGNORE_ON_RESUMPTION)
#define TLS13CONTEXT (SSL_EXT_TLS1_3_CERTIFICATE \
| SSL_EXT_TLS1_2_SERVER_HELLO \
| SSL_EXT_CLIENT_HELLO)
#define SERVERINFO_CUSTOM \
0x00, (char)TLSEXT_TYPE_signed_certificate_timestamp, \
0x00, 0x03, \
0x04, 0x05, 0x06 \
static const unsigned char serverinfo_custom_tls13[] = {
0x00, 0x00, (TLS13CONTEXT >> 8) & 0xff, TLS13CONTEXT & 0xff,
SERVERINFO_CUSTOM
};
static const unsigned char serverinfo_custom_v2[] = {
0x00, 0x00, (SYNTHV1CONTEXT >> 8) & 0xff, SYNTHV1CONTEXT & 0xff,
SERVERINFO_CUSTOM
};
static const unsigned char serverinfo_custom_v1[] = {
SERVERINFO_CUSTOM
};
static const size_t serverinfo_custom_tls13_len = sizeof(serverinfo_custom_tls13);
static const size_t serverinfo_custom_v2_len = sizeof(serverinfo_custom_v2);
static const size_t serverinfo_custom_v1_len = sizeof(serverinfo_custom_v1);
static int serverinfo_custom_parse_cb(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)
{
const size_t len = serverinfo_custom_v1_len;
const unsigned char *si = &serverinfo_custom_v1[len - 3];
int *p_cb_result = (int*)parse_arg;
*p_cb_result = TEST_mem_eq(in, inlen, si, 3);
return 1;
}
static int test_serverinfo_custom(const int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
int cb_result = 0;
/*
* Following variables are set in the switch statement
* according to the test iteration.
* Default values do not make much sense: test would fail with them.
*/
int serverinfo_version = 0;
int protocol_version = 0;
unsigned int extension_context = 0;
const unsigned char *si = NULL;
size_t si_len = 0;
const int call_use_serverinfo_ex = idx > 0;
switch (idx) {
case 0: /* FALLTHROUGH */
case 1:
serverinfo_version = SSL_SERVERINFOV1;
protocol_version = TLS1_2_VERSION;
extension_context = SYNTHV1CONTEXT;
si = serverinfo_custom_v1;
si_len = serverinfo_custom_v1_len;
break;
case 2:
serverinfo_version = SSL_SERVERINFOV2;
protocol_version = TLS1_2_VERSION;
extension_context = SYNTHV1CONTEXT;
si = serverinfo_custom_v2;
si_len = serverinfo_custom_v2_len;
break;
case 3:
serverinfo_version = SSL_SERVERINFOV2;
protocol_version = TLS1_3_VERSION;
extension_context = TLS13CONTEXT;
si = serverinfo_custom_tls13;
si_len = serverinfo_custom_tls13_len;
break;
}
if (!TEST_true(create_ssl_ctx_pair(libctx,
TLS_method(),
TLS_method(),
protocol_version,
protocol_version,
&sctx, &cctx, cert, privkey)))
goto end;
if (call_use_serverinfo_ex) {
if (!TEST_true(SSL_CTX_use_serverinfo_ex(sctx, serverinfo_version,
si, si_len)))
goto end;
} else {
if (!TEST_true(SSL_CTX_use_serverinfo(sctx, si, si_len)))
goto end;
}
if (!TEST_true(SSL_CTX_add_custom_ext(cctx, TLSEXT_TYPE_signed_certificate_timestamp,
extension_context,
NULL, NULL, NULL,
serverinfo_custom_parse_cb,
&cb_result))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_int_eq(SSL_do_handshake(clientssl), 1))
goto end;
if (!TEST_true(cb_result))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif
/*
* Test that SSL_export_keying_material() produces expected results. There are
* no test vectors so all we do is test that both sides of the communication
* produce the same results for different protocol versions.
*/
#define SMALL_LABEL_LEN 10
#define LONG_LABEL_LEN 249
static int test_export_key_mat(int tst)
{
int testresult = 0;
SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
const char label[LONG_LABEL_LEN + 1] = "test label";
const unsigned char context[] = "context";
const unsigned char *emptycontext = NULL;
unsigned char ckeymat1[80], ckeymat2[80], ckeymat3[80];
unsigned char skeymat1[80], skeymat2[80], skeymat3[80];
size_t labellen;
const int protocols[] = {
TLS1_VERSION,
TLS1_1_VERSION,
TLS1_2_VERSION,
TLS1_3_VERSION,
TLS1_3_VERSION,
TLS1_3_VERSION
};
#ifdef OPENSSL_NO_TLS1
if (tst == 0)
return 1;
#endif
#ifdef OPENSSL_NO_TLS1_1
if (tst == 1)
return 1;
#endif
if (is_fips && (tst == 0 || tst == 1))
return 1;
#ifdef OPENSSL_NO_TLS1_2
if (tst == 2)
return 1;
#endif
#ifdef OSSL_NO_USABLE_TLS1_3
if (tst >= 3)
return 1;
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
OPENSSL_assert(tst >= 0 && (size_t)tst < OSSL_NELEM(protocols));
SSL_CTX_set_max_proto_version(cctx, protocols[tst]);
SSL_CTX_set_min_proto_version(cctx, protocols[tst]);
if ((protocols[tst] < TLS1_2_VERSION) &&
(!SSL_CTX_set_cipher_list(cctx, "DEFAULT:@SECLEVEL=0")
|| !SSL_CTX_set_cipher_list(sctx, "DEFAULT:@SECLEVEL=0")))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
NULL)))
goto end;
/*
* Premature call of SSL_export_keying_material should just fail.
*/
if (!TEST_int_le(SSL_export_keying_material(clientssl, ckeymat1,
sizeof(ckeymat1), label,
SMALL_LABEL_LEN + 1, context,
sizeof(context) - 1, 1), 0))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
if (tst == 5) {
/*
* TLSv1.3 imposes a maximum label len of 249 bytes. Check we fail if we
* go over that.
*/
if (!TEST_int_le(SSL_export_keying_material(clientssl, ckeymat1,
sizeof(ckeymat1), label,
LONG_LABEL_LEN + 1, context,
sizeof(context) - 1, 1), 0))
goto end;
testresult = 1;
goto end;
} else if (tst == 4) {
labellen = LONG_LABEL_LEN;
} else {
labellen = SMALL_LABEL_LEN;
}
if (!TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat1,
sizeof(ckeymat1), label,
labellen, context,
sizeof(context) - 1, 1), 1)
|| !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat2,
sizeof(ckeymat2), label,
labellen,
emptycontext,
0, 1), 1)
|| !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat3,
sizeof(ckeymat3), label,
labellen,
NULL, 0, 0), 1)
|| !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat1,
sizeof(skeymat1), label,
labellen,
context,
sizeof(context) -1, 1),
1)
|| !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat2,
sizeof(skeymat2), label,
labellen,
emptycontext,
0, 1), 1)
|| !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat3,
sizeof(skeymat3), label,
labellen,
NULL, 0, 0), 1)
/*
* Check that both sides created the same key material with the
* same context.
*/
|| !TEST_mem_eq(ckeymat1, sizeof(ckeymat1), skeymat1,
sizeof(skeymat1))
/*
* Check that both sides created the same key material with an
* empty context.
*/
|| !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), skeymat2,
sizeof(skeymat2))
/*
* Check that both sides created the same key material without a
* context.
*/
|| !TEST_mem_eq(ckeymat3, sizeof(ckeymat3), skeymat3,
sizeof(skeymat3))
/* Different contexts should produce different results */
|| !TEST_mem_ne(ckeymat1, sizeof(ckeymat1), ckeymat2,
sizeof(ckeymat2)))
goto end;
/*
* Check that an empty context and no context produce different results in
* protocols less than TLSv1.3. In TLSv1.3 they should be the same.
*/
if ((tst < 3 && !TEST_mem_ne(ckeymat2, sizeof(ckeymat2), ckeymat3,
sizeof(ckeymat3)))
|| (tst >= 3 && !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), ckeymat3,
sizeof(ckeymat3))))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx2);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#ifndef OSSL_NO_USABLE_TLS1_3
/*
* Test that SSL_export_keying_material_early() produces expected
* results. There are no test vectors so all we do is test that both
* sides of the communication produce the same results for different
* protocol versions.
*/
static int test_export_key_mat_early(int idx)
{
static const char label[] = "test label";
static const unsigned char context[] = "context";
int testresult = 0;
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
SSL_SESSION *sess = NULL;
const unsigned char *emptycontext = NULL;
unsigned char ckeymat1[80], ckeymat2[80];
unsigned char skeymat1[80], skeymat2[80];
unsigned char buf[1];
size_t readbytes, written;
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl,
&sess, idx, SHA384_DIGEST_LENGTH)))
goto end;
/* Here writing 0 length early data is enough. */
if (!TEST_true(SSL_write_early_data(clientssl, NULL, 0, &written))
|| !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
SSL_READ_EARLY_DATA_ERROR)
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED))
goto end;
if (!TEST_int_eq(SSL_export_keying_material_early(
clientssl, ckeymat1, sizeof(ckeymat1), label,
sizeof(label) - 1, context, sizeof(context) - 1), 1)
|| !TEST_int_eq(SSL_export_keying_material_early(
clientssl, ckeymat2, sizeof(ckeymat2), label,
sizeof(label) - 1, emptycontext, 0), 1)
|| !TEST_int_eq(SSL_export_keying_material_early(
serverssl, skeymat1, sizeof(skeymat1), label,
sizeof(label) - 1, context, sizeof(context) - 1), 1)
|| !TEST_int_eq(SSL_export_keying_material_early(
serverssl, skeymat2, sizeof(skeymat2), label,
sizeof(label) - 1, emptycontext, 0), 1)
/*
* Check that both sides created the same key material with the
* same context.
*/
|| !TEST_mem_eq(ckeymat1, sizeof(ckeymat1), skeymat1,
sizeof(skeymat1))
/*
* Check that both sides created the same key material with an
* empty context.
*/
|| !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), skeymat2,
sizeof(skeymat2))
/* Different contexts should produce different results */
|| !TEST_mem_ne(ckeymat1, sizeof(ckeymat1), ckeymat2,
sizeof(ckeymat2)))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_SESSION_free(clientpsk);
SSL_SESSION_free(serverpsk);
clientpsk = serverpsk = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#define NUM_KEY_UPDATE_MESSAGES 40
/*
* Test KeyUpdate.
*/
static int test_key_update(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0, i, j;
char buf[20];
static char *mess = "A test message";
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
0,
&sctx, &cctx, cert, privkey))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
for (j = 0; j < 2; j++) {
/* Send lots of KeyUpdate messages */
for (i = 0; i < NUM_KEY_UPDATE_MESSAGES; i++) {
if (!TEST_true(SSL_key_update(clientssl,
(j == 0)
? SSL_KEY_UPDATE_NOT_REQUESTED
: SSL_KEY_UPDATE_REQUESTED))
|| !TEST_true(SSL_do_handshake(clientssl)))
goto end;
}
/* Check that sending and receiving app data is ok */
if (!TEST_int_eq(SSL_write(clientssl, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(serverssl, buf, sizeof(buf)),
strlen(mess)))
goto end;
if (!TEST_int_eq(SSL_write(serverssl, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(clientssl, buf, sizeof(buf)),
strlen(mess)))
goto end;
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test we can handle a KeyUpdate (update requested) message while
* write data is pending in peer.
* Test 0: Client sends KeyUpdate while Server is writing
* Test 1: Server sends KeyUpdate while Client is writing
*/
static int test_key_update_peer_in_write(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
char buf[20];
static char *mess = "A test message";
BIO *bretry = BIO_new(bio_s_always_retry());
BIO *tmp = NULL;
SSL *peerupdate = NULL, *peerwrite = NULL;
if (!TEST_ptr(bretry)
|| !TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
0,
&sctx, &cctx, cert, privkey))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
peerupdate = tst == 0 ? clientssl : serverssl;
peerwrite = tst == 0 ? serverssl : clientssl;
if (!TEST_true(SSL_key_update(peerupdate, SSL_KEY_UPDATE_REQUESTED))
|| !TEST_int_eq(SSL_do_handshake(peerupdate), 1))
goto end;
/* Swap the writing endpoint's write BIO to force a retry */
tmp = SSL_get_wbio(peerwrite);
if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
tmp = NULL;
goto end;
}
SSL_set0_wbio(peerwrite, bretry);
bretry = NULL;
/* Write data that we know will fail with SSL_ERROR_WANT_WRITE */
if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), -1)
|| !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE))
goto end;
/* Reinstate the original writing endpoint's write BIO */
SSL_set0_wbio(peerwrite, tmp);
tmp = NULL;
/* Now read some data - we will read the key update */
if (!TEST_int_eq(SSL_read(peerwrite, buf, sizeof(buf)), -1)
|| !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ))
goto end;
/*
* Complete the write we started previously and read it from the other
* endpoint
*/
if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess)))
goto end;
/* Write more data to ensure we send the KeyUpdate message back */
if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
BIO_free(bretry);
BIO_free(tmp);
return testresult;
}
/*
* Test we can handle a KeyUpdate (update requested) message while
* peer read data is pending after peer accepted keyupdate(the msg header
* had been read 5 bytes).
* Test 0: Client sends KeyUpdate while Server is reading
* Test 1: Server sends KeyUpdate while Client is reading
*/
static int test_key_update_peer_in_read(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
char prbuf[515], lwbuf[515] = {0};
static char *mess = "A test message";
BIO *lbio = NULL, *pbio = NULL;
SSL *local = NULL, *peer = NULL;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
0,
&sctx, &cctx, cert, privkey))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
local = tst == 0 ? clientssl : serverssl;
peer = tst == 0 ? serverssl : clientssl;
if (!TEST_int_eq(BIO_new_bio_pair(&lbio, 512, &pbio, 512), 1))
goto end;
SSL_set_bio(local, lbio, lbio);
SSL_set_bio(peer, pbio, pbio);
/*
* we first write keyupdate msg then appdata in local
* write data in local will fail with SSL_ERROR_WANT_WRITE,because
* lwbuf app data msg size + key updata msg size > 512(the size of
* the bio pair buffer)
*/
if (!TEST_true(SSL_key_update(local, SSL_KEY_UPDATE_REQUESTED))
|| !TEST_int_eq(SSL_write(local, lwbuf, sizeof(lwbuf)), -1)
|| !TEST_int_eq(SSL_get_error(local, -1), SSL_ERROR_WANT_WRITE))
goto end;
/*
* first read keyupdate msg in peer in peer
* then read appdata that we know will fail with SSL_ERROR_WANT_READ
*/
if (!TEST_int_eq(SSL_read(peer, prbuf, sizeof(prbuf)), -1)
|| !TEST_int_eq(SSL_get_error(peer, -1), SSL_ERROR_WANT_READ))
goto end;
/* Now write some data in peer - we will write the key update */
if (!TEST_int_eq(SSL_write(peer, mess, strlen(mess)), strlen(mess)))
goto end;
/*
* write data in local previously that we will complete
* read data in peer previously that we will complete
*/
if (!TEST_int_eq(SSL_write(local, lwbuf, sizeof(lwbuf)), sizeof(lwbuf))
|| !TEST_int_eq(SSL_read(peer, prbuf, sizeof(prbuf)), sizeof(prbuf)))
goto end;
/* check that sending and receiving appdata ok */
if (!TEST_int_eq(SSL_write(local, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(peer, prbuf, sizeof(prbuf)), strlen(mess)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test we can't send a KeyUpdate (update requested) message while
* local write data is pending.
* Test 0: Client sends KeyUpdate while Client is writing
* Test 1: Server sends KeyUpdate while Server is writing
*/
static int test_key_update_local_in_write(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
char buf[20];
static char *mess = "A test message";
BIO *bretry = BIO_new(bio_s_always_retry());
BIO *tmp = NULL;
SSL *local = NULL, *peer = NULL;
if (!TEST_ptr(bretry)
|| !TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
0,
&sctx, &cctx, cert, privkey))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
local = tst == 0 ? clientssl : serverssl;
peer = tst == 0 ? serverssl : clientssl;
/* Swap the writing endpoint's write BIO to force a retry */
tmp = SSL_get_wbio(local);
if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
tmp = NULL;
goto end;
}
SSL_set0_wbio(local, bretry);
bretry = NULL;
/* write data in local will fail with SSL_ERROR_WANT_WRITE */
if (!TEST_int_eq(SSL_write(local, mess, strlen(mess)), -1)
|| !TEST_int_eq(SSL_get_error(local, -1), SSL_ERROR_WANT_WRITE))
goto end;
/* Reinstate the original writing endpoint's write BIO */
SSL_set0_wbio(local, tmp);
tmp = NULL;
/* SSL_key_update will fail, because writing in local*/
if (!TEST_false(SSL_key_update(local, SSL_KEY_UPDATE_REQUESTED))
|| !TEST_int_eq(ERR_GET_REASON(ERR_peek_error()), SSL_R_BAD_WRITE_RETRY))
goto end;
ERR_clear_error();
/* write data in local previously that we will complete */
if (!TEST_int_eq(SSL_write(local, mess, strlen(mess)), strlen(mess)))
goto end;
/* SSL_key_update will succeed because there is no pending write data */
if (!TEST_true(SSL_key_update(local, SSL_KEY_UPDATE_REQUESTED))
|| !TEST_int_eq(SSL_do_handshake(local), 1))
goto end;
/*
* we write some appdata in local
* read data in peer - we will read the keyupdate msg
*/
if (!TEST_int_eq(SSL_write(local, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(peer, buf, sizeof(buf)), strlen(mess)))
goto end;
/* Write more peer more data to ensure we send the keyupdate message back */
if (!TEST_int_eq(SSL_write(peer, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(local, buf, sizeof(buf)), strlen(mess)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
BIO_free(bretry);
BIO_free(tmp);
return testresult;
}
/*
* Test we can handle a KeyUpdate (update requested) message while
* local read data is pending(the msg header had been read 5 bytes).
* Test 0: Client sends KeyUpdate while Client is reading
* Test 1: Server sends KeyUpdate while Server is reading
*/
static int test_key_update_local_in_read(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
char lrbuf[515], pwbuf[515] = {0}, prbuf[20];
static char *mess = "A test message";
BIO *lbio = NULL, *pbio = NULL;
SSL *local = NULL, *peer = NULL;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
0,
&sctx, &cctx, cert, privkey))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
local = tst == 0 ? clientssl : serverssl;
peer = tst == 0 ? serverssl : clientssl;
if (!TEST_int_eq(BIO_new_bio_pair(&lbio, 512, &pbio, 512), 1))
goto end;
SSL_set_bio(local, lbio, lbio);
SSL_set_bio(peer, pbio, pbio);
/* write app data in peer will fail with SSL_ERROR_WANT_WRITE */
if (!TEST_int_eq(SSL_write(peer, pwbuf, sizeof(pwbuf)), -1)
|| !TEST_int_eq(SSL_get_error(peer, -1), SSL_ERROR_WANT_WRITE))
goto end;
/* read appdata in local will fail with SSL_ERROR_WANT_READ */
if (!TEST_int_eq(SSL_read(local, lrbuf, sizeof(lrbuf)), -1)
|| !TEST_int_eq(SSL_get_error(local, -1), SSL_ERROR_WANT_READ))
goto end;
/* SSL_do_handshake will send keyupdate msg */
if (!TEST_true(SSL_key_update(local, SSL_KEY_UPDATE_REQUESTED))
|| !TEST_int_eq(SSL_do_handshake(local), 1))
goto end;
/*
* write data in peer previously that we will complete
* read data in local previously that we will complete
*/
if (!TEST_int_eq(SSL_write(peer, pwbuf, sizeof(pwbuf)), sizeof(pwbuf))
|| !TEST_int_eq(SSL_read(local, lrbuf, sizeof(lrbuf)), sizeof(lrbuf)))
goto end;
/*
* write data in local
* read data in peer - we will read the key update
*/
if (!TEST_int_eq(SSL_write(local, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(peer, prbuf, sizeof(prbuf)), strlen(mess)))
goto end;
/* Write more peer data to ensure we send the keyupdate message back */
if (!TEST_int_eq(SSL_write(peer, mess, strlen(mess)), strlen(mess))
|| !TEST_int_eq(SSL_read(local, lrbuf, sizeof(lrbuf)), strlen(mess)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif /* OSSL_NO_USABLE_TLS1_3 */
static int test_ssl_clear(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
#ifdef OPENSSL_NO_TLS1_2
if (idx == 1)
return 1;
#endif
/* Create an initial connection */
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey))
|| (idx == 1
&& !TEST_true(SSL_CTX_set_max_proto_version(cctx,
TLS1_2_VERSION)))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
serverssl = NULL;
/* Clear clientssl - we're going to reuse the object */
if (!TEST_true(SSL_clear(clientssl)))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl)))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/* Parse CH and retrieve any MFL extension value if present */
static int get_MFL_from_client_hello(BIO *bio, int *mfl_codemfl_code)
{
long len;
unsigned char *data;
PACKET pkt, pkt2, pkt3;
unsigned int MFL_code = 0, type = 0;
if (!TEST_uint_gt( len = BIO_get_mem_data( bio, (char **) &data ), 0 ) )
goto end;
memset(&pkt, 0, sizeof(pkt));
memset(&pkt2, 0, sizeof(pkt2));
memset(&pkt3, 0, sizeof(pkt3));
if (!TEST_long_gt(len, 0)
|| !TEST_true( PACKET_buf_init( &pkt, data, len ) )
/* Skip the record header */
|| !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH)
/* Skip the handshake message header */
|| !TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH))
/* Skip client version and random */
|| !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN
+ SSL3_RANDOM_SIZE))
/* Skip session id */
|| !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
/* Skip ciphers */
|| !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2))
/* Skip compression */
|| !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
/* Extensions len */
|| !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2)))
goto end;
/* Loop through all extensions */
while (PACKET_remaining(&pkt2)) {
if (!TEST_true(PACKET_get_net_2(&pkt2, &type))
|| !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3)))
goto end;
if (type == TLSEXT_TYPE_max_fragment_length) {
if (!TEST_uint_ne(PACKET_remaining(&pkt3), 0)
|| !TEST_true(PACKET_get_1(&pkt3, &MFL_code)))
goto end;
*mfl_codemfl_code = MFL_code;
return 1;
}
}
end:
return 0;
}
/* Maximum-Fragment-Length TLS extension mode to test */
static const unsigned char max_fragment_len_test[] = {
TLSEXT_max_fragment_length_512,
TLSEXT_max_fragment_length_1024,
TLSEXT_max_fragment_length_2048,
TLSEXT_max_fragment_length_4096
};
static int test_max_fragment_len_ext(int idx_tst)
{
SSL_CTX *ctx = NULL;
SSL *con = NULL;
int testresult = 0, MFL_mode = 0;
BIO *rbio, *wbio;
if (!TEST_true(create_ssl_ctx_pair(libctx, NULL, TLS_client_method(),
TLS1_VERSION, 0, NULL, &ctx, NULL,
NULL)))
return 0;
if (!TEST_true(SSL_CTX_set_tlsext_max_fragment_length(
ctx, max_fragment_len_test[idx_tst])))
goto end;
con = SSL_new(ctx);
if (!TEST_ptr(con))
goto end;
rbio = BIO_new(BIO_s_mem());
wbio = BIO_new(BIO_s_mem());
if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
BIO_free(rbio);
BIO_free(wbio);
goto end;
}
SSL_set_bio(con, rbio, wbio);
if (!TEST_int_le(SSL_connect(con), 0)) {
/* This shouldn't succeed because we don't have a server! */
goto end;
}
if (!TEST_true(get_MFL_from_client_hello(wbio, &MFL_mode)))
/* no MFL in client hello */
goto end;
if (!TEST_true(max_fragment_len_test[idx_tst] == MFL_mode))
goto end;
testresult = 1;
end:
SSL_free(con);
SSL_CTX_free(ctx);
return testresult;
}
#ifndef OSSL_NO_USABLE_TLS1_3
static int test_pha_key_update(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
return 0;
if (!TEST_true(SSL_CTX_set_min_proto_version(sctx, TLS1_3_VERSION))
|| !TEST_true(SSL_CTX_set_max_proto_version(sctx, TLS1_3_VERSION))
|| !TEST_true(SSL_CTX_set_min_proto_version(cctx, TLS1_3_VERSION))
|| !TEST_true(SSL_CTX_set_max_proto_version(cctx, TLS1_3_VERSION)))
goto end;
SSL_CTX_set_post_handshake_auth(cctx, 1);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
SSL_set_verify(serverssl, SSL_VERIFY_PEER, NULL);
if (!TEST_true(SSL_verify_client_post_handshake(serverssl)))
goto end;
if (!TEST_true(SSL_key_update(clientssl, SSL_KEY_UPDATE_NOT_REQUESTED)))
goto end;
/* Start handshake on the server */
if (!TEST_int_eq(SSL_do_handshake(serverssl), 1))
goto end;
/* Starts with SSL_connect(), but it's really just SSL_do_handshake() */
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif
#if !defined(OPENSSL_NO_SRP) && !defined(OPENSSL_NO_TLS1_2)
static SRP_VBASE *vbase = NULL;
static int ssl_srp_cb(SSL *s, int *ad, void *arg)
{
int ret = SSL3_AL_FATAL;
char *username;
SRP_user_pwd *user = NULL;
username = SSL_get_srp_username(s);
if (username == NULL) {
*ad = SSL_AD_INTERNAL_ERROR;
goto err;
}
user = SRP_VBASE_get1_by_user(vbase, username);
if (user == NULL) {
*ad = SSL_AD_INTERNAL_ERROR;
goto err;
}
if (SSL_set_srp_server_param(s, user->N, user->g, user->s, user->v,
user->info) <= 0) {
*ad = SSL_AD_INTERNAL_ERROR;
goto err;
}
ret = 0;
err:
SRP_user_pwd_free(user);
return ret;
}
static int create_new_vfile(char *userid, char *password, const char *filename)
{
char *gNid = NULL;
OPENSSL_STRING *row = OPENSSL_zalloc(sizeof(row) * (DB_NUMBER + 1));
TXT_DB *db = NULL;
int ret = 0;
BIO *out = NULL, *dummy = BIO_new_mem_buf("", 0);
size_t i;
if (!TEST_ptr(dummy) || !TEST_ptr(row))
goto end;
gNid = SRP_create_verifier_ex(userid, password, &row[DB_srpsalt],
&row[DB_srpverifier], NULL, NULL, libctx, NULL);
if (!TEST_ptr(gNid))
goto end;
/*
* The only way to create an empty TXT_DB is to provide a BIO with no data
* in it!
*/
db = TXT_DB_read(dummy, DB_NUMBER);
if (!TEST_ptr(db))
goto end;
out = BIO_new_file(filename, "w");
if (!TEST_ptr(out))
goto end;
row[DB_srpid] = OPENSSL_strdup(userid);
row[DB_srptype] = OPENSSL_strdup("V");
row[DB_srpgN] = OPENSSL_strdup(gNid);
if (!TEST_ptr(row[DB_srpid])
|| !TEST_ptr(row[DB_srptype])
|| !TEST_ptr(row[DB_srpgN])
|| !TEST_true(TXT_DB_insert(db, row)))
goto end;
row = NULL;
if (TXT_DB_write(out, db) <= 0)
goto end;
ret = 1;
end:
if (row != NULL) {
for (i = 0; i < DB_NUMBER; i++)
OPENSSL_free(row[i]);
}
OPENSSL_free(row);
BIO_free(dummy);
BIO_free(out);
TXT_DB_free(db);
return ret;
}
static int create_new_vbase(char *userid, char *password)
{
BIGNUM *verifier = NULL, *salt = NULL;
const SRP_gN *lgN = NULL;
SRP_user_pwd *user_pwd = NULL;
int ret = 0;
lgN = SRP_get_default_gN(NULL);
if (!TEST_ptr(lgN))
goto end;
if (!TEST_true(SRP_create_verifier_BN_ex(userid, password, &salt, &verifier,
lgN->N, lgN->g, libctx, NULL)))
goto end;
user_pwd = OPENSSL_zalloc(sizeof(*user_pwd));
if (!TEST_ptr(user_pwd))
goto end;
user_pwd->N = lgN->N;
user_pwd->g = lgN->g;
user_pwd->id = OPENSSL_strdup(userid);
if (!TEST_ptr(user_pwd->id))
goto end;
user_pwd->v = verifier;
user_pwd->s = salt;
verifier = salt = NULL;
if (sk_SRP_user_pwd_insert(vbase->users_pwd, user_pwd, 0) == 0)
goto end;
user_pwd = NULL;
ret = 1;
end:
SRP_user_pwd_free(user_pwd);
BN_free(salt);
BN_free(verifier);
return ret;
}
/*
* SRP tests
*
* Test 0: Simple successful SRP connection, new vbase
* Test 1: Connection failure due to bad password, new vbase
* Test 2: Simple successful SRP connection, vbase loaded from existing file
* Test 3: Connection failure due to bad password, vbase loaded from existing
* file
* Test 4: Simple successful SRP connection, vbase loaded from new file
* Test 5: Connection failure due to bad password, vbase loaded from new file
*/
static int test_srp(int tst)
{
char *userid = "test", *password = "password", *tstsrpfile;
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int ret, testresult = 0;
vbase = SRP_VBASE_new(NULL);
if (!TEST_ptr(vbase))
goto end;
if (tst == 0 || tst == 1) {
if (!TEST_true(create_new_vbase(userid, password)))
goto end;
} else {
if (tst == 4 || tst == 5) {
if (!TEST_true(create_new_vfile(userid, password, tmpfilename)))
goto end;
tstsrpfile = tmpfilename;
} else {
tstsrpfile = srpvfile;
}
if (!TEST_int_eq(SRP_VBASE_init(vbase, tstsrpfile), SRP_NO_ERROR))
goto end;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
if (!TEST_int_gt(SSL_CTX_set_srp_username_callback(sctx, ssl_srp_cb), 0)
|| !TEST_true(SSL_CTX_set_cipher_list(cctx, "SRP-AES-128-CBC-SHA"))
|| !TEST_true(SSL_CTX_set_max_proto_version(sctx, TLS1_2_VERSION))
|| !TEST_true(SSL_CTX_set_max_proto_version(cctx, TLS1_2_VERSION))
|| !TEST_int_gt(SSL_CTX_set_srp_username(cctx, userid), 0))
goto end;
if (tst % 2 == 1) {
if (!TEST_int_gt(SSL_CTX_set_srp_password(cctx, "badpass"), 0))
goto end;
} else {
if (!TEST_int_gt(SSL_CTX_set_srp_password(cctx, password), 0))
goto end;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
ret = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE);
if (ret) {
if (!TEST_true(tst % 2 == 0))
goto end;
} else {
if (!TEST_true(tst % 2 == 1))
goto end;
}
testresult = 1;
end:
SRP_VBASE_free(vbase);
vbase = NULL;
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif
static int info_cb_failed = 0;
static int info_cb_offset = 0;
static int info_cb_this_state = -1;
static struct info_cb_states_st {
int where;
const char *statestr;
} info_cb_states[][60] = {
{
/* TLSv1.2 server followed by resumption */
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT"},
{SSL_CB_LOOP, "PINIT"}, {SSL_CB_LOOP, "TRCH"}, {SSL_CB_LOOP, "TWSH"},
{SSL_CB_LOOP, "TWSC"}, {SSL_CB_LOOP, "TWSKE"}, {SSL_CB_LOOP, "TWSD"},
{SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TWSD"}, {SSL_CB_LOOP, "TRCKE"},
{SSL_CB_LOOP, "TRCCS"}, {SSL_CB_LOOP, "TRFIN"}, {SSL_CB_LOOP, "TWST"},
{SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWFIN"},
{SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL},
{SSL_CB_ALERT, NULL}, {SSL_CB_HANDSHAKE_START, NULL},
{SSL_CB_LOOP, "PINIT"}, {SSL_CB_LOOP, "PINIT"}, {SSL_CB_LOOP, "TRCH"},
{SSL_CB_LOOP, "TWSH"}, {SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWFIN"},
{SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TWFIN"}, {SSL_CB_LOOP, "TRCCS"},
{SSL_CB_LOOP, "TRFIN"}, {SSL_CB_HANDSHAKE_DONE, NULL},
{SSL_CB_EXIT, NULL}, {0, NULL},
}, {
/* TLSv1.2 client followed by resumption */
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT"},
{SSL_CB_LOOP, "TWCH"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TWCH"},
{SSL_CB_LOOP, "TRSH"}, {SSL_CB_LOOP, "TRSC"}, {SSL_CB_LOOP, "TRSKE"},
{SSL_CB_LOOP, "TRSD"}, {SSL_CB_LOOP, "TWCKE"}, {SSL_CB_LOOP, "TWCCS"},
{SSL_CB_LOOP, "TWFIN"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TWFIN"},
{SSL_CB_LOOP, "TRST"}, {SSL_CB_LOOP, "TRCCS"}, {SSL_CB_LOOP, "TRFIN"},
{SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL}, {SSL_CB_ALERT, NULL},
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT"},
{SSL_CB_LOOP, "TWCH"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TWCH"},
{SSL_CB_LOOP, "TRSH"}, {SSL_CB_LOOP, "TRCCS"}, {SSL_CB_LOOP, "TRFIN"},
{SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWFIN"},
{SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL}, {0, NULL},
}, {
/* TLSv1.3 server followed by resumption */
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT"},
{SSL_CB_LOOP, "PINIT"}, {SSL_CB_LOOP, "TRCH"}, {SSL_CB_LOOP, "TWSH"},
{SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWEE"}, {SSL_CB_LOOP, "TWSC"},
{SSL_CB_LOOP, "TWSCV"}, {SSL_CB_LOOP, "TWFIN"}, {SSL_CB_LOOP, "TED"},
{SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TED"}, {SSL_CB_LOOP, "TRFIN"},
{SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_LOOP, "TWST"},
{SSL_CB_LOOP, "TWST"}, {SSL_CB_EXIT, NULL}, {SSL_CB_ALERT, NULL},
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT"},
{SSL_CB_LOOP, "PINIT"}, {SSL_CB_LOOP, "TRCH"}, {SSL_CB_LOOP, "TWSH"},
{SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWEE"}, {SSL_CB_LOOP, "TWFIN"},
{SSL_CB_LOOP, "TED"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TED"},
{SSL_CB_LOOP, "TRFIN"}, {SSL_CB_HANDSHAKE_DONE, NULL},
{SSL_CB_LOOP, "TWST"}, {SSL_CB_EXIT, NULL}, {0, NULL},
}, {
/* TLSv1.3 client followed by resumption */
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT"},
{SSL_CB_LOOP, "TWCH"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TWCH"},
{SSL_CB_LOOP, "TRSH"}, {SSL_CB_LOOP, "TREE"}, {SSL_CB_LOOP, "TRSC"},
{SSL_CB_LOOP, "TRSCV"}, {SSL_CB_LOOP, "TRFIN"}, {SSL_CB_LOOP, "TWCCS"},
{SSL_CB_LOOP, "TWFIN"}, {SSL_CB_HANDSHAKE_DONE, NULL},
{SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "SSLOK"}, {SSL_CB_LOOP, "SSLOK"},
{SSL_CB_LOOP, "TRST"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "SSLOK"},
{SSL_CB_LOOP, "SSLOK"}, {SSL_CB_LOOP, "TRST"}, {SSL_CB_EXIT, NULL},
{SSL_CB_ALERT, NULL}, {SSL_CB_HANDSHAKE_START, NULL},
{SSL_CB_LOOP, "PINIT"}, {SSL_CB_LOOP, "TWCH"}, {SSL_CB_EXIT, NULL},
{SSL_CB_LOOP, "TWCH"}, {SSL_CB_LOOP, "TRSH"}, {SSL_CB_LOOP, "TREE"},
{SSL_CB_LOOP, "TRFIN"}, {SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWFIN"},
{SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL},
{SSL_CB_LOOP, "SSLOK"}, {SSL_CB_LOOP, "SSLOK"}, {SSL_CB_LOOP, "TRST"},
{SSL_CB_EXIT, NULL}, {0, NULL},
}, {
/* TLSv1.3 server, early_data */
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT"},
{SSL_CB_LOOP, "PINIT"}, {SSL_CB_LOOP, "TRCH"}, {SSL_CB_LOOP, "TWSH"},
{SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWEE"}, {SSL_CB_LOOP, "TWFIN"},
{SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL},
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "TED"},
{SSL_CB_LOOP, "TED"}, {SSL_CB_LOOP, "TWEOED"}, {SSL_CB_LOOP, "TRFIN"},
{SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_LOOP, "TWST"},
{SSL_CB_EXIT, NULL}, {0, NULL},
}, {
/* TLSv1.3 client, early_data */
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT"},
{SSL_CB_LOOP, "TWCH"}, {SSL_CB_LOOP, "TWCCS"},
{SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL},
{SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "TED"},
{SSL_CB_LOOP, "TED"}, {SSL_CB_LOOP, "TRSH"}, {SSL_CB_LOOP, "TREE"},
{SSL_CB_LOOP, "TRFIN"}, {SSL_CB_LOOP, "TPEDE"}, {SSL_CB_LOOP, "TWEOED"},
{SSL_CB_LOOP, "TWFIN"}, {SSL_CB_HANDSHAKE_DONE, NULL},
{SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "SSLOK"}, {SSL_CB_LOOP, "SSLOK"},
{SSL_CB_LOOP, "TRST"}, {SSL_CB_EXIT, NULL}, {0, NULL},
}, {
{0, NULL},
}
};
static void sslapi_info_callback(const SSL *s, int where, int ret)
{
struct info_cb_states_st *state = info_cb_states[info_cb_offset];
/* We do not ever expect a connection to fail in this test */
if (!TEST_false(ret == 0)) {
info_cb_failed = 1;
return;
}
/*
* Do some sanity checks. We never expect these things to happen in this
* test
*/
if (!TEST_false((SSL_is_server(s) && (where & SSL_ST_CONNECT) != 0))
|| !TEST_false(!SSL_is_server(s) && (where & SSL_ST_ACCEPT) != 0)
|| !TEST_int_ne(state[++info_cb_this_state].where, 0)) {
info_cb_failed = 1;
return;
}
/* Now check we're in the right state */
if (!TEST_true((where & state[info_cb_this_state].where) != 0)) {
info_cb_failed = 1;
return;
}
if ((where & SSL_CB_LOOP) != 0
&& !TEST_int_eq(strcmp(SSL_state_string(s),
state[info_cb_this_state].statestr), 0)) {
info_cb_failed = 1;
return;
}
/*
* Check that, if we've got SSL_CB_HANDSHAKE_DONE we are not in init
*/
if ((where & SSL_CB_HANDSHAKE_DONE)
&& SSL_in_init((SSL *)s) != 0) {
info_cb_failed = 1;
return;
}
}
/*
* Test the info callback gets called when we expect it to.
*
* Test 0: TLSv1.2, server
* Test 1: TLSv1.2, client
* Test 2: TLSv1.3, server
* Test 3: TLSv1.3, client
* Test 4: TLSv1.3, server, early_data
* Test 5: TLSv1.3, client, early_data
*/
static int test_info_callback(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
SSL_SESSION *clntsess = NULL;
int testresult = 0;
int tlsvers;
if (tst < 2) {
/* We need either ECDHE or DHE for the TLSv1.2 test to work */
#if !defined(OPENSSL_NO_TLS1_2) && (!defined(OPENSSL_NO_EC) \
|| !defined(OPENSSL_NO_DH))
tlsvers = TLS1_2_VERSION;
#else
return 1;
#endif
} else {
#ifndef OSSL_NO_USABLE_TLS1_3
tlsvers = TLS1_3_VERSION;
#else
return 1;
#endif
}
/* Reset globals */
info_cb_failed = 0;
info_cb_this_state = -1;
info_cb_offset = tst;
#ifndef OSSL_NO_USABLE_TLS1_3
if (tst >= 4) {
SSL_SESSION *sess = NULL;
size_t written, readbytes;
unsigned char buf[80];
time_t timer;
/* early_data tests */
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
&serverssl, &sess, 0,
SHA384_DIGEST_LENGTH)))
goto end;
/* We don't actually need this reference */
SSL_SESSION_free(sess);
SSL_set_info_callback((tst % 2) == 0 ? serverssl : clientssl,
sslapi_info_callback);
/* Write and read some early data and then complete the connection */
timer = time(NULL);
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_size_t_eq(written, strlen(MSG1)))
goto end;
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf,
sizeof(buf), &readbytes),
SSL_READ_EARLY_DATA_SUCCESS)) {
testresult = check_early_data_timeout(timer);
goto end;
}
if (!TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED)
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(info_cb_failed))
goto end;
testresult = 1;
goto end;
}
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
tlsvers, tlsvers, &sctx, &cctx, cert,
privkey)))
goto end;
if (!TEST_true(SSL_CTX_set_dh_auto(sctx, 1)))
goto end;
/*
* For even numbered tests we check the server callbacks. For odd numbers we
* check the client.
*/
SSL_CTX_set_info_callback((tst % 2) == 0 ? sctx : cctx,
sslapi_info_callback);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_false(info_cb_failed))
goto end;
clntsess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* Now do a resumption */
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_true(SSL_session_reused(clientssl))
|| !TEST_false(info_cb_failed))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_SESSION_free(clntsess);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static int test_ssl_pending(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
char msg[] = "A test message";
char buf[5];
size_t written, readbytes;
if (tst == 0) {
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
} else {
#ifndef OPENSSL_NO_DTLS
if (!TEST_true(create_ssl_ctx_pair(libctx, DTLS_server_method(),
DTLS_client_method(),
DTLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
goto end;
# ifdef OPENSSL_NO_DTLS1_2
/* Not supported in the FIPS provider */
if (is_fips) {
testresult = 1;
goto end;
};
/*
* Default sigalgs are SHA1 based in <DTLS1.2 which is in security
* level 0
*/
if (!TEST_true(SSL_CTX_set_cipher_list(sctx, "DEFAULT:@SECLEVEL=0"))
|| !TEST_true(SSL_CTX_set_cipher_list(cctx,
"DEFAULT:@SECLEVEL=0")))
goto end;
# endif
#else
return 1;
#endif
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
if (!TEST_int_eq(SSL_pending(clientssl), 0)
|| !TEST_false(SSL_has_pending(clientssl))
|| !TEST_int_eq(SSL_pending(serverssl), 0)
|| !TEST_false(SSL_has_pending(serverssl))
|| !TEST_true(SSL_write_ex(serverssl, msg, sizeof(msg), &written))
|| !TEST_size_t_eq(written, sizeof(msg))
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))
|| !TEST_size_t_eq(readbytes, sizeof(buf))
|| !TEST_int_eq(SSL_pending(clientssl), (int)(written - readbytes))
|| !TEST_true(SSL_has_pending(clientssl)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static struct {
unsigned int maxprot;
const char *clntciphers;
const char *clnttls13ciphers;
const char *srvrciphers;
const char *srvrtls13ciphers;
const char *shared;
const char *fipsshared;
} shared_ciphers_data[] = {
/*
* We can't establish a connection (even in TLSv1.1) with these ciphersuites if
* TLSv1.3 is enabled but TLSv1.2 is disabled.
*/
#if defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
{
TLS1_2_VERSION,
"AES128-SHA:AES256-SHA",
NULL,
"AES256-SHA:DHE-RSA-AES128-SHA",
NULL,
"AES256-SHA",
"AES256-SHA"
},
# if !defined(OPENSSL_NO_CHACHA) \
&& !defined(OPENSSL_NO_POLY1305) \
&& !defined(OPENSSL_NO_EC)
{
TLS1_2_VERSION,
"AES128-SHA:ECDHE-RSA-CHACHA20-POLY1305",
NULL,
"AES128-SHA:ECDHE-RSA-CHACHA20-POLY1305",
NULL,
"AES128-SHA:ECDHE-RSA-CHACHA20-POLY1305",
"AES128-SHA"
},
# endif
{
TLS1_2_VERSION,
"AES128-SHA:DHE-RSA-AES128-SHA:AES256-SHA",
NULL,
"AES128-SHA:DHE-RSA-AES256-SHA:AES256-SHA",
NULL,
"AES128-SHA:AES256-SHA",
"AES128-SHA:AES256-SHA"
},
{
TLS1_2_VERSION,
"AES128-SHA:AES256-SHA",
NULL,
"AES128-SHA:DHE-RSA-AES128-SHA",
NULL,
"AES128-SHA",
"AES128-SHA"
},
#endif
/*
* This test combines TLSv1.3 and TLSv1.2 ciphersuites so they must both be
* enabled.
*/
#if !defined(OSSL_NO_USABLE_TLS1_3) && !defined(OPENSSL_NO_TLS1_2) \
&& !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
{
TLS1_3_VERSION,
"AES128-SHA:AES256-SHA",
NULL,
"AES256-SHA:AES128-SHA256",
NULL,
"TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:"
"TLS_AES_128_GCM_SHA256:AES256-SHA",
"TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:AES256-SHA"
},
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
{
TLS1_3_VERSION,
"AES128-SHA",
"TLS_AES_256_GCM_SHA384",
"AES256-SHA",
"TLS_AES_256_GCM_SHA384",
"TLS_AES_256_GCM_SHA384",
"TLS_AES_256_GCM_SHA384"
},
#endif
};
static int int_test_ssl_get_shared_ciphers(int tst, int clnt)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
char buf[1024];
OSSL_LIB_CTX *tmplibctx = OSSL_LIB_CTX_new();
if (!TEST_ptr(tmplibctx))
goto end;
/*
* Regardless of whether we're testing with the FIPS provider loaded into
* libctx, we want one peer to always use the full set of ciphersuites
* available. Therefore we use a separate libctx with the default provider
* loaded into it. We run the same tests twice - once with the client side
* having the full set of ciphersuites and once with the server side.
*/
if (clnt) {
cctx = SSL_CTX_new_ex(tmplibctx, NULL, TLS_client_method());
if (!TEST_ptr(cctx))
goto end;
} else {
sctx = SSL_CTX_new_ex(tmplibctx, NULL, TLS_server_method());
if (!TEST_ptr(sctx))
goto end;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
shared_ciphers_data[tst].maxprot,
&sctx, &cctx, cert, privkey)))
goto end;
if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
shared_ciphers_data[tst].clntciphers))
|| (shared_ciphers_data[tst].clnttls13ciphers != NULL
&& !TEST_true(SSL_CTX_set_ciphersuites(cctx,
shared_ciphers_data[tst].clnttls13ciphers)))
|| !TEST_true(SSL_CTX_set_cipher_list(sctx,
shared_ciphers_data[tst].srvrciphers))
|| (shared_ciphers_data[tst].srvrtls13ciphers != NULL
&& !TEST_true(SSL_CTX_set_ciphersuites(sctx,
shared_ciphers_data[tst].srvrtls13ciphers))))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
if (!TEST_ptr(SSL_get_shared_ciphers(serverssl, buf, sizeof(buf)))
|| !TEST_int_eq(strcmp(buf,
is_fips
? shared_ciphers_data[tst].fipsshared
: shared_ciphers_data[tst].shared),
0)) {
TEST_info("Shared ciphers are: %s\n", buf);
goto end;
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
OSSL_LIB_CTX_free(tmplibctx);
return testresult;
}
static int test_ssl_get_shared_ciphers(int tst)
{
return int_test_ssl_get_shared_ciphers(tst, 0)
&& int_test_ssl_get_shared_ciphers(tst, 1);
}
static const char *appdata = "Hello World";
static int gen_tick_called, dec_tick_called, tick_key_cb_called;
static int tick_key_renew = 0;
static SSL_TICKET_RETURN tick_dec_ret = SSL_TICKET_RETURN_ABORT;
static int gen_tick_cb(SSL *s, void *arg)
{
gen_tick_called = 1;
return SSL_SESSION_set1_ticket_appdata(SSL_get_session(s), appdata,
strlen(appdata));
}
static SSL_TICKET_RETURN dec_tick_cb(SSL *s, SSL_SESSION *ss,
const unsigned char *keyname,
size_t keyname_length,
SSL_TICKET_STATUS status,
void *arg)
{
void *tickdata;
size_t tickdlen;
dec_tick_called = 1;
if (status == SSL_TICKET_EMPTY)
return SSL_TICKET_RETURN_IGNORE_RENEW;
if (!TEST_true(status == SSL_TICKET_SUCCESS
|| status == SSL_TICKET_SUCCESS_RENEW))
return SSL_TICKET_RETURN_ABORT;
if (!TEST_true(SSL_SESSION_get0_ticket_appdata(ss, &tickdata,
&tickdlen))
|| !TEST_size_t_eq(tickdlen, strlen(appdata))
|| !TEST_int_eq(memcmp(tickdata, appdata, tickdlen), 0))
return SSL_TICKET_RETURN_ABORT;
if (tick_key_cb_called) {
/* Don't change what the ticket key callback wanted to do */
switch (status) {
case SSL_TICKET_NO_DECRYPT:
return SSL_TICKET_RETURN_IGNORE_RENEW;
case SSL_TICKET_SUCCESS:
return SSL_TICKET_RETURN_USE;
case SSL_TICKET_SUCCESS_RENEW:
return SSL_TICKET_RETURN_USE_RENEW;
default:
return SSL_TICKET_RETURN_ABORT;
}
}
return tick_dec_ret;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
static int tick_key_cb(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH], EVP_CIPHER_CTX *ctx,
HMAC_CTX *hctx, int enc)
{
const unsigned char tick_aes_key[16] = "0123456789abcdef";
const unsigned char tick_hmac_key[16] = "0123456789abcdef";
EVP_CIPHER *aes128cbc;
EVP_MD *sha256;
int ret;
tick_key_cb_called = 1;
if (tick_key_renew == -1)
return 0;
aes128cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", NULL);
if (!TEST_ptr(aes128cbc))
return 0;
sha256 = EVP_MD_fetch(libctx, "SHA-256", NULL);
if (!TEST_ptr(sha256)) {
EVP_CIPHER_free(aes128cbc);
return 0;
}
memset(iv, 0, AES_BLOCK_SIZE);
memset(key_name, 0, 16);
if (aes128cbc == NULL
|| sha256 == NULL
|| !EVP_CipherInit_ex(ctx, aes128cbc, NULL, tick_aes_key, iv, enc)
|| !HMAC_Init_ex(hctx, tick_hmac_key, sizeof(tick_hmac_key), sha256,
NULL))
ret = -1;
else
ret = tick_key_renew ? 2 : 1;
EVP_CIPHER_free(aes128cbc);
EVP_MD_free(sha256);
return ret;
}
#endif
static int tick_key_evp_cb(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *ctx, EVP_MAC_CTX *hctx, int enc)
{
const unsigned char tick_aes_key[16] = "0123456789abcdef";
unsigned char tick_hmac_key[16] = "0123456789abcdef";
OSSL_PARAM params[2];
EVP_CIPHER *aes128cbc;
int ret;
tick_key_cb_called = 1;
if (tick_key_renew == -1)
return 0;
aes128cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", NULL);
if (!TEST_ptr(aes128cbc))
return 0;
memset(iv, 0, AES_BLOCK_SIZE);
memset(key_name, 0, 16);
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
"SHA256", 0);
params[1] = OSSL_PARAM_construct_end();
if (aes128cbc == NULL
|| !EVP_CipherInit_ex(ctx, aes128cbc, NULL, tick_aes_key, iv, enc)
|| !EVP_MAC_init(hctx, tick_hmac_key, sizeof(tick_hmac_key),
params))
ret = -1;
else
ret = tick_key_renew ? 2 : 1;
EVP_CIPHER_free(aes128cbc);
return ret;
}
/*
* Test the various ticket callbacks
* Test 0: TLSv1.2, no ticket key callback, no ticket, no renewal
* Test 1: TLSv1.3, no ticket key callback, no ticket, no renewal
* Test 2: TLSv1.2, no ticket key callback, no ticket, renewal
* Test 3: TLSv1.3, no ticket key callback, no ticket, renewal
* Test 4: TLSv1.2, no ticket key callback, ticket, no renewal
* Test 5: TLSv1.3, no ticket key callback, ticket, no renewal
* Test 6: TLSv1.2, no ticket key callback, ticket, renewal
* Test 7: TLSv1.3, no ticket key callback, ticket, renewal
* Test 8: TLSv1.2, old ticket key callback, ticket, no renewal
* Test 9: TLSv1.3, old ticket key callback, ticket, no renewal
* Test 10: TLSv1.2, old ticket key callback, ticket, renewal
* Test 11: TLSv1.3, old ticket key callback, ticket, renewal
* Test 12: TLSv1.2, old ticket key callback, no ticket
* Test 13: TLSv1.3, old ticket key callback, no ticket
* Test 14: TLSv1.2, ticket key callback, ticket, no renewal
* Test 15: TLSv1.3, ticket key callback, ticket, no renewal
* Test 16: TLSv1.2, ticket key callback, ticket, renewal
* Test 17: TLSv1.3, ticket key callback, ticket, renewal
* Test 18: TLSv1.2, ticket key callback, no ticket
* Test 19: TLSv1.3, ticket key callback, no ticket
*/
static int test_ticket_callbacks(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
SSL_SESSION *clntsess = NULL;
int testresult = 0;
#ifdef OPENSSL_NO_TLS1_2
if (tst % 2 == 0)
return 1;
#endif
#ifdef OSSL_NO_USABLE_TLS1_3
if (tst % 2 == 1)
return 1;
#endif
#ifdef OPENSSL_NO_DEPRECATED_3_0
if (tst >= 8 && tst <= 13)
return 1;
#endif
gen_tick_called = dec_tick_called = tick_key_cb_called = 0;
/* Which tests the ticket key callback should request renewal for */
if (tst == 10 || tst == 11 || tst == 16 || tst == 17)
tick_key_renew = 1;
else if (tst == 12 || tst == 13 || tst == 18 || tst == 19)
tick_key_renew = -1; /* abort sending the ticket/0-length ticket */
else
tick_key_renew = 0;
/* Which tests the decrypt ticket callback should request renewal for */
switch (tst) {
case 0:
case 1:
tick_dec_ret = SSL_TICKET_RETURN_IGNORE;
break;
case 2:
case 3:
tick_dec_ret = SSL_TICKET_RETURN_IGNORE_RENEW;
break;
case 4:
case 5:
tick_dec_ret = SSL_TICKET_RETURN_USE;
break;
case 6:
case 7:
tick_dec_ret = SSL_TICKET_RETURN_USE_RENEW;
break;
default:
tick_dec_ret = SSL_TICKET_RETURN_ABORT;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
((tst % 2) == 0) ? TLS1_2_VERSION
: TLS1_3_VERSION,
&sctx, &cctx, cert, privkey)))
goto end;
/*
* We only want sessions to resume from tickets - not the session cache. So
* switch the cache off.
*/
if (!TEST_true(SSL_CTX_set_session_cache_mode(sctx, SSL_SESS_CACHE_OFF)))
goto end;
if (!TEST_true(SSL_CTX_set_session_ticket_cb(sctx, gen_tick_cb, dec_tick_cb,
NULL)))
goto end;
if (tst >= 14) {
if (!TEST_true(SSL_CTX_set_tlsext_ticket_key_evp_cb(sctx, tick_key_evp_cb)))
goto end;
#ifndef OPENSSL_NO_DEPRECATED_3_0
} else if (tst >= 8) {
if (!TEST_true(SSL_CTX_set_tlsext_ticket_key_cb(sctx, tick_key_cb)))
goto end;
#endif
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
/*
* The decrypt ticket key callback in TLSv1.2 should be called even though
* we have no ticket yet, because it gets called with a status of
* SSL_TICKET_EMPTY (the client indicates support for tickets but does not
* actually send any ticket data). This does not happen in TLSv1.3 because
* it is not valid to send empty ticket data in TLSv1.3.
*/
if (!TEST_int_eq(gen_tick_called, 1)
|| !TEST_int_eq(dec_tick_called, ((tst % 2) == 0) ? 1 : 0))
goto end;
gen_tick_called = dec_tick_called = 0;
clntsess = SSL_get1_session(clientssl);
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/* Now do a resumption */
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
NULL))
|| !TEST_true(SSL_set_session(clientssl, clntsess))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
if (tick_dec_ret == SSL_TICKET_RETURN_IGNORE
|| tick_dec_ret == SSL_TICKET_RETURN_IGNORE_RENEW
|| tick_key_renew == -1) {
if (!TEST_false(SSL_session_reused(clientssl)))
goto end;
} else {
if (!TEST_true(SSL_session_reused(clientssl)))
goto end;
}
if (!TEST_int_eq(gen_tick_called,
(tick_key_renew
|| tick_dec_ret == SSL_TICKET_RETURN_IGNORE_RENEW
|| tick_dec_ret == SSL_TICKET_RETURN_USE_RENEW)
? 1 : 0)
/* There is no ticket to decrypt in tests 13 and 19 */
|| !TEST_int_eq(dec_tick_called, (tst == 13 || tst == 19) ? 0 : 1))
goto end;
testresult = 1;
end:
SSL_SESSION_free(clntsess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test incorrect shutdown.
* Test 0: client does not shutdown properly,
* server does not set SSL_OP_IGNORE_UNEXPECTED_EOF,
* server should get SSL_ERROR_SSL
* Test 1: client does not shutdown properly,
* server sets SSL_OP_IGNORE_UNEXPECTED_EOF,
* server should get SSL_ERROR_ZERO_RETURN
*/
static int test_incorrect_shutdown(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
char buf[80];
BIO *c2s;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), 0, 0,
&sctx, &cctx, cert, privkey)))
goto end;
if (tst == 1)
SSL_CTX_set_options(sctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
c2s = SSL_get_rbio(serverssl);
BIO_set_mem_eof_return(c2s, 0);
if (!TEST_false(SSL_read(serverssl, buf, sizeof(buf))))
goto end;
if (tst == 0 && !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_SSL) )
goto end;
if (tst == 1 && !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_ZERO_RETURN) )
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test bi-directional shutdown.
* Test 0: TLSv1.2
* Test 1: TLSv1.2, server continues to read/write after client shutdown
* Test 2: TLSv1.3, no pending NewSessionTicket messages
* Test 3: TLSv1.3, pending NewSessionTicket messages
* Test 4: TLSv1.3, server continues to read/write after client shutdown, server
* sends key update, client reads it
* Test 5: TLSv1.3, server continues to read/write after client shutdown, server
* sends CertificateRequest, client reads and ignores it
* Test 6: TLSv1.3, server continues to read/write after client shutdown, client
* doesn't read it
*/
static int test_shutdown(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
char msg[] = "A test message";
char buf[80];
size_t written, readbytes;
SSL_SESSION *sess;
#ifdef OPENSSL_NO_TLS1_2
if (tst <= 1)
return 1;
#endif
#ifdef OSSL_NO_USABLE_TLS1_3
if (tst >= 2)
return 1;
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
(tst <= 1) ? TLS1_2_VERSION
: TLS1_3_VERSION,
&sctx, &cctx, cert, privkey)))
goto end;
if (tst == 5)
SSL_CTX_set_post_handshake_auth(cctx, 1);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (tst == 3) {
if (!TEST_true(create_bare_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE, 1))
|| !TEST_ptr_ne(sess = SSL_get_session(clientssl), NULL)
|| !TEST_false(SSL_SESSION_is_resumable(sess)))
goto end;
} else if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
|| !TEST_ptr_ne(sess = SSL_get_session(clientssl), NULL)
|| !TEST_true(SSL_SESSION_is_resumable(sess))) {
goto end;
}
if (!TEST_int_eq(SSL_shutdown(clientssl), 0))
goto end;
if (tst >= 4) {
/*
* Reading on the server after the client has sent close_notify should
* fail and provide SSL_ERROR_ZERO_RETURN
*/
if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_int_eq(SSL_get_error(serverssl, 0),
SSL_ERROR_ZERO_RETURN)
|| !TEST_int_eq(SSL_get_shutdown(serverssl),
SSL_RECEIVED_SHUTDOWN)
/*
* Even though we're shutdown on receive we should still be
* able to write.
*/
|| !TEST_true(SSL_write(serverssl, msg, sizeof(msg))))
goto end;
if (tst == 4
&& !TEST_true(SSL_key_update(serverssl,
SSL_KEY_UPDATE_REQUESTED)))
goto end;
if (tst == 5) {
SSL_set_verify(serverssl, SSL_VERIFY_PEER, NULL);
if (!TEST_true(SSL_verify_client_post_handshake(serverssl)))
goto end;
}
if ((tst == 4 || tst == 5)
&& !TEST_true(SSL_write(serverssl, msg, sizeof(msg))))
goto end;
if (!TEST_int_eq(SSL_shutdown(serverssl), 1))
goto end;
if (tst == 4 || tst == 5) {
/* Should still be able to read data from server */
if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf),
&readbytes))
|| !TEST_size_t_eq(readbytes, sizeof(msg))
|| !TEST_int_eq(memcmp(msg, buf, readbytes), 0)
|| !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf),
&readbytes))
|| !TEST_size_t_eq(readbytes, sizeof(msg))
|| !TEST_int_eq(memcmp(msg, buf, readbytes), 0))
goto end;
}
}
/* Writing on the client after sending close_notify shouldn't be possible */
if (!TEST_false(SSL_write_ex(clientssl, msg, sizeof(msg), &written)))
goto end;
if (tst < 4) {
/*
* For these tests the client has sent close_notify but it has not yet
* been received by the server. The server has not sent close_notify
* yet.
*/
if (!TEST_int_eq(SSL_shutdown(serverssl), 0)
/*
* Writing on the server after sending close_notify shouldn't
* be possible.
*/
|| !TEST_false(SSL_write_ex(serverssl, msg, sizeof(msg), &written))
|| !TEST_int_eq(SSL_shutdown(clientssl), 1)
|| !TEST_ptr_ne(sess = SSL_get_session(clientssl), NULL)
|| !TEST_true(SSL_SESSION_is_resumable(sess))
|| !TEST_int_eq(SSL_shutdown(serverssl), 1))
goto end;
} else if (tst == 4 || tst == 5) {
/*
* In this test the client has sent close_notify and it has been
* received by the server which has responded with a close_notify. The
* client needs to read the close_notify sent by the server.
*/
if (!TEST_int_eq(SSL_shutdown(clientssl), 1)
|| !TEST_ptr_ne(sess = SSL_get_session(clientssl), NULL)
|| !TEST_true(SSL_SESSION_is_resumable(sess)))
goto end;
} else {
/*
* tst == 6
*
* The client has sent close_notify and is expecting a close_notify
* back, but instead there is application data first. The shutdown
* should fail with a fatal error.
*/
if (!TEST_int_eq(SSL_shutdown(clientssl), -1)
|| !TEST_int_eq(SSL_get_error(clientssl, -1), SSL_ERROR_SSL))
goto end;
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3)
static int cert_cb_cnt;
static int cert_cb(SSL *s, void *arg)
{
SSL_CTX *ctx = (SSL_CTX *)arg;
BIO *in = NULL;
EVP_PKEY *pkey = NULL;
X509 *x509 = NULL, *rootx = NULL;
STACK_OF(X509) *chain = NULL;
char *rootfile = NULL, *ecdsacert = NULL, *ecdsakey = NULL;
int ret = 0;
if (cert_cb_cnt == 0) {
/* Suspend the handshake */
cert_cb_cnt++;
return -1;
} else if (cert_cb_cnt == 1) {
/*
* Update the SSL_CTX, set the certificate and private key and then
* continue the handshake normally.
*/
if (ctx != NULL && !TEST_ptr(SSL_set_SSL_CTX(s, ctx)))
return 0;
if (!TEST_true(SSL_use_certificate_file(s, cert, SSL_FILETYPE_PEM))
|| !TEST_true(SSL_use_PrivateKey_file(s, privkey,
SSL_FILETYPE_PEM))
|| !TEST_true(SSL_check_private_key(s)))
return 0;
cert_cb_cnt++;
return 1;
} else if (cert_cb_cnt == 3) {
int rv;
rootfile = test_mk_file_path(certsdir, "rootcert.pem");
ecdsacert = test_mk_file_path(certsdir, "server-ecdsa-cert.pem");
ecdsakey = test_mk_file_path(certsdir, "server-ecdsa-key.pem");
if (!TEST_ptr(rootfile) || !TEST_ptr(ecdsacert) || !TEST_ptr(ecdsakey))
goto out;
chain = sk_X509_new_null();
if (!TEST_ptr(chain))
goto out;
if (!TEST_ptr(in = BIO_new(BIO_s_file()))
|| !TEST_int_gt(BIO_read_filename(in, rootfile), 0)
|| !TEST_ptr(rootx = X509_new_ex(libctx, NULL))
|| !TEST_ptr(PEM_read_bio_X509(in, &rootx, NULL, NULL))
|| !TEST_true(sk_X509_push(chain, rootx)))
goto out;
rootx = NULL;
BIO_free(in);
if (!TEST_ptr(in = BIO_new(BIO_s_file()))
|| !TEST_int_gt(BIO_read_filename(in, ecdsacert), 0)
|| !TEST_ptr(x509 = X509_new_ex(libctx, NULL))
|| !TEST_ptr(PEM_read_bio_X509(in, &x509, NULL, NULL)))
goto out;
BIO_free(in);
if (!TEST_ptr(in = BIO_new(BIO_s_file()))
|| !TEST_int_gt(BIO_read_filename(in, ecdsakey), 0)
|| !TEST_ptr(pkey = PEM_read_bio_PrivateKey_ex(in, NULL,
NULL, NULL,
libctx, NULL)))
goto out;
rv = SSL_check_chain(s, x509, pkey, chain);
/*
* If the cert doesn't show as valid here (e.g., because we don't
* have any shared sigalgs), then we will not set it, and there will
* be no certificate at all on the SSL or SSL_CTX. This, in turn,
* will cause tls_choose_sigalgs() to fail the connection.
*/
if ((rv & (CERT_PKEY_VALID | CERT_PKEY_CA_SIGNATURE))
== (CERT_PKEY_VALID | CERT_PKEY_CA_SIGNATURE)) {
if (!SSL_use_cert_and_key(s, x509, pkey, NULL, 1))
goto out;
}
ret = 1;
}
/* Abort the handshake */
out:
OPENSSL_free(ecdsacert);
OPENSSL_free(ecdsakey);
OPENSSL_free(rootfile);
BIO_free(in);
EVP_PKEY_free(pkey);
X509_free(x509);
X509_free(rootx);
sk_X509_pop_free(chain, X509_free);
return ret;
}
/*
* Test the certificate callback.
* Test 0: Callback fails
* Test 1: Success - no SSL_set_SSL_CTX() in the callback
* Test 2: Success - SSL_set_SSL_CTX() in the callback
* Test 3: Success - Call SSL_check_chain from the callback
* Test 4: Failure - SSL_check_chain fails from callback due to bad cert in the
* chain
* Test 5: Failure - SSL_check_chain fails from callback due to bad ee cert
*/
static int test_cert_cb_int(int prot, int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL, *snictx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0, ret;
#ifdef OPENSSL_NO_EC
/* We use an EC cert in these tests, so we skip in a no-ec build */
if (tst >= 3)
return 1;
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
prot,
&sctx, &cctx, NULL, NULL)))
goto end;
if (tst == 0)
cert_cb_cnt = -1;
else if (tst >= 3)
cert_cb_cnt = 3;
else
cert_cb_cnt = 0;
if (tst == 2) {
snictx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method());
if (!TEST_ptr(snictx))
goto end;
}
SSL_CTX_set_cert_cb(sctx, cert_cb, snictx);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (tst == 4) {
/*
* We cause SSL_check_chain() to fail by specifying sig_algs that
* the chain doesn't meet (the root uses an RSA cert)
*/
if (!TEST_true(SSL_set1_sigalgs_list(clientssl,
"ecdsa_secp256r1_sha256")))
goto end;
} else if (tst == 5) {
/*
* We cause SSL_check_chain() to fail by specifying sig_algs that
* the ee cert doesn't meet (the ee uses an ECDSA cert)
*/
if (!TEST_true(SSL_set1_sigalgs_list(clientssl,
"rsa_pss_rsae_sha256:rsa_pkcs1_sha256")))
goto end;
}
ret = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE);
if (!TEST_true(tst == 0 || tst == 4 || tst == 5 ? !ret : ret)
|| (tst > 0
&& !TEST_int_eq((cert_cb_cnt - 2) * (cert_cb_cnt - 3), 0))) {
goto end;
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
SSL_CTX_free(snictx);
return testresult;
}
#endif
static int test_cert_cb(int tst)
{
int testresult = 1;
#ifndef OPENSSL_NO_TLS1_2
testresult &= test_cert_cb_int(TLS1_2_VERSION, tst);
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
testresult &= test_cert_cb_int(TLS1_3_VERSION, tst);
#endif
return testresult;
}
static int client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
X509 *xcert;
EVP_PKEY *privpkey;
BIO *in = NULL;
BIO *priv_in = NULL;
/* Check that SSL_get0_peer_certificate() returns something sensible */
if (!TEST_ptr(SSL_get0_peer_certificate(ssl)))
return 0;
in = BIO_new_file(cert, "r");
if (!TEST_ptr(in))
return 0;
if (!TEST_ptr(xcert = X509_new_ex(libctx, NULL))
|| !TEST_ptr(PEM_read_bio_X509(in, &xcert, NULL, NULL))
|| !TEST_ptr(priv_in = BIO_new_file(privkey, "r"))
|| !TEST_ptr(privpkey = PEM_read_bio_PrivateKey_ex(priv_in, NULL,
NULL, NULL,
libctx, NULL)))
goto err;
*x509 = xcert;
*pkey = privpkey;
BIO_free(in);
BIO_free(priv_in);
return 1;
err:
X509_free(xcert);
BIO_free(in);
BIO_free(priv_in);
return 0;
}
static int test_client_cert_cb(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
#ifdef OPENSSL_NO_TLS1_2
if (tst == 0)
return 1;
#endif
#ifdef OSSL_NO_USABLE_TLS1_3
if (tst == 1)
return 1;
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
tst == 0 ? TLS1_2_VERSION
: TLS1_3_VERSION,
&sctx, &cctx, cert, privkey)))
goto end;
/*
* Test that setting a client_cert_cb results in a client certificate being
* sent.
*/
SSL_CTX_set_client_cert_cb(cctx, client_cert_cb);
SSL_CTX_set_verify(sctx,
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
verify_cb);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3)
/*
* Test setting certificate authorities on both client and server.
*
* Test 0: SSL_CTX_set0_CA_list() only
* Test 1: Both SSL_CTX_set0_CA_list() and SSL_CTX_set_client_CA_list()
* Test 2: Only SSL_CTX_set_client_CA_list()
*/
static int test_ca_names_int(int prot, int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
size_t i;
X509_NAME *name[] = { NULL, NULL, NULL, NULL };
char *strnames[] = { "Jack", "Jill", "John", "Joanne" };
STACK_OF(X509_NAME) *sk1 = NULL, *sk2 = NULL;
const STACK_OF(X509_NAME) *sktmp = NULL;
for (i = 0; i < OSSL_NELEM(name); i++) {
name[i] = X509_NAME_new();
if (!TEST_ptr(name[i])
|| !TEST_true(X509_NAME_add_entry_by_txt(name[i], "CN",
MBSTRING_ASC,
(unsigned char *)
strnames[i],
-1, -1, 0)))
goto end;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
prot,
&sctx, &cctx, cert, privkey)))
goto end;
SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, NULL);
if (tst == 0 || tst == 1) {
if (!TEST_ptr(sk1 = sk_X509_NAME_new_null())
|| !TEST_true(sk_X509_NAME_push(sk1, X509_NAME_dup(name[0])))
|| !TEST_true(sk_X509_NAME_push(sk1, X509_NAME_dup(name[1])))
|| !TEST_ptr(sk2 = sk_X509_NAME_new_null())
|| !TEST_true(sk_X509_NAME_push(sk2, X509_NAME_dup(name[0])))
|| !TEST_true(sk_X509_NAME_push(sk2, X509_NAME_dup(name[1]))))
goto end;
SSL_CTX_set0_CA_list(sctx, sk1);
SSL_CTX_set0_CA_list(cctx, sk2);
sk1 = sk2 = NULL;
}
if (tst == 1 || tst == 2) {
if (!TEST_ptr(sk1 = sk_X509_NAME_new_null())
|| !TEST_true(sk_X509_NAME_push(sk1, X509_NAME_dup(name[2])))
|| !TEST_true(sk_X509_NAME_push(sk1, X509_NAME_dup(name[3])))
|| !TEST_ptr(sk2 = sk_X509_NAME_new_null())
|| !TEST_true(sk_X509_NAME_push(sk2, X509_NAME_dup(name[2])))
|| !TEST_true(sk_X509_NAME_push(sk2, X509_NAME_dup(name[3]))))
goto end;
SSL_CTX_set_client_CA_list(sctx, sk1);
SSL_CTX_set_client_CA_list(cctx, sk2);
sk1 = sk2 = NULL;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
/*
* We only expect certificate authorities to have been sent to the server
* if we are using TLSv1.3 and SSL_set0_CA_list() was used
*/
sktmp = SSL_get0_peer_CA_list(serverssl);
if (prot == TLS1_3_VERSION
&& (tst == 0 || tst == 1)) {
if (!TEST_ptr(sktmp)
|| !TEST_int_eq(sk_X509_NAME_num(sktmp), 2)
|| !TEST_int_eq(X509_NAME_cmp(sk_X509_NAME_value(sktmp, 0),
name[0]), 0)
|| !TEST_int_eq(X509_NAME_cmp(sk_X509_NAME_value(sktmp, 1),
name[1]), 0))
goto end;
} else if (!TEST_ptr_null(sktmp)) {
goto end;
}
/*
* In all tests we expect certificate authorities to have been sent to the
* client. However, SSL_set_client_CA_list() should override
* SSL_set0_CA_list()
*/
sktmp = SSL_get0_peer_CA_list(clientssl);
if (!TEST_ptr(sktmp)
|| !TEST_int_eq(sk_X509_NAME_num(sktmp), 2)
|| !TEST_int_eq(X509_NAME_cmp(sk_X509_NAME_value(sktmp, 0),
name[tst == 0 ? 0 : 2]), 0)
|| !TEST_int_eq(X509_NAME_cmp(sk_X509_NAME_value(sktmp, 1),
name[tst == 0 ? 1 : 3]), 0))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
for (i = 0; i < OSSL_NELEM(name); i++)
X509_NAME_free(name[i]);
sk_X509_NAME_pop_free(sk1, X509_NAME_free);
sk_X509_NAME_pop_free(sk2, X509_NAME_free);
return testresult;
}
#endif
static int test_ca_names(int tst)
{
int testresult = 1;
#ifndef OPENSSL_NO_TLS1_2
testresult &= test_ca_names_int(TLS1_2_VERSION, tst);
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
testresult &= test_ca_names_int(TLS1_3_VERSION, tst);
#endif
return testresult;
}
#ifndef OPENSSL_NO_TLS1_2
static const char *multiblock_cipherlist_data[]=
{
"AES128-SHA",
"AES128-SHA256",
"AES256-SHA",
"AES256-SHA256",
};
/* Reduce the fragment size - so the multiblock test buffer can be small */
# define MULTIBLOCK_FRAGSIZE 512
static int test_multiblock_write(int test_index)
{
static const char *fetchable_ciphers[]=
{
"AES-128-CBC-HMAC-SHA1",
"AES-128-CBC-HMAC-SHA256",
"AES-256-CBC-HMAC-SHA1",
"AES-256-CBC-HMAC-SHA256"
};
const char *cipherlist = multiblock_cipherlist_data[test_index];
const SSL_METHOD *smeth = TLS_server_method();
const SSL_METHOD *cmeth = TLS_client_method();
int min_version = TLS1_VERSION;
int max_version = TLS1_2_VERSION; /* Don't select TLS1_3 */
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
/*
* Choose a buffer large enough to perform a multi-block operation
* i.e: write_len >= 4 * frag_size
* 9 * is chosen so that multiple multiblocks are used + some leftover.
*/
unsigned char msg[MULTIBLOCK_FRAGSIZE * 9];
unsigned char buf[sizeof(msg)], *p = buf;
size_t readbytes, written, len;
EVP_CIPHER *ciph = NULL;
/*
* Check if the cipher exists before attempting to use it since it only has
* a hardware specific implementation.
*/
ciph = EVP_CIPHER_fetch(libctx, fetchable_ciphers[test_index], "");
if (ciph == NULL) {
TEST_skip("Multiblock cipher is not available for %s", cipherlist);
return 1;
}
EVP_CIPHER_free(ciph);
/* Set up a buffer with some data that will be sent to the client */
RAND_bytes(msg, sizeof(msg));
if (!TEST_true(create_ssl_ctx_pair(libctx, smeth, cmeth, min_version,
max_version, &sctx, &cctx, cert,
privkey)))
goto end;
if (!TEST_true(SSL_CTX_set_max_send_fragment(sctx, MULTIBLOCK_FRAGSIZE)))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
/* settings to force it to use AES-CBC-HMAC_SHA */
SSL_set_options(serverssl, SSL_OP_NO_ENCRYPT_THEN_MAC);
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, cipherlist)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
if (!TEST_true(SSL_write_ex(serverssl, msg, sizeof(msg), &written))
|| !TEST_size_t_eq(written, sizeof(msg)))
goto end;
len = written;
while (len > 0) {
if (!TEST_true(SSL_read_ex(clientssl, p, MULTIBLOCK_FRAGSIZE, &readbytes)))
goto end;
p += readbytes;
len -= readbytes;
}
if (!TEST_mem_eq(msg, sizeof(msg), buf, sizeof(buf)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif /* OPENSSL_NO_TLS1_2 */
static int test_session_timeout(int test)
{
/*
* Test session ordering and timeout
* Can't explicitly test performance of the new code,
* but can test to see if the ordering of the sessions
* are correct, and they they are removed as expected
*/
SSL_SESSION *early = NULL;
SSL_SESSION *middle = NULL;
SSL_SESSION *late = NULL;
SSL_CTX *ctx;
int testresult = 0;
long now = (long)time(NULL);
#define TIMEOUT 10
if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_method()))
|| !TEST_ptr(early = SSL_SESSION_new())
|| !TEST_ptr(middle = SSL_SESSION_new())
|| !TEST_ptr(late = SSL_SESSION_new()))
goto end;
/* assign unique session ids */
early->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
memset(early->session_id, 1, SSL3_SSL_SESSION_ID_LENGTH);
middle->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
memset(middle->session_id, 2, SSL3_SSL_SESSION_ID_LENGTH);
late->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
memset(late->session_id, 3, SSL3_SSL_SESSION_ID_LENGTH);
if (!TEST_int_eq(SSL_CTX_add_session(ctx, early), 1)
|| !TEST_int_eq(SSL_CTX_add_session(ctx, middle), 1)
|| !TEST_int_eq(SSL_CTX_add_session(ctx, late), 1))
goto end;
/* Make sure they are all added */
if (!TEST_ptr(early->prev)
|| !TEST_ptr(middle->prev)
|| !TEST_ptr(late->prev))
goto end;
if (!TEST_int_ne(SSL_SESSION_set_time(early, now - 10), 0)
|| !TEST_int_ne(SSL_SESSION_set_time(middle, now), 0)
|| !TEST_int_ne(SSL_SESSION_set_time(late, now + 10), 0))
goto end;
if (!TEST_int_ne(SSL_SESSION_set_timeout(early, TIMEOUT), 0)
|| !TEST_int_ne(SSL_SESSION_set_timeout(middle, TIMEOUT), 0)
|| !TEST_int_ne(SSL_SESSION_set_timeout(late, TIMEOUT), 0))
goto end;
/* Make sure they are all still there */
if (!TEST_ptr(early->prev)
|| !TEST_ptr(middle->prev)
|| !TEST_ptr(late->prev))
goto end;
/* Make sure they are in the expected order */
if (!TEST_ptr_eq(late->next, middle)
|| !TEST_ptr_eq(middle->next, early)
|| !TEST_ptr_eq(early->prev, middle)
|| !TEST_ptr_eq(middle->prev, late))
goto end;
/* This should remove "early" */
SSL_CTX_flush_sessions(ctx, now + TIMEOUT - 1);
if (!TEST_ptr_null(early->prev)
|| !TEST_ptr(middle->prev)
|| !TEST_ptr(late->prev))
goto end;
/* This should remove "middle" */
SSL_CTX_flush_sessions(ctx, now + TIMEOUT + 1);
if (!TEST_ptr_null(early->prev)
|| !TEST_ptr_null(middle->prev)
|| !TEST_ptr(late->prev))
goto end;
/* This should remove "late" */
SSL_CTX_flush_sessions(ctx, now + TIMEOUT + 11);
if (!TEST_ptr_null(early->prev)
|| !TEST_ptr_null(middle->prev)
|| !TEST_ptr_null(late->prev))
goto end;
/* Add them back in again */
if (!TEST_int_eq(SSL_CTX_add_session(ctx, early), 1)
|| !TEST_int_eq(SSL_CTX_add_session(ctx, middle), 1)
|| !TEST_int_eq(SSL_CTX_add_session(ctx, late), 1))
goto end;
/* Make sure they are all added */
if (!TEST_ptr(early->prev)
|| !TEST_ptr(middle->prev)
|| !TEST_ptr(late->prev))
goto end;
/* This should remove all of them */
SSL_CTX_flush_sessions(ctx, 0);
if (!TEST_ptr_null(early->prev)
|| !TEST_ptr_null(middle->prev)
|| !TEST_ptr_null(late->prev))
goto end;
(void)SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_UPDATE_TIME
| SSL_CTX_get_session_cache_mode(ctx));
/* make sure |now| is NOT equal to the current time */
now -= 10;
if (!TEST_int_ne(SSL_SESSION_set_time(early, now), 0)
|| !TEST_int_eq(SSL_CTX_add_session(ctx, early), 1)
|| !TEST_long_ne(SSL_SESSION_get_time(early), now))
goto end;
testresult = 1;
end:
SSL_CTX_free(ctx);
SSL_SESSION_free(early);
SSL_SESSION_free(middle);
SSL_SESSION_free(late);
return testresult;
}
/*
* Test that a session cache overflow works as expected
* Test 0: TLSv1.3, timeout on new session later than old session
* Test 1: TLSv1.2, timeout on new session later than old session
* Test 2: TLSv1.3, timeout on new session earlier than old session
* Test 3: TLSv1.2, timeout on new session earlier than old session
*/
#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
static int test_session_cache_overflow(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
#ifdef OSSL_NO_USABLE_TLS1_3
/* If no TLSv1.3 available then do nothing in this case */
if (idx % 2 == 0)
return TEST_skip("No TLSv1.3 available");
#endif
#ifdef OPENSSL_NO_TLS1_2
/* If no TLSv1.2 available then do nothing in this case */
if (idx % 2 == 1)
return TEST_skip("No TLSv1.2 available");
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION,
(idx % 2 == 0) ? TLS1_3_VERSION
: TLS1_2_VERSION,
&sctx, &cctx, cert, privkey))
|| !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET)))
goto end;
SSL_CTX_sess_set_get_cb(sctx, get_session_cb);
get_sess_val = NULL;
SSL_CTX_sess_set_cache_size(sctx, 1);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
if (idx > 1) {
sess = SSL_get_session(serverssl);
if (!TEST_ptr(sess))
goto end;
/*
* Cause this session to have a longer timeout than the next session to
* be added.
*/
if (!TEST_true(SSL_SESSION_set_timeout(sess, LONG_MAX / 2))) {
sess = NULL;
goto end;
}
sess = NULL;
}
SSL_shutdown(serverssl);
SSL_shutdown(clientssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
/*
* Session cache size is 1 and we already populated the cache with a session
* so the next connection should cause an overflow.
*/
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
/*
* The session we just negotiated may have been already removed from the
* internal cache - but we will return it anyway from our external cache.
*/
get_sess_val = SSL_get_session(serverssl);
if (!TEST_ptr(get_sess_val))
goto end;
sess = SSL_get1_session(clientssl);
if (!TEST_ptr(sess))
goto end;
SSL_shutdown(serverssl);
SSL_shutdown(clientssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(SSL_set_session(clientssl, sess)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
SSL_SESSION_free(sess);
return testresult;
}
#endif /* !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) */
/*
* Test 0: Client sets servername and server acknowledges it (TLSv1.2)
* Test 1: Client sets servername and server does not acknowledge it (TLSv1.2)
* Test 2: Client sets inconsistent servername on resumption (TLSv1.2)
* Test 3: Client does not set servername on initial handshake (TLSv1.2)
* Test 4: Client does not set servername on resumption handshake (TLSv1.2)
* Test 5: Client sets servername and server acknowledges it (TLSv1.3)
* Test 6: Client sets servername and server does not acknowledge it (TLSv1.3)
* Test 7: Client sets inconsistent servername on resumption (TLSv1.3)
* Test 8: Client does not set servername on initial handshake(TLSv1.3)
* Test 9: Client does not set servername on resumption handshake (TLSv1.3)
*/
static int test_servername(int tst)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
const char *sexpectedhost = NULL, *cexpectedhost = NULL;
#ifdef OPENSSL_NO_TLS1_2
if (tst <= 4)
return 1;
#endif
#ifdef OSSL_NO_USABLE_TLS1_3
if (tst >= 5)
return 1;
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
(tst <= 4) ? TLS1_2_VERSION
: TLS1_3_VERSION,
&sctx, &cctx, cert, privkey))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (tst != 1 && tst != 6) {
if (!TEST_true(SSL_CTX_set_tlsext_servername_callback(sctx,
hostname_cb)))
goto end;
}
if (tst != 3 && tst != 8) {
if (!TEST_true(SSL_set_tlsext_host_name(clientssl, "goodhost")))
goto end;
sexpectedhost = cexpectedhost = "goodhost";
}
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
if (!TEST_str_eq(SSL_get_servername(clientssl, TLSEXT_NAMETYPE_host_name),
cexpectedhost)
|| !TEST_str_eq(SSL_get_servername(serverssl,
TLSEXT_NAMETYPE_host_name),
sexpectedhost))
goto end;
/* Now repeat with a resumption handshake */
if (!TEST_int_eq(SSL_shutdown(clientssl), 0)
|| !TEST_ptr_ne(sess = SSL_get1_session(clientssl), NULL)
|| !TEST_true(SSL_SESSION_is_resumable(sess))
|| !TEST_int_eq(SSL_shutdown(serverssl), 0))
goto end;
SSL_free(clientssl);
SSL_free(serverssl);
clientssl = serverssl = NULL;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
NULL)))
goto end;
if (!TEST_true(SSL_set_session(clientssl, sess)))
goto end;
sexpectedhost = cexpectedhost = "goodhost";
if (tst == 2 || tst == 7) {
/* Set an inconsistent hostname */
if (!TEST_true(SSL_set_tlsext_host_name(clientssl, "altgoodhost")))
goto end;
/*
* In TLSv1.2 we expect the hostname from the original handshake, in
* TLSv1.3 we expect the hostname from this handshake
*/
if (tst == 7)
sexpectedhost = cexpectedhost = "altgoodhost";
if (!TEST_str_eq(SSL_get_servername(clientssl,
TLSEXT_NAMETYPE_host_name),
"altgoodhost"))
goto end;
} else if (tst == 4 || tst == 9) {
/*
* A TLSv1.3 session does not associate a session with a servername,
* but a TLSv1.2 session does.
*/
if (tst == 9)
sexpectedhost = cexpectedhost = NULL;
if (!TEST_str_eq(SSL_get_servername(clientssl,
TLSEXT_NAMETYPE_host_name),
cexpectedhost))
goto end;
} else {
if (!TEST_true(SSL_set_tlsext_host_name(clientssl, "goodhost")))
goto end;
/*
* In a TLSv1.2 resumption where the hostname was not acknowledged
* we expect the hostname on the server to be empty. On the client we
* return what was requested in this case.
*
* Similarly if the client didn't set a hostname on an original TLSv1.2
* session but is now, the server hostname will be empty, but the client
* is as we set it.
*/
if (tst == 1 || tst == 3)
sexpectedhost = NULL;
if (!TEST_str_eq(SSL_get_servername(clientssl,
TLSEXT_NAMETYPE_host_name),
"goodhost"))
goto end;
}
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
if (!TEST_true(SSL_session_reused(clientssl))
|| !TEST_true(SSL_session_reused(serverssl))
|| !TEST_str_eq(SSL_get_servername(clientssl,
TLSEXT_NAMETYPE_host_name),
cexpectedhost)
|| !TEST_str_eq(SSL_get_servername(serverssl,
TLSEXT_NAMETYPE_host_name),
sexpectedhost))
goto end;
testresult = 1;
end:
SSL_SESSION_free(sess);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#if !defined(OPENSSL_NO_EC) \
&& (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2))
/*
* Test that if signature algorithms are not available, then we do not offer or
* accept them.
* Test 0: Two RSA sig algs available: both RSA sig algs shared
* Test 1: The client only has SHA2-256: only SHA2-256 algorithms shared
* Test 2: The server only has SHA2-256: only SHA2-256 algorithms shared
* Test 3: An RSA and an ECDSA sig alg available: both sig algs shared
* Test 4: The client only has an ECDSA sig alg: only ECDSA algorithms shared
* Test 5: The server only has an ECDSA sig alg: only ECDSA algorithms shared
*/
static int test_sigalgs_available(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
OSSL_LIB_CTX *tmpctx = OSSL_LIB_CTX_new();
OSSL_LIB_CTX *clientctx = libctx, *serverctx = libctx;
OSSL_PROVIDER *filterprov = NULL;
int sig, hash;
if (!TEST_ptr(tmpctx))
goto end;
if (idx != 0 && idx != 3) {
if (!TEST_true(OSSL_PROVIDER_add_builtin(tmpctx, "filter",
filter_provider_init)))
goto end;
filterprov = OSSL_PROVIDER_load(tmpctx, "filter");
if (!TEST_ptr(filterprov))
goto end;
if (idx < 3) {
/*
* Only enable SHA2-256 so rsa_pss_rsae_sha384 should not be offered
* or accepted for the peer that uses this libctx. Note that libssl
* *requires* SHA2-256 to be available so we cannot disable that. We
* also need SHA1 for our certificate.
*/
if (!TEST_true(filter_provider_set_filter(OSSL_OP_DIGEST,
"SHA2-256:SHA1")))
goto end;
} else {
if (!TEST_true(filter_provider_set_filter(OSSL_OP_SIGNATURE,
"ECDSA"))
|| !TEST_true(filter_provider_set_filter(OSSL_OP_KEYMGMT,
"EC:X25519:X448")))
goto end;
}
if (idx == 1 || idx == 4)
clientctx = tmpctx;
else
serverctx = tmpctx;
}
cctx = SSL_CTX_new_ex(clientctx, NULL, TLS_client_method());
sctx = SSL_CTX_new_ex(serverctx, NULL, TLS_server_method());
if (!TEST_ptr(cctx) || !TEST_ptr(sctx))
goto end;
if (idx != 5) {
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
0,
&sctx, &cctx, cert, privkey)))
goto end;
} else {
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_VERSION,
0,
&sctx, &cctx, cert2, privkey2)))
goto end;
}
/* Ensure we only use TLSv1.2 ciphersuites based on SHA256 */
if (idx < 4) {
if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
"ECDHE-RSA-AES128-GCM-SHA256")))
goto end;
} else {
if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
"ECDHE-ECDSA-AES128-GCM-SHA256")))
goto end;
}
if (idx < 3) {
if (!SSL_CTX_set1_sigalgs_list(cctx,
"rsa_pss_rsae_sha384"
":rsa_pss_rsae_sha256")
|| !SSL_CTX_set1_sigalgs_list(sctx,
"rsa_pss_rsae_sha384"
":rsa_pss_rsae_sha256"))
goto end;
} else {
if (!SSL_CTX_set1_sigalgs_list(cctx, "rsa_pss_rsae_sha256:ECDSA+SHA256")
|| !SSL_CTX_set1_sigalgs_list(sctx,
"rsa_pss_rsae_sha256:ECDSA+SHA256"))
goto end;
}
if (idx != 5
&& (!TEST_int_eq(SSL_CTX_use_certificate_file(sctx, cert2,
SSL_FILETYPE_PEM), 1)
|| !TEST_int_eq(SSL_CTX_use_PrivateKey_file(sctx,
privkey2,
SSL_FILETYPE_PEM), 1)
|| !TEST_int_eq(SSL_CTX_check_private_key(sctx), 1)))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
/* For tests 0 and 3 we expect 2 shared sigalgs, otherwise exactly 1 */
if (!TEST_int_eq(SSL_get_shared_sigalgs(serverssl, 0, &sig, &hash, NULL,
NULL, NULL),
(idx == 0 || idx == 3) ? 2 : 1))
goto end;
if (!TEST_int_eq(hash, idx == 0 ? NID_sha384 : NID_sha256))
goto end;
if (!TEST_int_eq(sig, (idx == 4 || idx == 5) ? EVP_PKEY_EC
: NID_rsassaPss))
goto end;
testresult = filter_provider_check_clean_finish();
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
OSSL_PROVIDER_unload(filterprov);
OSSL_LIB_CTX_free(tmpctx);
return testresult;
}
#endif /*
* !defined(OPENSSL_NO_EC) \
* && (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2))
*/
#ifndef OPENSSL_NO_TLS1_3
/* This test can run in TLSv1.3 even if ec and dh are disabled */
static int test_pluggable_group(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
OSSL_PROVIDER *tlsprov = OSSL_PROVIDER_load(libctx, "tls-provider");
/* Check that we are not impacted by a provider without any groups */
OSSL_PROVIDER *legacyprov = OSSL_PROVIDER_load(libctx, "legacy");
const char *group_name = idx == 0 ? "xorkemgroup" : "xorgroup";
if (!TEST_ptr(tlsprov))
goto end;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
TLS1_3_VERSION,
&sctx, &cctx, cert, privkey))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
/* ensure GROUPLIST_INCREMENT (=40) logic triggers: */
if (!TEST_true(SSL_set1_groups_list(serverssl, "xorgroup:xorkemgroup:dummy1:dummy2:dummy3:dummy4:dummy5:dummy6:dummy7:dummy8:dummy9:dummy10:dummy11:dummy12:dummy13:dummy14:dummy15:dummy16:dummy17:dummy18:dummy19:dummy20:dummy21:dummy22:dummy23:dummy24:dummy25:dummy26:dummy27:dummy28:dummy29:dummy30:dummy31:dummy32:dummy33:dummy34:dummy35:dummy36:dummy37:dummy38:dummy39:dummy40:dummy41:dummy42:dummy43"))
/* removing a single algorithm from the list makes the test pass */
|| !TEST_true(SSL_set1_groups_list(clientssl, group_name)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
if (!TEST_str_eq(group_name,
SSL_group_to_name(serverssl, SSL_get_shared_group(serverssl, 0))))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
OSSL_PROVIDER_unload(tlsprov);
OSSL_PROVIDER_unload(legacyprov);
return testresult;
}
#endif
#ifndef OPENSSL_NO_TLS1_2
static int test_ssl_dup(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL, *client2ssl = NULL;
int testresult = 0;
BIO *rbio = NULL, *wbio = NULL;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
0,
0,
&sctx, &cctx, cert, privkey)))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(SSL_set_min_proto_version(clientssl, TLS1_2_VERSION))
|| !TEST_true(SSL_set_max_proto_version(clientssl, TLS1_2_VERSION)))
goto end;
client2ssl = SSL_dup(clientssl);
rbio = SSL_get_rbio(clientssl);
if (!TEST_ptr(rbio)
|| !TEST_true(BIO_up_ref(rbio)))
goto end;
SSL_set0_rbio(client2ssl, rbio);
rbio = NULL;
wbio = SSL_get_wbio(clientssl);
if (!TEST_ptr(wbio) || !TEST_true(BIO_up_ref(wbio)))
goto end;
SSL_set0_wbio(client2ssl, wbio);
rbio = NULL;
if (!TEST_ptr(client2ssl)
/* Handshake not started so pointers should be different */
|| !TEST_ptr_ne(clientssl, client2ssl))
goto end;
if (!TEST_int_eq(SSL_get_min_proto_version(client2ssl), TLS1_2_VERSION)
|| !TEST_int_eq(SSL_get_max_proto_version(client2ssl), TLS1_2_VERSION))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, client2ssl, SSL_ERROR_NONE)))
goto end;
SSL_free(clientssl);
clientssl = SSL_dup(client2ssl);
if (!TEST_ptr(clientssl)
/* Handshake has finished so pointers should be the same */
|| !TEST_ptr_eq(clientssl, client2ssl))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_free(client2ssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
# ifndef OPENSSL_NO_DH
static EVP_PKEY *tmp_dh_params = NULL;
/* Helper function for the test_set_tmp_dh() tests */
static EVP_PKEY *get_tmp_dh_params(void)
{
if (tmp_dh_params == NULL) {
BIGNUM *p = NULL;
OSSL_PARAM_BLD *tmpl = NULL;
EVP_PKEY_CTX *pctx = NULL;
OSSL_PARAM *params = NULL;
EVP_PKEY *dhpkey = NULL;
p = BN_get_rfc3526_prime_2048(NULL);
if (!TEST_ptr(p))
goto end;
pctx = EVP_PKEY_CTX_new_from_name(libctx, "DH", NULL);
if (!TEST_ptr(pctx)
|| !TEST_int_eq(EVP_PKEY_fromdata_init(pctx), 1))
goto end;
tmpl = OSSL_PARAM_BLD_new();
if (!TEST_ptr(tmpl)
|| !TEST_true(OSSL_PARAM_BLD_push_BN(tmpl,
OSSL_PKEY_PARAM_FFC_P,
p))
|| !TEST_true(OSSL_PARAM_BLD_push_uint(tmpl,
OSSL_PKEY_PARAM_FFC_G,
2)))
goto end;
params = OSSL_PARAM_BLD_to_param(tmpl);
if (!TEST_ptr(params)
|| !TEST_int_eq(EVP_PKEY_fromdata(pctx, &dhpkey,
EVP_PKEY_KEY_PARAMETERS,
params), 1))
goto end;
tmp_dh_params = dhpkey;
end:
BN_free(p);
EVP_PKEY_CTX_free(pctx);
OSSL_PARAM_BLD_free(tmpl);
OSSL_PARAM_free(params);
}
if (tmp_dh_params != NULL && !EVP_PKEY_up_ref(tmp_dh_params))
return NULL;
return tmp_dh_params;
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
/* Callback used by test_set_tmp_dh() */
static DH *tmp_dh_callback(SSL *s, int is_export, int keylen)
{
EVP_PKEY *dhpkey = get_tmp_dh_params();
DH *ret = NULL;
if (!TEST_ptr(dhpkey))
return NULL;
/*
* libssl does not free the returned DH, so we free it now knowing that even
* after we free dhpkey, there will still be a reference to the owning
* EVP_PKEY in tmp_dh_params, and so the DH object will live for the length
* of time we need it for.
*/
ret = EVP_PKEY_get1_DH(dhpkey);
DH_free(ret);
EVP_PKEY_free(dhpkey);
return ret;
}
# endif
/*
* Test the various methods for setting temporary DH parameters
*
* Test 0: Default (no auto) setting
* Test 1: Explicit SSL_CTX auto off
* Test 2: Explicit SSL auto off
* Test 3: Explicit SSL_CTX auto on
* Test 4: Explicit SSL auto on
* Test 5: Explicit SSL_CTX auto off, custom DH params via EVP_PKEY
* Test 6: Explicit SSL auto off, custom DH params via EVP_PKEY
*
* The following are testing deprecated APIs, so we only run them if available
* Test 7: Explicit SSL_CTX auto off, custom DH params via DH
* Test 8: Explicit SSL auto off, custom DH params via DH
* Test 9: Explicit SSL_CTX auto off, custom DH params via callback
* Test 10: Explicit SSL auto off, custom DH params via callback
*/
static int test_set_tmp_dh(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
int dhauto = (idx == 3 || idx == 4) ? 1 : 0;
int expected = (idx <= 2) ? 0 : 1;
EVP_PKEY *dhpkey = NULL;
# ifndef OPENSSL_NO_DEPRECATED_3_0
DH *dh = NULL;
# else
if (idx >= 7)
return 1;
# endif
if (idx >= 5 && idx <= 8) {
dhpkey = get_tmp_dh_params();
if (!TEST_ptr(dhpkey))
goto end;
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
if (idx == 7 || idx == 8) {
dh = EVP_PKEY_get1_DH(dhpkey);
if (!TEST_ptr(dh))
goto end;
}
# endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
0,
0,
&sctx, &cctx, cert, privkey)))
goto end;
if ((idx & 1) == 1) {
if (!TEST_true(SSL_CTX_set_dh_auto(sctx, dhauto)))
goto end;
}
if (idx == 5) {
if (!TEST_true(SSL_CTX_set0_tmp_dh_pkey(sctx, dhpkey)))
goto end;
dhpkey = NULL;
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
else if (idx == 7) {
if (!TEST_true(SSL_CTX_set_tmp_dh(sctx, dh)))
goto end;
} else if (idx == 9) {
SSL_CTX_set_tmp_dh_callback(sctx, tmp_dh_callback);
}
# endif
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if ((idx & 1) == 0 && idx != 0) {
if (!TEST_true(SSL_set_dh_auto(serverssl, dhauto)))
goto end;
}
if (idx == 6) {
if (!TEST_true(SSL_set0_tmp_dh_pkey(serverssl, dhpkey)))
goto end;
dhpkey = NULL;
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
else if (idx == 8) {
if (!TEST_true(SSL_set_tmp_dh(serverssl, dh)))
goto end;
} else if (idx == 10) {
SSL_set_tmp_dh_callback(serverssl, tmp_dh_callback);
}
# endif
if (!TEST_true(SSL_set_min_proto_version(serverssl, TLS1_2_VERSION))
|| !TEST_true(SSL_set_max_proto_version(serverssl, TLS1_2_VERSION))
|| !TEST_true(SSL_set_cipher_list(serverssl, "DHE-RSA-AES128-SHA")))
goto end;
/*
* If autoon then we should succeed. Otherwise we expect failure because
* there are no parameters
*/
if (!TEST_int_eq(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE), expected))
goto end;
testresult = 1;
end:
# ifndef OPENSSL_NO_DEPRECATED_3_0
DH_free(dh);
# endif
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
EVP_PKEY_free(dhpkey);
return testresult;
}
/*
* Test the auto DH keys are appropriately sized
*/
static int test_dh_auto(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
EVP_PKEY *tmpkey = NULL;
char *thiscert = NULL, *thiskey = NULL;
size_t expdhsize = 0;
const char *ciphersuite = "DHE-RSA-AES128-SHA";
switch (idx) {
case 0:
/* The FIPS provider doesn't support this DH size - so we ignore it */
if (is_fips)
return 1;
thiscert = cert1024;
thiskey = privkey1024;
expdhsize = 1024;
break;
case 1:
/* 2048 bit prime */
thiscert = cert;
thiskey = privkey;
expdhsize = 2048;
break;
case 2:
thiscert = cert3072;
thiskey = privkey3072;
expdhsize = 3072;
break;
case 3:
thiscert = cert4096;
thiskey = privkey4096;
expdhsize = 4096;
break;
case 4:
thiscert = cert8192;
thiskey = privkey8192;
expdhsize = 8192;
break;
/* No certificate cases */
case 5:
/* The FIPS provider doesn't support this DH size - so we ignore it */
if (is_fips)
return 1;
ciphersuite = "ADH-AES128-SHA256:@SECLEVEL=0";
expdhsize = 1024;
break;
case 6:
ciphersuite = "ADH-AES256-SHA256:@SECLEVEL=0";
expdhsize = 3072;
break;
default:
TEST_error("Invalid text index");
goto end;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
0,
0,
&sctx, &cctx, thiscert, thiskey)))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
if (!TEST_true(SSL_set_dh_auto(serverssl, 1))
|| !TEST_true(SSL_set_min_proto_version(serverssl, TLS1_2_VERSION))
|| !TEST_true(SSL_set_max_proto_version(serverssl, TLS1_2_VERSION))
|| !TEST_true(SSL_set_cipher_list(serverssl, ciphersuite))
|| !TEST_true(SSL_set_cipher_list(clientssl, ciphersuite)))
goto end;
/*
* Send the server's first flight. At this point the server has created the
* temporary DH key but hasn't finished using it yet. Once used it is
* removed, so we cannot test it.
*/
if (!TEST_int_le(SSL_connect(clientssl), 0)
|| !TEST_int_le(SSL_accept(serverssl), 0))
goto end;
if (!TEST_int_gt(SSL_get_tmp_key(serverssl, &tmpkey), 0))
goto end;
if (!TEST_size_t_eq(EVP_PKEY_get_bits(tmpkey), expdhsize))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
EVP_PKEY_free(tmpkey);
return testresult;
}
# endif /* OPENSSL_NO_DH */
#endif /* OPENSSL_NO_TLS1_2 */
#ifndef OSSL_NO_USABLE_TLS1_3
/*
* Test that setting an SNI callback works with TLSv1.3. Specifically we check
* that it works even without a certificate configured for the original
* SSL_CTX
*/
static int test_sni_tls13(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
/* Reset callback counter */
snicb = 0;
/* Create an initial SSL_CTX with no certificate configured */
sctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method());
if (!TEST_ptr(sctx))
goto end;
/* Require TLSv1.3 as a minimum */
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_3_VERSION, 0,
&sctx2, &cctx, cert, privkey)))
goto end;
/* Set up SNI */
if (!TEST_true(SSL_CTX_set_tlsext_servername_callback(sctx, sni_cb))
|| !TEST_true(SSL_CTX_set_tlsext_servername_arg(sctx, sctx2)))
goto end;
/*
* Connection should still succeed because the final SSL_CTX has the right
* certificates configured.
*/
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
/* We should have had the SNI callback called exactly once */
if (!TEST_int_eq(snicb, 1))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx2);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
/*
* Test that the lifetime hint of a TLSv1.3 ticket is no more than 1 week
* 0 = TLSv1.2
* 1 = TLSv1.3
*/
static int test_ticket_lifetime(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
int version = TLS1_3_VERSION;
#define ONE_WEEK_SEC (7 * 24 * 60 * 60)
#define TWO_WEEK_SEC (2 * ONE_WEEK_SEC)
if (idx == 0) {
#ifdef OPENSSL_NO_TLS1_2
return TEST_skip("TLS 1.2 is disabled.");
#else
version = TLS1_2_VERSION;
#endif
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), version, version,
&sctx, &cctx, cert, privkey)))
goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
/*
* Set the timeout to be more than 1 week
* make sure the returned value is the default
*/
if (!TEST_long_eq(SSL_CTX_set_timeout(sctx, TWO_WEEK_SEC),
SSL_get_default_timeout(serverssl)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
if (idx == 0) {
/* TLSv1.2 uses the set value */
if (!TEST_ulong_eq(SSL_SESSION_get_ticket_lifetime_hint(SSL_get_session(clientssl)), TWO_WEEK_SEC))
goto end;
} else {
/* TLSv1.3 uses the limited value */
if (!TEST_ulong_le(SSL_SESSION_get_ticket_lifetime_hint(SSL_get_session(clientssl)), ONE_WEEK_SEC))
goto end;
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif
/*
* Test that setting an ALPN does not violate RFC
*/
static int test_set_alpn(void)
{
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
int testresult = 0;
unsigned char bad0[] = { 0x00, 'b', 'a', 'd' };
unsigned char good[] = { 0x04, 'g', 'o', 'o', 'd' };
unsigned char bad1[] = { 0x01, 'b', 'a', 'd' };
unsigned char bad2[] = { 0x03, 'b', 'a', 'd', 0x00};
unsigned char bad3[] = { 0x03, 'b', 'a', 'd', 0x01, 'b', 'a', 'd'};
unsigned char bad4[] = { 0x03, 'b', 'a', 'd', 0x06, 'b', 'a', 'd'};
/* Create an initial SSL_CTX with no certificate configured */
ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method());
if (!TEST_ptr(ctx))
goto end;
/* the set_alpn functions return 0 (false) on success, non-zero (true) on failure */
if (!TEST_false(SSL_CTX_set_alpn_protos(ctx, NULL, 2)))
goto end;
if (!TEST_false(SSL_CTX_set_alpn_protos(ctx, good, 0)))
goto end;
if (!TEST_false(SSL_CTX_set_alpn_protos(ctx, good, sizeof(good))))
goto end;
if (!TEST_true(SSL_CTX_set_alpn_protos(ctx, good, 1)))
goto end;
if (!TEST_true(SSL_CTX_set_alpn_protos(ctx, bad0, sizeof(bad0))))
goto end;
if (!TEST_true(SSL_CTX_set_alpn_protos(ctx, bad1, sizeof(bad1))))
goto end;
if (!TEST_true(SSL_CTX_set_alpn_protos(ctx, bad2, sizeof(bad2))))
goto end;
if (!TEST_true(SSL_CTX_set_alpn_protos(ctx, bad3, sizeof(bad3))))
goto end;
if (!TEST_true(SSL_CTX_set_alpn_protos(ctx, bad4, sizeof(bad4))))
goto end;
ssl = SSL_new(ctx);
if (!TEST_ptr(ssl))
goto end;
if (!TEST_false(SSL_set_alpn_protos(ssl, NULL, 2)))
goto end;
if (!TEST_false(SSL_set_alpn_protos(ssl, good, 0)))
goto end;
if (!TEST_false(SSL_set_alpn_protos(ssl, good, sizeof(good))))
goto end;
if (!TEST_true(SSL_set_alpn_protos(ssl, good, 1)))
goto end;
if (!TEST_true(SSL_set_alpn_protos(ssl, bad0, sizeof(bad0))))
goto end;
if (!TEST_true(SSL_set_alpn_protos(ssl, bad1, sizeof(bad1))))
goto end;
if (!TEST_true(SSL_set_alpn_protos(ssl, bad2, sizeof(bad2))))
goto end;
if (!TEST_true(SSL_set_alpn_protos(ssl, bad3, sizeof(bad3))))
goto end;
if (!TEST_true(SSL_set_alpn_protos(ssl, bad4, sizeof(bad4))))
goto end;
testresult = 1;
end:
SSL_free(ssl);
SSL_CTX_free(ctx);
return testresult;
}
/*
* Test SSL_CTX_set1_verify/chain_cert_store and SSL_CTX_get_verify/chain_cert_store.
*/
static int test_set_verify_cert_store_ssl_ctx(void)
{
SSL_CTX *ctx = NULL;
int testresult = 0;
X509_STORE *store = NULL, *new_store = NULL,
*cstore = NULL, *new_cstore = NULL;
/* Create an initial SSL_CTX. */
ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method());
if (!TEST_ptr(ctx))
goto end;
/* Retrieve verify store pointer. */
if (!TEST_true(SSL_CTX_get0_verify_cert_store(ctx, &store)))
goto end;
/* Retrieve chain store pointer. */
if (!TEST_true(SSL_CTX_get0_chain_cert_store(ctx, &cstore)))
goto end;
/* We haven't set any yet, so this should be NULL. */
if (!TEST_ptr_null(store) || !TEST_ptr_null(cstore))
goto end;
/* Create stores. We use separate stores so pointers are different. */
new_store = X509_STORE_new();
if (!TEST_ptr(new_store))
goto end;
new_cstore = X509_STORE_new();
if (!TEST_ptr(new_cstore))
goto end;
/* Set stores. */
if (!TEST_true(SSL_CTX_set1_verify_cert_store(ctx, new_store)))
goto end;
if (!TEST_true(SSL_CTX_set1_chain_cert_store(ctx, new_cstore)))
goto end;
/* Should be able to retrieve the same pointer. */
if (!TEST_true(SSL_CTX_get0_verify_cert_store(ctx, &store)))
goto end;
if (!TEST_true(SSL_CTX_get0_chain_cert_store(ctx, &cstore)))
goto end;
if (!TEST_ptr_eq(store, new_store) || !TEST_ptr_eq(cstore, new_cstore))
goto end;
/* Should be able to unset again. */
if (!TEST_true(SSL_CTX_set1_verify_cert_store(ctx, NULL)))
goto end;
if (!TEST_true(SSL_CTX_set1_chain_cert_store(ctx, NULL)))
goto end;
/* Should now be NULL. */
if (!TEST_true(SSL_CTX_get0_verify_cert_store(ctx, &store)))
goto end;
if (!TEST_true(SSL_CTX_get0_chain_cert_store(ctx, &cstore)))
goto end;
if (!TEST_ptr_null(store) || !TEST_ptr_null(cstore))
goto end;
testresult = 1;
end:
X509_STORE_free(new_store);
X509_STORE_free(new_cstore);
SSL_CTX_free(ctx);
return testresult;
}
/*
* Test SSL_set1_verify/chain_cert_store and SSL_get_verify/chain_cert_store.
*/
static int test_set_verify_cert_store_ssl(void)
{
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
int testresult = 0;
X509_STORE *store = NULL, *new_store = NULL,
*cstore = NULL, *new_cstore = NULL;
/* Create an initial SSL_CTX. */
ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method());
if (!TEST_ptr(ctx))
goto end;
/* Create an SSL object. */
ssl = SSL_new(ctx);
if (!TEST_ptr(ssl))
goto end;
/* Retrieve verify store pointer. */
if (!TEST_true(SSL_get0_verify_cert_store(ssl, &store)))
goto end;
/* Retrieve chain store pointer. */
if (!TEST_true(SSL_get0_chain_cert_store(ssl, &cstore)))
goto end;
/* We haven't set any yet, so this should be NULL. */
if (!TEST_ptr_null(store) || !TEST_ptr_null(cstore))
goto end;
/* Create stores. We use separate stores so pointers are different. */
new_store = X509_STORE_new();
if (!TEST_ptr(new_store))
goto end;
new_cstore = X509_STORE_new();
if (!TEST_ptr(new_cstore))
goto end;
/* Set stores. */
if (!TEST_true(SSL_set1_verify_cert_store(ssl, new_store)))
goto end;
if (!TEST_true(SSL_set1_chain_cert_store(ssl, new_cstore)))
goto end;
/* Should be able to retrieve the same pointer. */
if (!TEST_true(SSL_get0_verify_cert_store(ssl, &store)))
goto end;
if (!TEST_true(SSL_get0_chain_cert_store(ssl, &cstore)))
goto end;
if (!TEST_ptr_eq(store, new_store) || !TEST_ptr_eq(cstore, new_cstore))
goto end;
/* Should be able to unset again. */
if (!TEST_true(SSL_set1_verify_cert_store(ssl, NULL)))
goto end;
if (!TEST_true(SSL_set1_chain_cert_store(ssl, NULL)))
goto end;
/* Should now be NULL. */
if (!TEST_true(SSL_get0_verify_cert_store(ssl, &store)))
goto end;
if (!TEST_true(SSL_get0_chain_cert_store(ssl, &cstore)))
goto end;
if (!TEST_ptr_null(store) || !TEST_ptr_null(cstore))
goto end;
testresult = 1;
end:
X509_STORE_free(new_store);
X509_STORE_free(new_cstore);
SSL_free(ssl);
SSL_CTX_free(ctx);
return testresult;
}
static int test_inherit_verify_param(void)
{
int testresult = 0;
SSL_CTX *ctx = NULL;
X509_VERIFY_PARAM *cp = NULL;
SSL *ssl = NULL;
X509_VERIFY_PARAM *sp = NULL;
int hostflags = X509_CHECK_FLAG_NEVER_CHECK_SUBJECT;
ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method());
if (!TEST_ptr(ctx))
goto end;
cp = SSL_CTX_get0_param(ctx);
if (!TEST_ptr(cp))
goto end;
if (!TEST_int_eq(X509_VERIFY_PARAM_get_hostflags(cp), 0))
goto end;
X509_VERIFY_PARAM_set_hostflags(cp, hostflags);
ssl = SSL_new(ctx);
if (!TEST_ptr(ssl))
goto end;
sp = SSL_get0_param(ssl);
if (!TEST_ptr(sp))
goto end;
if (!TEST_int_eq(X509_VERIFY_PARAM_get_hostflags(sp), hostflags))
goto end;
testresult = 1;
end:
SSL_free(ssl);
SSL_CTX_free(ctx);
return testresult;
}
static int test_load_dhfile(void)
{
#ifndef OPENSSL_NO_DH
int testresult = 0;
SSL_CTX *ctx = NULL;
SSL_CONF_CTX *cctx = NULL;
if (dhfile == NULL)
return 1;
if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_client_method()))
|| !TEST_ptr(cctx = SSL_CONF_CTX_new()))
goto end;
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
SSL_CONF_CTX_set_flags(cctx,
SSL_CONF_FLAG_CERTIFICATE
| SSL_CONF_FLAG_SERVER
| SSL_CONF_FLAG_FILE);
if (!TEST_int_eq(SSL_CONF_cmd(cctx, "DHParameters", dhfile), 2))
goto end;
testresult = 1;
end:
SSL_CONF_CTX_free(cctx);
SSL_CTX_free(ctx);
return testresult;
#else
return TEST_skip("DH not supported by this build");
#endif
}
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE)
/*
* Test TLSv1.2 with a pipeline capable cipher. TLSv1.3 and DTLS do not
* support this yet. The only pipeline capable cipher that we have is in the
* dasync engine (providers don't support this yet), so we have to use
* deprecated APIs for this test.
*
* Test 0: Client has pipelining enabled, server does not
* Test 1: Server has pipelining enabled, client does not
* Test 2: Client has pipelining enabled, server does not: not enough data to
* fill all the pipelines
* Test 3: Client has pipelining enabled, server does not: not enough data to
* fill all the pipelines by more than a full pipeline's worth
* Test 4: Client has pipelining enabled, server does not: more data than all
* the available pipelines can take
* Test 5: Client has pipelining enabled, server does not: Maximum size pipeline
* Test 6: Repeat of test 0, but the engine is loaded late (after the SSL_CTX
* is created)
*/
static int test_pipelining(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL, *peera, *peerb;
int testresult = 0, numreads;
/* A 55 byte message */
unsigned char *msg = (unsigned char *)
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123";
size_t written, readbytes, offset, msglen, fragsize = 10, numpipes = 5;
size_t expectedreads;
unsigned char *buf = NULL;
ENGINE *e = NULL;
if (idx != 6) {
e = load_dasync();
if (e == NULL)
return 0;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), 0,
TLS1_2_VERSION, &sctx, &cctx, cert,
privkey)))
goto end;
if (idx == 6) {
e = load_dasync();
if (e == NULL)
goto end;
/* Now act like test 0 */
idx = 0;
}
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
if (!TEST_true(SSL_set_cipher_list(clientssl, "AES128-SHA")))
goto end;
/* peera is always configured for pipelining, while peerb is not. */
if (idx == 1) {
peera = serverssl;
peerb = clientssl;
} else {
peera = clientssl;
peerb = serverssl;
}
if (idx == 5) {
numpipes = 2;
/* Maximum allowed fragment size */
fragsize = SSL3_RT_MAX_PLAIN_LENGTH;
msglen = fragsize * numpipes;
msg = OPENSSL_malloc(msglen);
if (!TEST_ptr(msg))
goto end;
if (!TEST_int_gt(RAND_bytes_ex(libctx, msg, msglen, 0), 0))
goto end;
} else if (idx == 4) {
msglen = 55;
} else {
msglen = 50;
}
if (idx == 2)
msglen -= 2; /* Send 2 less bytes */
else if (idx == 3)
msglen -= 12; /* Send 12 less bytes */
buf = OPENSSL_malloc(msglen);
if (!TEST_ptr(buf))
goto end;
if (idx == 5) {
/*
* Test that setting a split send fragment longer than the maximum
* allowed fails
*/
if (!TEST_false(SSL_set_split_send_fragment(peera, fragsize + 1)))
goto end;
}
/*
* In the normal case. We have 5 pipelines with 10 bytes per pipeline
* (50 bytes in total). This is a ridiculously small number of bytes -
* but sufficient for our purposes
*/
if (!TEST_true(SSL_set_max_pipelines(peera, numpipes))
|| !TEST_true(SSL_set_split_send_fragment(peera, fragsize)))
goto end;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
/* Write some data from peera to peerb */
if (!TEST_true(SSL_write_ex(peera, msg, msglen, &written))
|| !TEST_size_t_eq(written, msglen))
goto end;
/*
* If the pipelining code worked, then we expect all |numpipes| pipelines to
* have been used - except in test 3 where only |numpipes - 1| pipelines
* will be used. This will result in |numpipes| records (|numpipes - 1| for
* test 3) having been sent to peerb. Since peerb is not using read_ahead we
* expect this to be read in |numpipes| or |numpipes - 1| separate
* SSL_read_ex calls. In the case of test 4, there is then one additional
* read for left over data that couldn't fit in the previous pipelines
*/
for (offset = 0, numreads = 0;
offset < msglen;
offset += readbytes, numreads++) {
if (!TEST_true(SSL_read_ex(peerb, buf + offset,
msglen - offset, &readbytes)))
goto end;
}
expectedreads = idx == 4 ? numpipes + 1
: (idx == 3 ? numpipes - 1 : numpipes);
if (!TEST_mem_eq(msg, msglen, buf, offset)
|| !TEST_int_eq(numreads, expectedreads))
goto end;
/*
* Write some data from peerb to peera. We do this in up to |numpipes + 1|
* chunks to exercise the read pipelining code on peera.
*/
for (offset = 0; offset < msglen; offset += fragsize) {
size_t sendlen = msglen - offset;
if (sendlen > fragsize)
sendlen = fragsize;
if (!TEST_true(SSL_write_ex(peerb, msg + offset, sendlen, &written))
|| !TEST_size_t_eq(written, sendlen))
goto end;
}
/*
* The data was written in |numpipes|, |numpipes - 1| or |numpipes + 1|
* separate chunks (depending on which test we are running). If the
* pipelining is working then we expect peera to read up to numpipes chunks
* and process them in parallel, giving back the complete result in a single
* call to SSL_read_ex
*/
if (!TEST_true(SSL_read_ex(peera, buf, msglen, &readbytes))
|| !TEST_size_t_le(readbytes, msglen))
goto end;
if (idx == 4) {
size_t readbytes2;
if (!TEST_true(SSL_read_ex(peera, buf + readbytes,
msglen - readbytes, &readbytes2)))
goto end;
readbytes += readbytes2;
if (!TEST_size_t_le(readbytes, msglen))
goto end;
}
if (!TEST_mem_eq(msg, msglen, buf, readbytes))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
if (e != NULL) {
ENGINE_unregister_ciphers(e);
ENGINE_finish(e);
ENGINE_free(e);
}
OPENSSL_free(buf);
if (fragsize == SSL3_RT_MAX_PLAIN_LENGTH)
OPENSSL_free(msg);
return testresult;
}
#endif /* !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) */
/*
* Force a write retry during handshaking. We test various combinations of
* scenarios. We test a large certificate message which will fill the buffering
* BIO used in the handshake. We try with client auth on and off. Finally we
* also try a BIO that indicates retry via a 0 return. BIO_write() is documented
* to indicate retry via -1 - but sometimes BIOs don't do that.
*
* Test 0: Standard certificate message
* Test 1: Large certificate message
* Test 2: Standard cert, verify peer
* Test 3: Large cert, verify peer
* Test 4: Standard cert, BIO returns 0 on retry
* Test 5: Large cert, BIO returns 0 on retry
* Test 6: Standard cert, verify peer, BIO returns 0 on retry
* Test 7: Large cert, verify peer, BIO returns 0 on retry
* Test 8-15: Repeat of above with TLSv1.2
*/
static int test_handshake_retry(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
BIO *tmp = NULL, *bretry = BIO_new(bio_s_always_retry());
int maxversion = 0;
if (!TEST_ptr(bretry))
goto end;
#ifndef OPENSSL_NO_TLS1_2
if ((idx & 8) == 8)
maxversion = TLS1_2_VERSION;
#else
if ((idx & 8) == 8)
return TEST_skip("No TLSv1.2");
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), 0, maxversion,
&sctx, &cctx, cert, privkey)))
goto end;
/*
* Add a large amount of data to fill the buffering BIO used by the SSL
* object
*/
if ((idx & 1) == 1 && !add_large_cert_chain(sctx))
goto end;
/*
* We don't actually configure a client cert, but neither do we fail if one
* isn't present.
*/
if ((idx & 2) == 2)
SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, NULL);
if ((idx & 4) == 4)
set_always_retry_err_val(0);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
tmp = SSL_get_wbio(serverssl);
if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
tmp = NULL;
goto end;
}
SSL_set0_wbio(serverssl, bretry);
bretry = NULL;
if (!TEST_int_eq(SSL_connect(clientssl), -1))
goto end;
if (!TEST_int_eq(SSL_accept(serverssl), -1)
|| !TEST_int_eq(SSL_get_error(serverssl, -1), SSL_ERROR_WANT_WRITE))
goto end;
/* Restore a BIO that will let the write succeed */
SSL_set0_wbio(serverssl, tmp);
tmp = NULL;
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
BIO_free(bretry);
BIO_free(tmp);
set_always_retry_err_val(-1);
return testresult;
}
struct resume_servername_cb_data {
int i;
SSL_CTX *cctx;
SSL_CTX *sctx;
SSL_SESSION *sess;
int recurse;
};
/*
* Servername callback. We use it here to run another complete handshake using
* the same session - and mark the session as not_resuamble at the end
*/
static int resume_servername_cb(SSL *s, int *ad, void *arg)
{
struct resume_servername_cb_data *cbdata = arg;
SSL *serverssl = NULL, *clientssl = NULL;
int ret = SSL_TLSEXT_ERR_ALERT_FATAL;
if (cbdata->recurse)
return SSL_TLSEXT_ERR_ALERT_FATAL;
if ((cbdata->i % 3) != 1)
return SSL_TLSEXT_ERR_OK;
cbdata->recurse = 1;
if (!TEST_true(create_ssl_objects(cbdata->sctx, cbdata->cctx, &serverssl,
&clientssl, NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, cbdata->sess)))
goto end;
ERR_set_mark();
/*
* We expect this to fail - because the servername cb will fail. This will
* mark the session as not_resumable.
*/
if (!TEST_false(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) {
ERR_clear_last_mark();
goto end;
}
ERR_pop_to_mark();
ret = SSL_TLSEXT_ERR_OK;
end:
SSL_free(serverssl);
SSL_free(clientssl);
cbdata->recurse = 0;
return ret;
}
/*
* Test multiple resumptions and cache size handling
* Test 0: TLSv1.3 (max_early_data set)
* Test 1: TLSv1.3 (SSL_OP_NO_TICKET set)
* Test 2: TLSv1.3 (max_early_data and SSL_OP_NO_TICKET set)
* Test 3: TLSv1.3 (SSL_OP_NO_TICKET, simultaneous resumes)
* Test 4: TLSv1.2
*/
static int test_multi_resume(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
SSL_SESSION *sess = NULL;
int max_version = TLS1_3_VERSION;
int i, testresult = 0;
struct resume_servername_cb_data cbdata;
#if defined(OPENSSL_NO_TLS1_2)
if (idx == 4)
return TEST_skip("TLSv1.2 is disabled in this build");
#else
if (idx == 4)
max_version = TLS1_2_VERSION;
#endif
#if defined(OSSL_NO_USABLE_TLS1_3)
if (idx != 4)
return TEST_skip("No usable TLSv1.3 in this build");
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION,
max_version, &sctx, &cctx, cert,
privkey)))
goto end;
/*
* TLSv1.3 only uses a session cache if either max_early_data > 0 (used for
* replay protection), or if SSL_OP_NO_TICKET is in use
*/
if (idx == 0 || idx == 2) {
if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024)))
goto end;
}
if (idx == 1 || idx == 2 || idx == 3)
SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET);
SSL_CTX_sess_set_cache_size(sctx, 5);
if (idx == 3) {
SSL_CTX_set_tlsext_servername_callback(sctx, resume_servername_cb);
SSL_CTX_set_tlsext_servername_arg(sctx, &cbdata);
cbdata.cctx = cctx;
cbdata.sctx = sctx;
cbdata.recurse = 0;
}
for (i = 0; i < 30; i++) {
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(SSL_set_session(clientssl, sess)))
goto end;
/*
* Check simultaneous resumes. We pause the connection part way through
* the handshake by (mis)using the servername_cb. The pause occurs after
* session resumption has already occurred, but before any session
* tickets have been issued. While paused we run another complete
* handshake resuming the same session.
*/
if (idx == 3) {
cbdata.i = i;
cbdata.sess = sess;
}
/*
* Recreate a bug where dynamically changing the max_early_data value
* can cause sessions in the session cache which cannot be deleted.
*/
if ((idx == 0 || idx == 2) && (i % 3) == 2)
SSL_set_max_early_data(serverssl, 0);
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
if (sess == NULL || (idx == 0 && (i % 3) == 2)) {
if (!TEST_false(SSL_session_reused(clientssl)))
goto end;
} else {
if (!TEST_true(SSL_session_reused(clientssl)))
goto end;
}
SSL_SESSION_free(sess);
/* Do a full handshake, followed by two resumptions */
if ((i % 3) == 2) {
sess = NULL;
} else {
if (!TEST_ptr((sess = SSL_get1_session(clientssl))))
goto end;
}
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;
}
/* We should never exceed the session cache size limit */
if (!TEST_long_le(SSL_CTX_sess_number(sctx), 5))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
SSL_SESSION_free(sess);
return testresult;
}
static struct next_proto_st {
int serverlen;
unsigned char server[40];
int clientlen;
unsigned char client[40];
int expected_ret;
size_t selectedlen;
unsigned char selected[40];
} next_proto_tests[] = {
{
4, { 3, 'a', 'b', 'c' },
4, { 3, 'a', 'b', 'c' },
OPENSSL_NPN_NEGOTIATED,
3, { 'a', 'b', 'c' }
},
{
7, { 3, 'a', 'b', 'c', 2, 'a', 'b' },
4, { 3, 'a', 'b', 'c' },
OPENSSL_NPN_NEGOTIATED,
3, { 'a', 'b', 'c' }
},
{
7, { 2, 'a', 'b', 3, 'a', 'b', 'c', },
4, { 3, 'a', 'b', 'c' },
OPENSSL_NPN_NEGOTIATED,
3, { 'a', 'b', 'c' }
},
{
4, { 3, 'a', 'b', 'c' },
7, { 3, 'a', 'b', 'c', 2, 'a', 'b', },
OPENSSL_NPN_NEGOTIATED,
3, { 'a', 'b', 'c' }
},
{
4, { 3, 'a', 'b', 'c' },
7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
OPENSSL_NPN_NEGOTIATED,
3, { 'a', 'b', 'c' }
},
{
7, { 2, 'b', 'c', 3, 'a', 'b', 'c' },
7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
OPENSSL_NPN_NEGOTIATED,
3, { 'a', 'b', 'c' }
},
{
10, { 2, 'b', 'c', 3, 'a', 'b', 'c', 2, 'a', 'b' },
7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
OPENSSL_NPN_NEGOTIATED,
3, { 'a', 'b', 'c' }
},
{
4, { 3, 'b', 'c', 'd' },
4, { 3, 'a', 'b', 'c' },
OPENSSL_NPN_NO_OVERLAP,
3, { 'a', 'b', 'c' }
},
{
0, { 0 },
4, { 3, 'a', 'b', 'c' },
OPENSSL_NPN_NO_OVERLAP,
3, { 'a', 'b', 'c' }
},
{
-1, { 0 },
4, { 3, 'a', 'b', 'c' },
OPENSSL_NPN_NO_OVERLAP,
3, { 'a', 'b', 'c' }
},
{
4, { 3, 'a', 'b', 'c' },
0, { 0 },
OPENSSL_NPN_NO_OVERLAP,
0, { 0 }
},
{
4, { 3, 'a', 'b', 'c' },
-1, { 0 },
OPENSSL_NPN_NO_OVERLAP,
0, { 0 }
},
{
3, { 3, 'a', 'b', 'c' },
4, { 3, 'a', 'b', 'c' },
OPENSSL_NPN_NO_OVERLAP,
3, { 'a', 'b', 'c' }
},
{
4, { 3, 'a', 'b', 'c' },
3, { 3, 'a', 'b', 'c' },
OPENSSL_NPN_NO_OVERLAP,
0, { 0 }
}
};
static int test_select_next_proto(int idx)
{
struct next_proto_st *np = &next_proto_tests[idx];
int ret = 0;
unsigned char *out, *client, *server;
unsigned char outlen;
unsigned int clientlen, serverlen;
if (np->clientlen == -1) {
client = NULL;
clientlen = 0;
} else {
client = np->client;
clientlen = (unsigned int)np->clientlen;
}
if (np->serverlen == -1) {
server = NULL;
serverlen = 0;
} else {
server = np->server;
serverlen = (unsigned int)np->serverlen;
}
if (!TEST_int_eq(SSL_select_next_proto(&out, &outlen, server, serverlen,
client, clientlen),
np->expected_ret))
goto err;
if (np->selectedlen == 0) {
if (!TEST_ptr_null(out) || !TEST_uchar_eq(outlen, 0))
goto err;
} else {
if (!TEST_mem_eq(out, outlen, np->selected, np->selectedlen))
goto err;
}
ret = 1;
err:
return ret;
}
static const unsigned char fooprot[] = {3, 'f', 'o', 'o' };
static const unsigned char barprot[] = {3, 'b', 'a', 'r' };
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG)
static int npn_advert_cb(SSL *ssl, const unsigned char **out,
unsigned int *outlen, void *arg)
{
int *idx = (int *)arg;
switch (*idx) {
default:
case 0:
*out = fooprot;
*outlen = sizeof(fooprot);
return SSL_TLSEXT_ERR_OK;
case 1:
+ *out = NULL;
*outlen = 0;
return SSL_TLSEXT_ERR_OK;
case 2:
return SSL_TLSEXT_ERR_NOACK;
}
}
static int npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg)
{
int *idx = (int *)arg;
switch (*idx) {
case 0:
case 1:
*out = (unsigned char *)(fooprot + 1);
*outlen = *fooprot;
return SSL_TLSEXT_ERR_OK;
case 3:
*out = (unsigned char *)(barprot + 1);
*outlen = *barprot;
return SSL_TLSEXT_ERR_OK;
case 4:
*outlen = 0;
return SSL_TLSEXT_ERR_OK;
default:
case 2:
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
}
/*
* Test the NPN callbacks
* Test 0: advert = foo, select = foo
* Test 1: advert = <empty>, select = foo
* Test 2: no advert
* Test 3: advert = foo, select = bar
* Test 4: advert = foo, select = <empty> (should fail)
*/
static int test_npn(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), 0, TLS1_2_VERSION,
&sctx, &cctx, cert, privkey)))
goto end;
SSL_CTX_set_next_protos_advertised_cb(sctx, npn_advert_cb, &idx);
SSL_CTX_set_next_proto_select_cb(cctx, npn_select_cb, &idx);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
NULL)))
goto end;
if (idx == 4) {
/* We don't allow empty selection of NPN, so this should fail */
if (!TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
} else {
const unsigned char *prot;
unsigned int protlen;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
SSL_get0_next_proto_negotiated(serverssl, &prot, &protlen);
switch (idx) {
case 0:
case 1:
if (!TEST_mem_eq(prot, protlen, fooprot + 1, *fooprot))
goto end;
break;
case 2:
if (!TEST_uint_eq(protlen, 0))
goto end;
break;
case 3:
if (!TEST_mem_eq(prot, protlen, barprot + 1, *barprot))
goto end;
break;
default:
TEST_error("Should not get here");
goto end;
}
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
#endif /* !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG) */
static int alpn_select_cb2(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg)
{
int *idx = (int *)arg;
switch (*idx) {
case 0:
*out = (unsigned char *)(fooprot + 1);
*outlen = *fooprot;
return SSL_TLSEXT_ERR_OK;
case 2:
*out = (unsigned char *)(barprot + 1);
*outlen = *barprot;
return SSL_TLSEXT_ERR_OK;
case 3:
*outlen = 0;
return SSL_TLSEXT_ERR_OK;
default:
case 1:
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
return 0;
}
/*
* Test the ALPN callbacks
* Test 0: client = foo, select = foo
* Test 1: client = <empty>, select = none
* Test 2: client = foo, select = bar (should fail)
* Test 3: client = foo, select = <empty> (should fail)
*/
static int test_alpn(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
const unsigned char *prots = fooprot;
unsigned int protslen = sizeof(fooprot);
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), 0, 0,
&sctx, &cctx, cert, privkey)))
goto end;
SSL_CTX_set_alpn_select_cb(sctx, alpn_select_cb2, &idx);
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
NULL)))
goto end;
if (idx == 1) {
prots = NULL;
protslen = 0;
}
/* SSL_set_alpn_protos returns 0 for success! */
if (!TEST_false(SSL_set_alpn_protos(clientssl, prots, protslen)))
goto end;
if (idx == 2 || idx == 3) {
/* We don't allow empty selection of NPN, so this should fail */
if (!TEST_false(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
} else {
const unsigned char *prot;
unsigned int protlen;
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE)))
goto end;
SSL_get0_alpn_selected(clientssl, &prot, &protlen);
switch (idx) {
case 0:
if (!TEST_mem_eq(prot, protlen, fooprot + 1, *fooprot))
goto end;
break;
case 1:
if (!TEST_uint_eq(protlen, 0))
goto end;
break;
default:
TEST_error("Should not get here");
goto end;
}
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n")
int setup_tests(void)
{
char *modulename;
char *configfile;
libctx = OSSL_LIB_CTX_new();
if (!TEST_ptr(libctx))
return 0;
defctxnull = OSSL_PROVIDER_load(NULL, "null");
/*
* Verify that the default and fips providers in the default libctx are not
* available
*/
if (!TEST_false(OSSL_PROVIDER_available(NULL, "default"))
|| !TEST_false(OSSL_PROVIDER_available(NULL, "fips")))
return 0;
if (!test_skip_common_options()) {
TEST_error("Error parsing test options\n");
return 0;
}
if (!TEST_ptr(certsdir = test_get_argument(0))
|| !TEST_ptr(srpvfile = test_get_argument(1))
|| !TEST_ptr(tmpfilename = test_get_argument(2))
|| !TEST_ptr(modulename = test_get_argument(3))
|| !TEST_ptr(configfile = test_get_argument(4))
|| !TEST_ptr(dhfile = test_get_argument(5)))
return 0;
if (!TEST_true(OSSL_LIB_CTX_load_config(libctx, configfile)))
return 0;
/* Check we have the expected provider available */
if (!TEST_true(OSSL_PROVIDER_available(libctx, modulename)))
return 0;
/* Check the default provider is not available */
if (strcmp(modulename, "default") != 0
&& !TEST_false(OSSL_PROVIDER_available(libctx, "default")))
return 0;
if (strcmp(modulename, "fips") == 0)
is_fips = 1;
/*
* We add, but don't load the test "tls-provider". We'll load it when we
* need it.
*/
if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "tls-provider",
tls_provider_init)))
return 0;
if (getenv("OPENSSL_TEST_GETCOUNTS") != NULL) {
#ifdef OPENSSL_NO_CRYPTO_MDEBUG
TEST_error("not supported in this build");
return 0;
#else
int i, mcount, rcount, fcount;
for (i = 0; i < 4; i++)
test_export_key_mat(i);
CRYPTO_get_alloc_counts(&mcount, &rcount, &fcount);
test_printf_stdout("malloc %d realloc %d free %d\n",
mcount, rcount, fcount);
return 1;
#endif
}
cert = test_mk_file_path(certsdir, "servercert.pem");
if (cert == NULL)
goto err;
privkey = test_mk_file_path(certsdir, "serverkey.pem");
if (privkey == NULL)
goto err;
cert2 = test_mk_file_path(certsdir, "server-ecdsa-cert.pem");
if (cert2 == NULL)
goto err;
privkey2 = test_mk_file_path(certsdir, "server-ecdsa-key.pem");
if (privkey2 == NULL)
goto err;
cert1024 = test_mk_file_path(certsdir, "ee-cert-1024.pem");
if (cert1024 == NULL)
goto err;
privkey1024 = test_mk_file_path(certsdir, "ee-key-1024.pem");
if (privkey1024 == NULL)
goto err;
cert3072 = test_mk_file_path(certsdir, "ee-cert-3072.pem");
if (cert3072 == NULL)
goto err;
privkey3072 = test_mk_file_path(certsdir, "ee-key-3072.pem");
if (privkey3072 == NULL)
goto err;
cert4096 = test_mk_file_path(certsdir, "ee-cert-4096.pem");
if (cert4096 == NULL)
goto err;
privkey4096 = test_mk_file_path(certsdir, "ee-key-4096.pem");
if (privkey4096 == NULL)
goto err;
cert8192 = test_mk_file_path(certsdir, "ee-cert-8192.pem");
if (cert8192 == NULL)
goto err;
privkey8192 = test_mk_file_path(certsdir, "ee-key-8192.pem");
if (privkey8192 == NULL)
goto err;
#if !defined(OPENSSL_NO_KTLS) && !defined(OPENSSL_NO_SOCK)
# if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3)
ADD_ALL_TESTS(test_ktls, NUM_KTLS_TEST_CIPHERS * 4);
ADD_ALL_TESTS(test_ktls_sendfile, NUM_KTLS_TEST_CIPHERS);
# endif
#endif
ADD_TEST(test_large_message_tls);
ADD_TEST(test_large_message_tls_read_ahead);
#ifndef OPENSSL_NO_DTLS
ADD_TEST(test_large_message_dtls);
#endif
ADD_ALL_TESTS(test_large_app_data, 28);
ADD_TEST(test_cleanse_plaintext);
#ifndef OPENSSL_NO_OCSP
ADD_TEST(test_tlsext_status_type);
#endif
ADD_TEST(test_session_with_only_int_cache);
ADD_TEST(test_session_with_only_ext_cache);
ADD_TEST(test_session_with_both_cache);
ADD_TEST(test_session_wo_ca_names);
#ifndef OSSL_NO_USABLE_TLS1_3
ADD_ALL_TESTS(test_stateful_tickets, 3);
ADD_ALL_TESTS(test_stateless_tickets, 3);
ADD_TEST(test_psk_tickets);
ADD_ALL_TESTS(test_extra_tickets, 6);
#endif
ADD_ALL_TESTS(test_ssl_set_bio, TOTAL_SSL_SET_BIO_TESTS);
ADD_TEST(test_ssl_bio_pop_next_bio);
ADD_TEST(test_ssl_bio_pop_ssl_bio);
ADD_TEST(test_ssl_bio_change_rbio);
ADD_TEST(test_ssl_bio_change_wbio);
#if !defined(OPENSSL_NO_TLS1_2) || defined(OSSL_NO_USABLE_TLS1_3)
ADD_ALL_TESTS(test_set_sigalgs, OSSL_NELEM(testsigalgs) * 2);
ADD_TEST(test_keylog);
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
ADD_TEST(test_keylog_no_master_key);
#endif
ADD_TEST(test_client_cert_verify_cb);
ADD_TEST(test_ssl_build_cert_chain);
ADD_TEST(test_ssl_ctx_build_cert_chain);
#ifndef OPENSSL_NO_TLS1_2
ADD_TEST(test_client_hello_cb);
ADD_TEST(test_no_ems);
ADD_TEST(test_ccs_change_cipher);
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
ADD_ALL_TESTS(test_early_data_read_write, 6);
/*
* We don't do replay tests for external PSK. Replay protection isn't used
* in that scenario.
*/
ADD_ALL_TESTS(test_early_data_replay, 2);
ADD_ALL_TESTS(test_early_data_skip, OSSL_NELEM(ciphersuites) * 3);
ADD_ALL_TESTS(test_early_data_skip_hrr, OSSL_NELEM(ciphersuites) * 3);
ADD_ALL_TESTS(test_early_data_skip_hrr_fail, OSSL_NELEM(ciphersuites) * 3);
ADD_ALL_TESTS(test_early_data_skip_abort, OSSL_NELEM(ciphersuites) * 3);
ADD_ALL_TESTS(test_early_data_not_sent, 3);
ADD_ALL_TESTS(test_early_data_psk, 8);
ADD_ALL_TESTS(test_early_data_psk_with_all_ciphers, 5);
ADD_ALL_TESTS(test_early_data_not_expected, 3);
# ifndef OPENSSL_NO_TLS1_2
ADD_ALL_TESTS(test_early_data_tls1_2, 3);
# endif
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
ADD_ALL_TESTS(test_set_ciphersuite, 10);
ADD_TEST(test_ciphersuite_change);
ADD_ALL_TESTS(test_tls13_ciphersuite, 4);
# ifdef OPENSSL_NO_PSK
ADD_ALL_TESTS(test_tls13_psk, 1);
# else
ADD_ALL_TESTS(test_tls13_psk, 4);
# endif /* OPENSSL_NO_PSK */
# ifndef OPENSSL_NO_TLS1_2
/* Test with both TLSv1.3 and 1.2 versions */
ADD_ALL_TESTS(test_key_exchange, 14);
# if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_DH)
ADD_ALL_TESTS(test_negotiated_group,
4 * (OSSL_NELEM(ecdhe_kexch_groups)
+ OSSL_NELEM(ffdhe_kexch_groups)));
# endif
# else
/* Test with only TLSv1.3 versions */
ADD_ALL_TESTS(test_key_exchange, 12);
# endif
ADD_ALL_TESTS(test_custom_exts, 6);
ADD_TEST(test_stateless);
ADD_TEST(test_pha_key_update);
#else
ADD_ALL_TESTS(test_custom_exts, 3);
#endif
ADD_ALL_TESTS(test_export_key_mat, 6);
#ifndef OSSL_NO_USABLE_TLS1_3
ADD_ALL_TESTS(test_export_key_mat_early, 3);
ADD_TEST(test_key_update);
ADD_ALL_TESTS(test_key_update_peer_in_write, 2);
ADD_ALL_TESTS(test_key_update_peer_in_read, 2);
ADD_ALL_TESTS(test_key_update_local_in_write, 2);
ADD_ALL_TESTS(test_key_update_local_in_read, 2);
#endif
ADD_ALL_TESTS(test_ssl_clear, 2);
ADD_ALL_TESTS(test_max_fragment_len_ext, OSSL_NELEM(max_fragment_len_test));
#if !defined(OPENSSL_NO_SRP) && !defined(OPENSSL_NO_TLS1_2)
ADD_ALL_TESTS(test_srp, 6);
#endif
ADD_ALL_TESTS(test_info_callback, 6);
ADD_ALL_TESTS(test_ssl_pending, 2);
ADD_ALL_TESTS(test_ssl_get_shared_ciphers, OSSL_NELEM(shared_ciphers_data));
ADD_ALL_TESTS(test_ticket_callbacks, 20);
ADD_ALL_TESTS(test_shutdown, 7);
ADD_ALL_TESTS(test_incorrect_shutdown, 2);
ADD_ALL_TESTS(test_cert_cb, 6);
ADD_ALL_TESTS(test_client_cert_cb, 2);
ADD_ALL_TESTS(test_ca_names, 3);
#ifndef OPENSSL_NO_TLS1_2
ADD_ALL_TESTS(test_multiblock_write, OSSL_NELEM(multiblock_cipherlist_data));
#endif
ADD_ALL_TESTS(test_servername, 10);
#if !defined(OPENSSL_NO_EC) \
&& (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2))
ADD_ALL_TESTS(test_sigalgs_available, 6);
#endif
#ifndef OPENSSL_NO_TLS1_3
ADD_ALL_TESTS(test_pluggable_group, 2);
#endif
#ifndef OPENSSL_NO_TLS1_2
ADD_TEST(test_ssl_dup);
# ifndef OPENSSL_NO_DH
ADD_ALL_TESTS(test_set_tmp_dh, 11);
ADD_ALL_TESTS(test_dh_auto, 7);
# endif
#endif
#ifndef OSSL_NO_USABLE_TLS1_3
ADD_TEST(test_sni_tls13);
ADD_ALL_TESTS(test_ticket_lifetime, 2);
#endif
ADD_TEST(test_inherit_verify_param);
ADD_TEST(test_set_alpn);
ADD_TEST(test_set_verify_cert_store_ssl_ctx);
ADD_TEST(test_set_verify_cert_store_ssl);
ADD_ALL_TESTS(test_session_timeout, 1);
#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
ADD_ALL_TESTS(test_session_cache_overflow, 4);
#endif
ADD_TEST(test_load_dhfile);
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3)
ADD_ALL_TESTS(test_serverinfo_custom, 4);
#endif
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE)
ADD_ALL_TESTS(test_pipelining, 7);
#endif
ADD_ALL_TESTS(test_handshake_retry, 16);
ADD_ALL_TESTS(test_multi_resume, 5);
ADD_ALL_TESTS(test_select_next_proto, OSSL_NELEM(next_proto_tests));
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG)
ADD_ALL_TESTS(test_npn, 5);
#endif
ADD_ALL_TESTS(test_alpn, 4);
return 1;
err:
OPENSSL_free(cert);
OPENSSL_free(privkey);
OPENSSL_free(cert2);
OPENSSL_free(privkey2);
return 0;
}
void cleanup_tests(void)
{
# if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DH)
EVP_PKEY_free(tmp_dh_params);
#endif
OPENSSL_free(cert);
OPENSSL_free(privkey);
OPENSSL_free(cert2);
OPENSSL_free(privkey2);
OPENSSL_free(cert1024);
OPENSSL_free(privkey1024);
OPENSSL_free(cert3072);
OPENSSL_free(privkey3072);
OPENSSL_free(cert4096);
OPENSSL_free(privkey4096);
OPENSSL_free(cert8192);
OPENSSL_free(privkey8192);
bio_s_mempacket_test_free();
bio_s_always_retry_free();
OSSL_PROVIDER_unload(defctxnull);
OSSL_LIB_CTX_free(libctx);
}
diff --git a/crypto/openssl/test/testutil/tests.c b/crypto/openssl/test/testutil/tests.c
index ef7e224cd119..05526870acd3 100644
--- a/crypto/openssl/test/testutil/tests.c
+++ b/crypto/openssl/test/testutil/tests.c
@@ -1,472 +1,473 @@
/*
- * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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 "../testutil.h"
#include "output.h"
#include "tu_local.h"
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include "internal/nelem.h"
#include <openssl/asn1.h>
/*
* Output a failed test first line.
* All items are optional are generally not preinted if passed as NULL.
* The special cases are for prefix where "ERROR" is assumed and for left
* and right where a non-failure message is produced if either is NULL.
*/
void test_fail_message_prefix(const char *prefix, const char *file,
int line, const char *type,
const char *left, const char *right,
const char *op)
{
test_printf_stderr("%s: ", prefix != NULL ? prefix : "ERROR");
if (type)
test_printf_stderr("(%s) ", type);
if (op != NULL) {
if (left != NULL && right != NULL)
test_printf_stderr("'%s %s %s' failed", left, op, right);
else
test_printf_stderr("'%s'", op);
}
if (file != NULL) {
test_printf_stderr(" @ %s:%d", file, line);
}
test_printf_stderr("\n");
}
/*
* A common routine to output test failure messages. Generally this should not
* be called directly, rather it should be called by the following functions.
*
* |desc| is a printf formatted description with arguments |args| that is
* supplied by the user and |desc| can be NULL. |type| is the data type
* that was tested (int, char, ptr, ...). |fmt| is a system provided
* printf format with following arguments that spell out the failure
* details i.e. the actual values compared and the operator used.
*
* The typical use for this is from an utility test function:
*
* int test6(const char *file, int line, int n) {
* if (n != 6) {
* test_fail_message(1, file, line, "int", "value %d is not %d", n, 6);
* return 0;
* }
* return 1;
* }
*
* calling test6(3, "oops") will return 0 and produce out along the lines of:
* FAIL oops: (int) value 3 is not 6\n
*/
static void test_fail_message(const char *prefix, const char *file, int line,
const char *type, const char *left,
const char *right, const char *op,
const char *fmt, ...)
PRINTF_FORMAT(8, 9);
static void test_fail_message_va(const char *prefix, const char *file,
int line, const char *type,
const char *left, const char *right,
const char *op, const char *fmt, va_list ap)
{
test_fail_message_prefix(prefix, file, line, type, left, right, op);
if (fmt != NULL) {
test_vprintf_stderr(fmt, ap);
test_printf_stderr("\n");
}
test_flush_stderr();
}
static void test_fail_message(const char *prefix, const char *file,
int line, const char *type,
const char *left, const char *right,
const char *op, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
test_fail_message_va(prefix, file, line, type, left, right, op, fmt, ap);
va_end(ap);
}
void test_info_c90(const char *desc, ...)
{
va_list ap;
va_start(ap, desc);
test_fail_message_va("INFO", NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
va_end(ap);
}
void test_info(const char *file, int line, const char *desc, ...)
{
va_list ap;
va_start(ap, desc);
test_fail_message_va("INFO", file, line, NULL, NULL, NULL, NULL, desc, ap);
va_end(ap);
}
void test_error_c90(const char *desc, ...)
{
va_list ap;
va_start(ap, desc);
test_fail_message_va(NULL, NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
va_end(ap);
test_printf_stderr("\n");
}
void test_error(const char *file, int line, const char *desc, ...)
{
va_list ap;
va_start(ap, desc);
test_fail_message_va(NULL, file, line, NULL, NULL, NULL, NULL, desc, ap);
va_end(ap);
test_printf_stderr("\n");
}
void test_perror(const char *s)
{
/*
* Using openssl_strerror_r causes linking issues since it isn't
* exported from libcrypto.so
*/
TEST_error("%s: %s", s, strerror(errno));
}
void test_note(const char *fmt, ...)
{
+ test_flush_stdout();
if (fmt != NULL) {
va_list ap;
va_start(ap, fmt);
test_vprintf_stderr(fmt, ap);
va_end(ap);
test_printf_stderr("\n");
}
test_flush_stderr();
}
int test_skip(const char *file, int line, const char *desc, ...)
{
va_list ap;
va_start(ap, desc);
test_fail_message_va("SKIP", file, line, NULL, NULL, NULL, NULL, desc, ap);
va_end(ap);
return TEST_SKIP_CODE;
}
int test_skip_c90(const char *desc, ...)
{
va_list ap;
va_start(ap, desc);
test_fail_message_va("SKIP", NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
va_end(ap);
test_printf_stderr("\n");
return TEST_SKIP_CODE;
}
void test_openssl_errors(void)
{
ERR_print_errors_cb(openssl_error_cb, NULL);
ERR_clear_error();
}
/*
* Define some comparisons between pairs of various types.
* These functions return 1 if the test is true.
* Otherwise, they return 0 and pretty-print diagnostics.
*
* In each case the functions produced are:
* int test_name_eq(const type t1, const type t2, const char *desc, ...);
* int test_name_ne(const type t1, const type t2, const char *desc, ...);
* int test_name_lt(const type t1, const type t2, const char *desc, ...);
* int test_name_le(const type t1, const type t2, const char *desc, ...);
* int test_name_gt(const type t1, const type t2, const char *desc, ...);
* int test_name_ge(const type t1, const type t2, const char *desc, ...);
*
* The t1 and t2 arguments are to be compared for equality, inequality,
* less than, less than or equal to, greater than and greater than or
* equal to respectively. If the specified condition holds, the functions
* return 1. If the condition does not hold, the functions print a diagnostic
* message and return 0.
*
* The desc argument is a printf format string followed by its arguments and
* this is included in the output if the condition being tested for is false.
*/
#define DEFINE_COMPARISON(type, name, opname, op, fmt) \
int test_ ## name ## _ ## opname(const char *file, int line, \
const char *s1, const char *s2, \
const type t1, const type t2) \
{ \
if (t1 op t2) \
return 1; \
test_fail_message(NULL, file, line, #type, s1, s2, #op, \
"[" fmt "] compared to [" fmt "]", \
t1, t2); \
return 0; \
}
#define DEFINE_COMPARISONS(type, name, fmt) \
DEFINE_COMPARISON(type, name, eq, ==, fmt) \
DEFINE_COMPARISON(type, name, ne, !=, fmt) \
DEFINE_COMPARISON(type, name, lt, <, fmt) \
DEFINE_COMPARISON(type, name, le, <=, fmt) \
DEFINE_COMPARISON(type, name, gt, >, fmt) \
DEFINE_COMPARISON(type, name, ge, >=, fmt)
DEFINE_COMPARISONS(int, int, "%d")
DEFINE_COMPARISONS(unsigned int, uint, "%u")
DEFINE_COMPARISONS(char, char, "%c")
DEFINE_COMPARISONS(unsigned char, uchar, "%u")
DEFINE_COMPARISONS(long, long, "%ld")
DEFINE_COMPARISONS(unsigned long, ulong, "%lu")
DEFINE_COMPARISONS(size_t, size_t, "%zu")
DEFINE_COMPARISONS(double, double, "%g")
DEFINE_COMPARISON(void *, ptr, eq, ==, "%p")
DEFINE_COMPARISON(void *, ptr, ne, !=, "%p")
int test_ptr_null(const char *file, int line, const char *s, const void *p)
{
if (p == NULL)
return 1;
test_fail_message(NULL, file, line, "ptr", s, "NULL", "==", "%p", p);
return 0;
}
int test_ptr(const char *file, int line, const char *s, const void *p)
{
if (p != NULL)
return 1;
test_fail_message(NULL, file, line, "ptr", s, "NULL", "!=", "%p", p);
return 0;
}
int test_true(const char *file, int line, const char *s, int b)
{
if (b)
return 1;
test_fail_message(NULL, file, line, "bool", s, "true", "==", "false");
return 0;
}
int test_false(const char *file, int line, const char *s, int b)
{
if (!b)
return 1;
test_fail_message(NULL, file, line, "bool", s, "false", "==", "true");
return 0;
}
int test_str_eq(const char *file, int line, const char *st1, const char *st2,
const char *s1, const char *s2)
{
if (s1 == NULL && s2 == NULL)
return 1;
if (s1 == NULL || s2 == NULL || strcmp(s1, s2) != 0) {
test_fail_string_message(NULL, file, line, "string", st1, st2, "==",
s1, s1 == NULL ? 0 : strlen(s1),
s2, s2 == NULL ? 0 : strlen(s2));
return 0;
}
return 1;
}
int test_str_ne(const char *file, int line, const char *st1, const char *st2,
const char *s1, const char *s2)
{
if ((s1 == NULL) ^ (s2 == NULL))
return 1;
if (s1 == NULL || strcmp(s1, s2) == 0) {
test_fail_string_message(NULL, file, line, "string", st1, st2, "!=",
s1, s1 == NULL ? 0 : strlen(s1),
s2, s2 == NULL ? 0 : strlen(s2));
return 0;
}
return 1;
}
int test_strn_eq(const char *file, int line, const char *st1, const char *st2,
const char *s1, size_t n1, const char *s2, size_t n2)
{
if (s1 == NULL && s2 == NULL)
return 1;
if (n1 != n2 || s1 == NULL || s2 == NULL || strncmp(s1, s2, n1) != 0) {
test_fail_string_message(NULL, file, line, "string", st1, st2, "==",
s1, s1 == NULL ? 0 : OPENSSL_strnlen(s1, n1),
s2, s2 == NULL ? 0 : OPENSSL_strnlen(s2, n2));
return 0;
}
return 1;
}
int test_strn_ne(const char *file, int line, const char *st1, const char *st2,
const char *s1, size_t n1, const char *s2, size_t n2)
{
if ((s1 == NULL) ^ (s2 == NULL))
return 1;
if (n1 != n2 || s1 == NULL || strncmp(s1, s2, n1) == 0) {
test_fail_string_message(NULL, file, line, "string", st1, st2, "!=",
s1, s1 == NULL ? 0 : OPENSSL_strnlen(s1, n1),
s2, s2 == NULL ? 0 : OPENSSL_strnlen(s2, n2));
return 0;
}
return 1;
}
int test_mem_eq(const char *file, int line, const char *st1, const char *st2,
const void *s1, size_t n1, const void *s2, size_t n2)
{
if (s1 == NULL && s2 == NULL)
return 1;
if (n1 != n2 || s1 == NULL || s2 == NULL || memcmp(s1, s2, n1) != 0) {
test_fail_memory_message(NULL, file, line, "memory", st1, st2, "==",
s1, n1, s2, n2);
return 0;
}
return 1;
}
int test_mem_ne(const char *file, int line, const char *st1, const char *st2,
const void *s1, size_t n1, const void *s2, size_t n2)
{
if ((s1 == NULL) ^ (s2 == NULL))
return 1;
if (n1 != n2)
return 1;
if (s1 == NULL || memcmp(s1, s2, n1) == 0) {
test_fail_memory_message(NULL, file, line, "memory", st1, st2, "!=",
s1, n1, s2, n2);
return 0;
}
return 1;
}
#define DEFINE_BN_COMPARISONS(opname, op, zero_cond) \
int test_BN_ ## opname(const char *file, int line, \
const char *s1, const char *s2, \
const BIGNUM *t1, const BIGNUM *t2) \
{ \
if (BN_cmp(t1, t2) op 0) \
return 1; \
test_fail_bignum_message(NULL, file, line, "BIGNUM", s1, s2, \
#op, t1, t2); \
return 0; \
} \
int test_BN_ ## opname ## _zero(const char *file, int line, \
const char *s, const BIGNUM *a) \
{ \
if (a != NULL &&(zero_cond)) \
return 1; \
test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", \
s, "0", #op, a); \
return 0; \
}
DEFINE_BN_COMPARISONS(eq, ==, BN_is_zero(a))
DEFINE_BN_COMPARISONS(ne, !=, !BN_is_zero(a))
DEFINE_BN_COMPARISONS(gt, >, !BN_is_negative(a) && !BN_is_zero(a))
DEFINE_BN_COMPARISONS(ge, >=, !BN_is_negative(a) || BN_is_zero(a))
DEFINE_BN_COMPARISONS(lt, <, BN_is_negative(a) && !BN_is_zero(a))
DEFINE_BN_COMPARISONS(le, <=, BN_is_negative(a) || BN_is_zero(a))
int test_BN_eq_one(const char *file, int line, const char *s, const BIGNUM *a)
{
if (a != NULL && BN_is_one(a))
return 1;
test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", s, "1", "==", a);
return 0;
}
int test_BN_odd(const char *file, int line, const char *s, const BIGNUM *a)
{
if (a != NULL && BN_is_odd(a))
return 1;
test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", "ODD(", ")", s, a);
return 0;
}
int test_BN_even(const char *file, int line, const char *s, const BIGNUM *a)
{
if (a != NULL && !BN_is_odd(a))
return 1;
test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", "EVEN(", ")", s,
a);
return 0;
}
int test_BN_eq_word(const char *file, int line, const char *bns, const char *ws,
const BIGNUM *a, BN_ULONG w)
{
BIGNUM *bw;
if (a != NULL && BN_is_word(a, w))
return 1;
if ((bw = BN_new()) != NULL)
BN_set_word(bw, w);
test_fail_bignum_message(NULL, file, line, "BIGNUM", bns, ws, "==", a, bw);
BN_free(bw);
return 0;
}
int test_BN_abs_eq_word(const char *file, int line, const char *bns,
const char *ws, const BIGNUM *a, BN_ULONG w)
{
BIGNUM *bw, *aa;
if (a != NULL && BN_abs_is_word(a, w))
return 1;
if ((aa = BN_dup(a)) != NULL)
BN_set_negative(aa, 0);
if ((bw = BN_new()) != NULL)
BN_set_word(bw, w);
test_fail_bignum_message(NULL, file, line, "BIGNUM", bns, ws, "abs==",
aa, bw);
BN_free(bw);
BN_free(aa);
return 0;
}
static const char *print_time(const ASN1_TIME *t)
{
return t == NULL ? "<null>" : (const char *)ASN1_STRING_get0_data(t);
}
#define DEFINE_TIME_T_COMPARISON(opname, op) \
int test_time_t_ ## opname(const char *file, int line, \
const char *s1, const char *s2, \
const time_t t1, const time_t t2) \
{ \
ASN1_TIME *at1 = ASN1_TIME_set(NULL, t1); \
ASN1_TIME *at2 = ASN1_TIME_set(NULL, t2); \
int r = at1 != NULL && at2 != NULL \
&& ASN1_TIME_compare(at1, at2) op 0; \
if (!r) \
test_fail_message(NULL, file, line, "time_t", s1, s2, #op, \
"[%s] compared to [%s]", \
print_time(at1), print_time(at2)); \
ASN1_STRING_free(at1); \
ASN1_STRING_free(at2); \
return r; \
}
DEFINE_TIME_T_COMPARISON(eq, ==)
DEFINE_TIME_T_COMPARISON(ne, !=)
DEFINE_TIME_T_COMPARISON(gt, >)
DEFINE_TIME_T_COMPARISON(ge, >=)
DEFINE_TIME_T_COMPARISON(lt, <)
DEFINE_TIME_T_COMPARISON(le, <=)
diff --git a/crypto/openssl/test/threadstest.c b/crypto/openssl/test/threadstest.c
index 289565c14b5d..046a9eb80239 100644
--- a/crypto/openssl/test/threadstest.c
+++ b/crypto/openssl/test/threadstest.c
@@ -1,728 +1,728 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not 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
*/
/* test_multi below tests the thread safety of a deprecated function */
#define OPENSSL_SUPPRESS_DEPRECATED
#if defined(_WIN32)
# include <windows.h>
#endif
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/rsa.h>
#include <openssl/aes.h>
#include <openssl/rsa.h>
#include "testutil.h"
#include "threadstest.h"
/* Limit the maximum number of threads */
#define MAXIMUM_THREADS 10
/* Limit the maximum number of providers loaded into a library context */
#define MAXIMUM_PROVIDERS 4
static int do_fips = 0;
static char *privkey;
static char *config_file = NULL;
static int multidefault_run = 0;
static const char *default_provider[] = { "default", NULL };
static int test_lock(void)
{
CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
int res;
res = TEST_true(CRYPTO_THREAD_read_lock(lock))
&& TEST_true(CRYPTO_THREAD_unlock(lock))
&& TEST_true(CRYPTO_THREAD_write_lock(lock))
&& TEST_true(CRYPTO_THREAD_unlock(lock));
CRYPTO_THREAD_lock_free(lock);
return res;
}
static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT;
static unsigned once_run_count = 0;
static void once_do_run(void)
{
once_run_count++;
}
static void once_run_thread_cb(void)
{
CRYPTO_THREAD_run_once(&once_run, once_do_run);
}
static int test_once(void)
{
thread_t thread;
if (!TEST_true(run_thread(&thread, once_run_thread_cb))
|| !TEST_true(wait_for_thread(thread))
|| !CRYPTO_THREAD_run_once(&once_run, once_do_run)
|| !TEST_int_eq(once_run_count, 1))
return 0;
return 1;
}
static CRYPTO_THREAD_LOCAL thread_local_key;
static unsigned destructor_run_count = 0;
static int thread_local_thread_cb_ok = 0;
static void thread_local_destructor(void *arg)
{
unsigned *count;
if (arg == NULL)
return;
count = arg;
(*count)++;
}
static void thread_local_thread_cb(void)
{
void *ptr;
ptr = CRYPTO_THREAD_get_local(&thread_local_key);
if (!TEST_ptr_null(ptr)
|| !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key,
&destructor_run_count)))
return;
ptr = CRYPTO_THREAD_get_local(&thread_local_key);
if (!TEST_ptr_eq(ptr, &destructor_run_count))
return;
thread_local_thread_cb_ok = 1;
}
static int test_thread_local(void)
{
thread_t thread;
void *ptr = NULL;
if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key,
thread_local_destructor)))
return 0;
ptr = CRYPTO_THREAD_get_local(&thread_local_key);
if (!TEST_ptr_null(ptr)
|| !TEST_true(run_thread(&thread, thread_local_thread_cb))
|| !TEST_true(wait_for_thread(thread))
|| !TEST_int_eq(thread_local_thread_cb_ok, 1))
return 0;
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
ptr = CRYPTO_THREAD_get_local(&thread_local_key);
if (!TEST_ptr_null(ptr))
return 0;
# if !defined(OPENSSL_SYS_WINDOWS)
if (!TEST_int_eq(destructor_run_count, 1))
return 0;
# endif
#endif
if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key)))
return 0;
return 1;
}
static int test_atomic(void)
{
int val = 0, ret = 0, testresult = 0;
uint64_t val64 = 1, ret64 = 0;
CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
if (!TEST_ptr(lock))
return 0;
if (CRYPTO_atomic_add(&val, 1, &ret, NULL)) {
/* This succeeds therefore we're on a platform with lockless atomics */
if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret))
goto err;
} else {
/* This failed therefore we're on a platform without lockless atomics */
if (!TEST_int_eq(val, 0) || !TEST_int_eq(val, ret))
goto err;
}
val = 0;
ret = 0;
if (!TEST_true(CRYPTO_atomic_add(&val, 1, &ret, lock)))
goto err;
if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret))
goto err;
if (CRYPTO_atomic_or(&val64, 2, &ret64, NULL)) {
/* This succeeds therefore we're on a platform with lockless atomics */
if (!TEST_uint_eq((unsigned int)val64, 3)
|| !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
goto err;
} else {
/* This failed therefore we're on a platform without lockless atomics */
if (!TEST_uint_eq((unsigned int)val64, 1)
|| !TEST_int_eq((unsigned int)ret64, 0))
goto err;
}
val64 = 1;
ret64 = 0;
if (!TEST_true(CRYPTO_atomic_or(&val64, 2, &ret64, lock)))
goto err;
if (!TEST_uint_eq((unsigned int)val64, 3)
|| !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
goto err;
ret64 = 0;
if (CRYPTO_atomic_load(&val64, &ret64, NULL)) {
/* This succeeds therefore we're on a platform with lockless atomics */
if (!TEST_uint_eq((unsigned int)val64, 3)
|| !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
goto err;
} else {
/* This failed therefore we're on a platform without lockless atomics */
if (!TEST_uint_eq((unsigned int)val64, 3)
|| !TEST_int_eq((unsigned int)ret64, 0))
goto err;
}
ret64 = 0;
if (!TEST_true(CRYPTO_atomic_load(&val64, &ret64, lock)))
goto err;
if (!TEST_uint_eq((unsigned int)val64, 3)
|| !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
goto err;
testresult = 1;
err:
CRYPTO_THREAD_lock_free(lock);
return testresult;
}
static OSSL_LIB_CTX *multi_libctx = NULL;
static int multi_success;
static OSSL_PROVIDER *multi_provider[MAXIMUM_PROVIDERS + 1];
static size_t multi_num_threads;
static thread_t multi_threads[MAXIMUM_THREADS];
static void multi_intialise(void)
{
multi_success = 1;
multi_libctx = NULL;
multi_num_threads = 0;
memset(multi_threads, 0, sizeof(multi_threads));
memset(multi_provider, 0, sizeof(multi_provider));
}
static void thead_teardown_libctx(void)
{
OSSL_PROVIDER **p;
for (p = multi_provider; *p != NULL; p++)
OSSL_PROVIDER_unload(*p);
OSSL_LIB_CTX_free(multi_libctx);
multi_intialise();
}
static int thread_setup_libctx(int libctx, const char *providers[])
{
size_t n;
if (libctx && !TEST_true(test_get_libctx(&multi_libctx, NULL, config_file,
NULL, NULL)))
return 0;
if (providers != NULL)
for (n = 0; providers[n] != NULL; n++)
if (!TEST_size_t_lt(n, MAXIMUM_PROVIDERS)
|| !TEST_ptr(multi_provider[n] = OSSL_PROVIDER_load(multi_libctx,
providers[n]))) {
thead_teardown_libctx();
return 0;
}
return 1;
}
static int teardown_threads(void)
{
size_t i;
for (i = 0; i < multi_num_threads; i++)
if (!TEST_true(wait_for_thread(multi_threads[i])))
return 0;
return 1;
}
static int start_threads(size_t n, void (*thread_func)(void))
{
size_t i;
if (!TEST_size_t_le(multi_num_threads + n, MAXIMUM_THREADS))
return 0;
for (i = 0 ; i < n; i++)
if (!TEST_true(run_thread(multi_threads + multi_num_threads++, thread_func)))
return 0;
return 1;
}
/* Template multi-threaded test function */
static int thread_run_test(void (*main_func)(void),
size_t num_threads, void (*thread_func)(void),
int libctx, const char *providers[])
{
int testresult = 0;
multi_intialise();
if (!thread_setup_libctx(libctx, providers)
|| !start_threads(num_threads, thread_func))
goto err;
if (main_func != NULL)
main_func();
if (!teardown_threads()
|| !TEST_true(multi_success))
goto err;
testresult = 1;
err:
thead_teardown_libctx();
return testresult;
}
static void thread_general_worker(void)
{
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
EVP_CIPHER_CTX *cipherctx = EVP_CIPHER_CTX_new();
EVP_CIPHER *ciph = EVP_CIPHER_fetch(multi_libctx, "AES-128-CBC", NULL);
const char *message = "Hello World";
size_t messlen = strlen(message);
/* Should be big enough for encryption output too */
unsigned char out[EVP_MAX_MD_SIZE];
const unsigned char key[AES_BLOCK_SIZE] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f
};
const unsigned char iv[AES_BLOCK_SIZE] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f
};
unsigned int mdoutl;
int ciphoutl;
EVP_PKEY *pkey = NULL;
int testresult = 0;
int i, isfips;
isfips = OSSL_PROVIDER_available(multi_libctx, "fips");
if (!TEST_ptr(mdctx)
|| !TEST_ptr(md)
|| !TEST_ptr(cipherctx)
|| !TEST_ptr(ciph))
goto err;
/* Do some work */
for (i = 0; i < 5; i++) {
if (!TEST_true(EVP_DigestInit_ex(mdctx, md, NULL))
|| !TEST_true(EVP_DigestUpdate(mdctx, message, messlen))
|| !TEST_true(EVP_DigestFinal(mdctx, out, &mdoutl)))
goto err;
}
for (i = 0; i < 5; i++) {
if (!TEST_true(EVP_EncryptInit_ex(cipherctx, ciph, NULL, key, iv))
|| !TEST_true(EVP_EncryptUpdate(cipherctx, out, &ciphoutl,
(unsigned char *)message,
messlen))
|| !TEST_true(EVP_EncryptFinal(cipherctx, out, &ciphoutl)))
goto err;
}
/*
* We want the test to run quickly - not securely.
* Therefore we use an insecure bit length where we can (512).
* In the FIPS module though we must use a longer length.
*/
- pkey = EVP_PKEY_Q_keygen(multi_libctx, NULL, "RSA", isfips ? 2048 : 512);
+ pkey = EVP_PKEY_Q_keygen(multi_libctx, NULL, "RSA", (size_t)(isfips ? 2048 : 512));
if (!TEST_ptr(pkey))
goto err;
testresult = 1;
err:
EVP_MD_CTX_free(mdctx);
EVP_MD_free(md);
EVP_CIPHER_CTX_free(cipherctx);
EVP_CIPHER_free(ciph);
EVP_PKEY_free(pkey);
if (!testresult)
multi_success = 0;
}
static void thread_multi_simple_fetch(void)
{
EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
if (md != NULL)
EVP_MD_free(md);
else
multi_success = 0;
}
static EVP_PKEY *shared_evp_pkey = NULL;
static void thread_shared_evp_pkey(void)
{
char *msg = "Hello World";
unsigned char ctbuf[256];
unsigned char ptbuf[256];
size_t ptlen, ctlen = sizeof(ctbuf);
EVP_PKEY_CTX *ctx = NULL;
int success = 0;
int i;
for (i = 0; i < 1 + do_fips; i++) {
if (i > 0)
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey,
i == 0 ? "provider=default"
: "provider=fips");
if (!TEST_ptr(ctx))
goto err;
if (!TEST_int_ge(EVP_PKEY_encrypt_init(ctx), 0)
|| !TEST_int_ge(EVP_PKEY_encrypt(ctx, ctbuf, &ctlen,
(unsigned char *)msg, strlen(msg)),
0))
goto err;
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, NULL);
if (!TEST_ptr(ctx))
goto err;
ptlen = sizeof(ptbuf);
if (!TEST_int_ge(EVP_PKEY_decrypt_init(ctx), 0)
|| !TEST_int_gt(EVP_PKEY_decrypt(ctx, ptbuf, &ptlen, ctbuf, ctlen),
0)
|| !TEST_mem_eq(msg, strlen(msg), ptbuf, ptlen))
goto err;
}
success = 1;
err:
EVP_PKEY_CTX_free(ctx);
if (!success)
multi_success = 0;
}
static void thread_downgrade_shared_evp_pkey(void)
{
#ifndef OPENSSL_NO_DEPRECATED_3_0
/*
* This test is only relevant for deprecated functions that perform
* downgrading
*/
if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL)
multi_success = 0;
#else
/* Shouldn't ever get here */
multi_success = 0;
#endif
}
static void thread_provider_load_unload(void)
{
OSSL_PROVIDER *deflt = OSSL_PROVIDER_load(multi_libctx, "default");
if (!TEST_ptr(deflt)
|| !TEST_true(OSSL_PROVIDER_available(multi_libctx, "default")))
multi_success = 0;
OSSL_PROVIDER_unload(deflt);
}
/*
* Do work in multiple worker threads at the same time.
* Test 0: General worker, using the default provider
* Test 1: General worker, using the fips provider
* Test 2: Simple fetch worker
* Test 3: Worker downgrading a shared EVP_PKEY
* Test 4: Worker using a shared EVP_PKEY
* Test 5: Worker loading and unloading a provider
*/
static int test_multi(int idx)
{
thread_t thread1, thread2;
int testresult = 0;
OSSL_PROVIDER *prov = NULL, *prov2 = NULL;
void (*worker)(void) = NULL;
void (*worker2)(void) = NULL;
EVP_MD *sha256 = NULL;
if (idx == 1 && !do_fips)
return TEST_skip("FIPS not supported");
#ifdef OPENSSL_NO_DEPRECATED_3_0
if (idx == 3)
return TEST_skip("Skipping tests for deprected functions");
#endif
multi_success = 1;
if (!TEST_true(test_get_libctx(&multi_libctx, NULL, config_file,
NULL, NULL)))
return 0;
prov = OSSL_PROVIDER_load(multi_libctx, (idx == 1) ? "fips" : "default");
if (!TEST_ptr(prov))
goto err;
switch (idx) {
case 0:
case 1:
worker = thread_general_worker;
break;
case 2:
worker = thread_multi_simple_fetch;
break;
case 3:
worker2 = thread_downgrade_shared_evp_pkey;
/* fall through */
case 4:
/*
* If available we have both the default and fips providers for this
* test
*/
if (do_fips
&& !TEST_ptr(prov2 = OSSL_PROVIDER_load(multi_libctx, "fips")))
goto err;
if (!TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx)))
goto err;
worker = thread_shared_evp_pkey;
break;
case 5:
/*
* We ensure we get an md from the default provider, and then unload the
* provider. This ensures the provider remains around but in a
* deactivated state.
*/
sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
OSSL_PROVIDER_unload(prov);
prov = NULL;
worker = thread_provider_load_unload;
break;
default:
TEST_error("Invalid test index");
goto err;
}
if (worker2 == NULL)
worker2 = worker;
if (!TEST_true(run_thread(&thread1, worker))
|| !TEST_true(run_thread(&thread2, worker2)))
goto err;
worker();
testresult = 1;
/*
* Don't combine these into one if statement; must wait for both threads.
*/
if (!TEST_true(wait_for_thread(thread1)))
testresult = 0;
if (!TEST_true(wait_for_thread(thread2)))
testresult = 0;
if (!TEST_true(multi_success))
testresult = 0;
err:
EVP_MD_free(sha256);
OSSL_PROVIDER_unload(prov);
OSSL_PROVIDER_unload(prov2);
OSSL_LIB_CTX_free(multi_libctx);
EVP_PKEY_free(shared_evp_pkey);
shared_evp_pkey = NULL;
multi_libctx = NULL;
return testresult;
}
static char *multi_load_provider = "legacy";
/*
* This test attempts to load several providers at the same time, and if
* run with a thread sanitizer, should crash if the core provider code
* doesn't synchronize well enough.
*/
#define MULTI_LOAD_THREADS 10
static void test_multi_load_worker(void)
{
OSSL_PROVIDER *prov;
if (!TEST_ptr(prov = OSSL_PROVIDER_load(NULL, multi_load_provider))
|| !TEST_true(OSSL_PROVIDER_unload(prov)))
multi_success = 0;
}
static int test_multi_default(void)
{
thread_t thread1, thread2;
int testresult = 0;
OSSL_PROVIDER *prov = NULL;
/* Avoid running this test twice */
if (multidefault_run) {
TEST_skip("multi default test already run");
return 1;
}
multidefault_run = 1;
multi_success = 1;
multi_libctx = NULL;
prov = OSSL_PROVIDER_load(multi_libctx, "default");
if (!TEST_ptr(prov))
goto err;
if (!TEST_true(run_thread(&thread1, thread_multi_simple_fetch))
|| !TEST_true(run_thread(&thread2, thread_multi_simple_fetch)))
goto err;
thread_multi_simple_fetch();
if (!TEST_true(wait_for_thread(thread1))
|| !TEST_true(wait_for_thread(thread2))
|| !TEST_true(multi_success))
goto err;
testresult = 1;
err:
OSSL_PROVIDER_unload(prov);
return testresult;
}
static int test_multi_load(void)
{
thread_t threads[MULTI_LOAD_THREADS];
int i, res = 1;
OSSL_PROVIDER *prov;
/* The multidefault test must run prior to this test */
if (!multidefault_run) {
TEST_info("Running multi default test first");
res = test_multi_default();
}
/*
* We use the legacy provider in test_multi_load_worker because it uses a
* child libctx that might hit more codepaths that might be sensitive to
* threading issues. But in a no-legacy build that won't be loadable so
* we use the default provider instead.
*/
prov = OSSL_PROVIDER_load(NULL, "legacy");
if (prov == NULL) {
TEST_info("Cannot load legacy provider - assuming this is a no-legacy build");
multi_load_provider = "default";
}
OSSL_PROVIDER_unload(prov);
multi_success = 1;
for (i = 0; i < MULTI_LOAD_THREADS; i++)
(void)TEST_true(run_thread(&threads[i], test_multi_load_worker));
for (i = 0; i < MULTI_LOAD_THREADS; i++)
(void)TEST_true(wait_for_thread(threads[i]));
return res && multi_success;
}
static void test_lib_ctx_load_config_worker(void)
{
if (!TEST_int_eq(OSSL_LIB_CTX_load_config(multi_libctx, config_file), 1))
multi_success = 0;
}
static int test_lib_ctx_load_config(void)
{
return thread_run_test(&test_lib_ctx_load_config_worker,
MAXIMUM_THREADS, &test_lib_ctx_load_config_worker,
1, default_provider);
}
typedef enum OPTION_choice {
OPT_ERR = -1,
OPT_EOF = 0,
OPT_FIPS, OPT_CONFIG_FILE,
OPT_TEST_ENUM
} OPTION_CHOICE;
const OPTIONS *test_get_options(void)
{
static const OPTIONS options[] = {
OPT_TEST_OPTIONS_DEFAULT_USAGE,
{ "fips", OPT_FIPS, '-', "Test the FIPS provider" },
{ "config", OPT_CONFIG_FILE, '<',
"The configuration file to use for the libctx" },
{ NULL }
};
return options;
}
int setup_tests(void)
{
OPTION_CHOICE o;
char *datadir;
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_FIPS:
do_fips = 1;
break;
case OPT_CONFIG_FILE:
config_file = opt_arg();
break;
case OPT_TEST_CASES:
break;
default:
return 0;
}
}
if (!TEST_ptr(datadir = test_get_argument(0)))
return 0;
privkey = test_mk_file_path(datadir, "rsakey.pem");
if (!TEST_ptr(privkey))
return 0;
/* Keep first to validate auto creation of default library context */
ADD_TEST(test_multi_default);
ADD_TEST(test_lock);
ADD_TEST(test_once);
ADD_TEST(test_thread_local);
ADD_TEST(test_atomic);
ADD_TEST(test_multi_load);
ADD_ALL_TESTS(test_multi, 6);
ADD_TEST(test_lib_ctx_load_config);
return 1;
}
void cleanup_tests(void)
{
OPENSSL_free(privkey);
}
diff --git a/crypto/openssl/util/check-format-commit.sh b/crypto/openssl/util/check-format-commit.sh
index 7e712dc48cf6..206827dd8669 100755
--- a/crypto/openssl/util/check-format-commit.sh
+++ b/crypto/openssl/util/check-format-commit.sh
@@ -1,171 +1,170 @@
#!/bin/bash
# Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License").
# You may not 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 script is a wrapper around check-format.pl. It accepts a commit sha
-# value as input, and uses it to identify the files and ranges that were
-# changed in that commit, filtering check-format.pl output only to lines that
-# fall into the commits change ranges.
-#
-
-
-# List of Regexes to use when running check-format.pl.
-# Style checks don't apply to any of these
-EXCLUDED_FILE_REGEX=("\.pod" \
- "\.pl" \
- "\.pm" \
- "\.t" \
- "\.yml" \
- "\.sh")
-
-# Exit code for the script
-EXIT_CODE=0
+# This script is a wrapper around check-format.pl.
+# It accepts the same commit revision range as 'git diff' as arguments,
+# or just a single commit id, and uses it to identify the files and line ranges
+# that were changed in that commit range, filtering check-format.pl output
+# only to lines that fall into the change ranges of the changed files.
+# examples:
+# check-format-commit.sh # check unstaged changes
+# check-format-commit.sh HEAD
+# check-format-commit.sh @~3..
+# check-format-commit.sh f5981c9629667a5a5d6
+# check-format-commit.sh f5981c9629667a5a5d6..ee0bf38e8709bf71888
+
+# Allowlist of files to scan
+# Currently this is any .c or .h file (with an optional .in suffix)
+FILE_NAME_END_ALLOWLIST=("\.[ch]\(.in\)\?")
# Global vars
# TEMPDIR is used to hold any files this script creates
# And is cleaned on EXIT with a trap function
TEMPDIR=$(mktemp -d /tmp/checkformat.XXXXXX)
# TOPDIR always points to the root of the git tree we are working in
# used to locate the check-format.pl script
TOPDIR=$(git rev-parse --show-toplevel)
# cleanup handler function, returns us to the root of the git tree
# and erases our temp directory
cleanup() {
rm -rf $TEMPDIR
cd $TOPDIR
}
trap cleanup EXIT
-# Get the canonical sha256 sum for the commit we are checking
+# Get the list of ids of the commits we are checking,
+# or empty for unstaged changes.
# This lets us pass in symbolic ref names like master/etc and
-# resolve them to sha256 sums easily
-COMMIT=$(git rev-parse $1)
+# resolve them to commit ids easily
+COMMIT_RANGE="$@"
+[ -n $COMMIT_RANGE ] && COMMIT_LAST=$(git rev-parse $COMMIT_RANGE)
-# Fail gracefully if git rev-parse doesn't produce a valid
-# commit
+# Fail gracefully if git rev-parse doesn't produce a valid commit
if [ $? -ne 0 ]
then
- echo "$1 is not a valid revision"
+ echo "$1 is not a valid commit range or commit id"
exit 1
fi
-# Create a iteratable list of files to check for a
-# given commit. It produces output of the format
-# <commit id> <file name> <change start line>, <change line count>
-touch $TEMPDIR/ranges.txt
-git show $COMMIT | awk -v mycmt=$COMMIT '
+# If the commit range is exactly one revision,
+# git rev-parse will output just the commit id of that one alone.
+# In that case, we must manipulate a little to get a desirable result,
+# as 'git diff' has a slightly different interpretation of a single commit id:
+# it takes that to mean all commits up to HEAD, plus any unstaged changes.
+if [ $(echo -n "$COMMIT_LAST" | wc -w) -ne 1 ]; then
+ COMMIT_LAST=$(echo "$COMMIT_LAST" | head -1)
+else
+ # $COMMIT_RANGE is just one commit, make it an actual range
+ COMMIT_RANGE=$COMMIT_RANGE^..$COMMIT_RANGE
+fi
+
+# Create an iterable list of files to check formatting on,
+# including the line ranges that are changed by the commits
+# It produces output of this format:
+# <file name> <change start line>, <change line count>
+git diff -U0 $COMMIT_RANGE | awk '
BEGIN {myfile=""}
- /+{3}/ {
- gsub(/b\//,"",$2);
- myfile=$2
- }
- /@@/ {
- gsub(/+/,"",$3);
- printf mycmt " " myfile " " $3 "\n"
- }' >> $TEMPDIR/ranges.txt || true
-
-# filter out anything that matches on a filter regex
-for i in ${EXCLUDED_FILE_REGEX[@]}
-do
- touch $TEMPDIR/ranges.filter
- grep -v "$i" $TEMPDIR/ranges.txt >> $TEMPDIR/ranges.filter || true
- REMAINING_FILES=$(wc -l $TEMPDIR/ranges.filter | awk '{print $1}')
- if [ $REMAINING_FILES -eq 0 ]
- then
- echo "This commit has no files that require checking"
- exit 0
- fi
- mv $TEMPDIR/ranges.filter $TEMPDIR/ranges.txt
-done
+ /^\+\+\+/ { sub(/^b./,"",$2); file=$2 }
+ /^@@/ { sub(/^\+/,"",$3); range=$3; printf file " " range "\n" }
+ ' > $TEMPDIR/ranges.txt
-# check out the files from the commit level.
-# For each file name in ranges, we show that file at the commit
-# level we are checking, and redirect it to the same path, relative
-# to $TEMPDIR/check-format. This give us the full file to run
-# check-format.pl on with line numbers matching the ranges in the
-# $TEMPDIR/ranges.txt file
-for j in $(grep $COMMIT $TEMPDIR/ranges.txt | awk '{print $2}')
+# filter in anything that matches on a filter regex
+for i in ${FILE_NAME_END_ALLOWLIST[@]}
do
- FDIR=$(dirname $j)
- mkdir -p $TEMPDIR/check-format/$FDIR
- git show $COMMIT:$j > $TEMPDIR/check-format/$j
+ # Note the space after the $i below. This is done because we want
+ # to match on file name suffixes, but the input file is of the form
+ # <commit> <file path> <range start>, <range length>
+ # So we can't just match on end of line. The additional space
+ # here lets us match on suffixes followed by the expected space
+ # in the input file
+ grep "$i " $TEMPDIR/ranges.txt >> $TEMPDIR/ranges.filter || true
done
-# Now for each file in $TEMPDIR/check-format run check-format.pl
-# Note that we use the %P formatter in the find utilty. This strips
-# off the $TEMPDIR/check-format path prefix, leaving $j with the
-# path to the file relative to the root of the source dir, so that
-# output from check-format.pl looks correct, relative to the root
-# of the git tree.
-for j in $(find $TEMPDIR/check-format -type f -printf "%P\n")
+REMAINING_FILES=$(wc -l <$TEMPDIR/ranges.filter)
+if [ $REMAINING_FILES -eq 0 ]
+then
+ echo "The given commit range has no C source file changes that require checking"
+ exit 0
+fi
+
+# unless checking the format of unstaged changes,
+# check out the files from the commit range.
+if [ -n "$COMMIT_RANGE" ]
+then
+ # For each file name in ranges, we show that file at the commit range
+ # we are checking, and redirect it to the same path,
+ # relative to $TEMPDIR/check-format.
+ # This give us the full file path to run check-format.pl on
+ # with line numbers matching the ranges in the $TEMPDIR/ranges.filter file
+ for j in $(awk '{print $1}' $TEMPDIR/ranges.filter | sort -u)
+ do
+ FDIR=$(dirname $j)
+ mkdir -p $TEMPDIR/check-format/$FDIR
+ git show $COMMIT_LAST:$j > $TEMPDIR/check-format/$j
+ done
+fi
+
+# Now for each file in $TEMPDIR/ranges.filter, run check-format.pl
+for j in $(awk '{print $1}' $TEMPDIR/ranges.filter | sort -u)
do
range_start=()
range_end=()
# Get the ranges for this file. Create 2 arrays. range_start contains
# the start lines for valid ranges from the commit. the range_end array
- # contains the corresponding end line (note, since diff output gives us
+ # contains the corresponding end line. Note, since diff output gives us
# a line count for a change, the range_end[k] entry is actually
# range_start[k]+line count
- for k in $(grep $COMMIT $TEMPDIR/ranges.txt | grep $j | awk '{print $3}')
+ for k in $(grep ^$j $TEMPDIR/ranges.filter | awk '{print $2}')
do
- RANGE=$k
- RSTART=$(echo $RANGE | awk -F',' '{print $1}')
- RLEN=$(echo $RANGE | awk -F',' '{print $2}')
+ RSTART=$(echo $k | awk -F',' '{print $1}')
+ RLEN=$(echo $k | awk -F',' '{print $2}')
+ # when the hunk is just one line, its length is implied
+ if [ -z "$RLEN" ]; then RLEN=1; fi
let REND=$RSTART+$RLEN
range_start+=($RSTART)
range_end+=($REND)
done
- # Go to our checked out tree
- cd $TEMPDIR/check-format
+ # Go to our checked out tree, unless checking unstaged changes
+ [ -n "$COMMIT_RANGE" ] && cd $TEMPDIR/check-format
# Actually run check-format.pl on the file, capturing the output
- # in a temporary file. Note the format of check-patch.pl output is
- # <file name>:<line number>:<error text>:<offending line contents>
- $TOPDIR/util/check-format.pl $j > $TEMPDIR/format-results.txt
+ # in a temporary file. Note the format of check-format.pl output is
+ # <file path>:<line number>:<error text>:<offending line contents>
+ $TOPDIR/util/check-format.pl $j > $TEMPDIR/results.txt
# Now we filter the check-format.pl output based on the changed lines
# captured in the range_start/end arrays
let maxidx=${#range_start[@]}-1
for k in $(seq 0 1 $maxidx)
do
RSTART=${range_start[$k]}
REND=${range_end[$k]}
# field 2 of check-format.pl output is the offending line number
# Check here if any line in that output falls between any of the
# start/end ranges defined in the range_start/range_end array.
# If it does fall in that range, print the entire line to stdout
- # If anything is printed, have awk exit with a non-zero exit code
awk -v rstart=$RSTART -v rend=$REND -F':' '
- BEGIN {rc=0}
- /:/ {
- if (($2 >= rstart) && ($2 <= rend)) {
- print $0;
- rc=1
- }
- }
- END {exit rc;}
- ' $TEMPDIR/format-results.txt
-
- # If awk exited with a non-zero code, this script will also exit
- # with a non-zero code
- if [ $? -ne 0 ]
- then
- EXIT_CODE=1
- fi
+ /:/ { if (rstart <= $2 && $2 <= rend) print $0 }
+ ' $TEMPDIR/results.txt >>$TEMPDIR/results-filtered.txt
done
done
+cat $TEMPDIR/results-filtered.txt
-# Exit with the recorded exit code above
-exit $EXIT_CODE
+# If any findings were in range, exit with a different error code
+if [ -s $TEMPDIR/results-filtered.txt ]
+then
+ exit 2
+fi
diff --git a/crypto/openssl/util/check-format.pl b/crypto/openssl/util/check-format.pl
index ef2c1920e722..559b9023d08c 100755
--- a/crypto/openssl/util/check-format.pl
+++ b/crypto/openssl/util/check-format.pl
@@ -1,1275 +1,1275 @@
#! /usr/bin/env perl
#
# Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
# Copyright Siemens AG 2019-2022
#
# Licensed under the Apache License 2.0 (the "License").
# You may not 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
#
# check-format.pl
# - check formatting of C source according to OpenSSL coding style
#
# usage:
# check-format.pl [-l|--sloppy-len] [-l|--sloppy-bodylen]
# [-s|--sloppy-space] [-c|--sloppy-comment]
# [-m|--sloppy-macro] [-h|--sloppy-hang]
# [-e|--eol-comment] [-1|--1-stmt]
# <files>
#
# run self-tests:
# util/check-format.pl util/check-format-test-positives.c
# util/check-format.pl util/check-format-test-negatives.c
#
# checks adherence to the formatting rules of the OpenSSL coding guidelines
# assuming that the input files contain syntactically correct C code.
# This pragmatic tool is incomplete and yields some false positives.
# Still it should be useful for detecting most typical glitches.
#
# options:
# -l | --sloppy-len increase accepted max line length from 80 to 84
# -l | --sloppy-bodylen do not report function body length > 200
# -s | --sloppy-space do not report whitespace nits
# -c | --sloppy-comment do not report indentation of comments
# Otherwise for each multi-line comment the indentation of
# its lines is checked for consistency. For each comment
# that does not begin to the right of normal code its
# indentation must be as for normal code, while in case it
# also has no normal code to its right it is considered to
# refer to the following line and may be indented equally.
# -m | --sloppy-macro allow missing extra indentation of macro bodies
# -h | --sloppy-hang when checking hanging indentation, do not report
# * same indentation as on line before
# * same indentation as non-hanging indent level
# * indentation moved left (not beyond non-hanging indent)
# just to fit contents within the line length limit
# -e | --eol-comment report needless intermediate multiple consecutive spaces also before end-of-line comments
# -1 | --1-stmt do more aggressive checks for { 1 stmt } - see below
#
# There are non-trivial false positives and negatives such as the following.
#
# * When a line contains several issues of the same kind only one is reported.
#
# * When a line contains more than one statement this is (correctly) reported
# but in some situations the indentation checks for subsequent lines go wrong.
#
# * There is the special OpenSSL rule not to unnecessarily use braces around
# single statements:
# {
# stmt;
# }
# except within if ... else constructs where some branch contains more than one
# statement. Since the exception is hard to recognize when such branches occur
# after the current position (such that false positives would be reported)
# the tool by checks for this rule by default only for do/while/for bodies.
# Yet with the --1-stmt option false positives are preferred over negatives.
# False negatives occur if the braces are more than two non-blank lines apart.
#
# * The presence of multiple consecutive spaces is regarded a coding style nit
# except when this is before end-of-line comments (unless the --eol-comment is given) and
# except when done in order to align certain columns over multiple lines, e.g.:
# # define AB 1
# # define CDE 22
# # define F 3333
# This pattern is recognized - and consequently extra space not reported -
# for a given line if in the non-blank line before or after (if existing)
# for each occurrence of " \S" (where \S means non-space) in the given line
# there is " \S" in the other line in the respective column position.
# This may lead to both false negatives (in case of coincidental " \S")
# and false positives (in case of more complex multi-column alignment).
#
# * When just part of control structures depend on #if(n)(def), which can be
# considered bad programming style, indentation false positives occur, e.g.:
# #if X
# if (1) /* bad style */
# #else
# if (2) /* bad style resulting in false positive */
# #endif
# c; /* resulting further false positive */
use strict;
# use List::Util qw[min max];
use POSIX;
use constant INDENT_LEVEL => 4;
use constant MAX_LINE_LENGTH => 80;
use constant MAX_BODY_LENGTH => 200;
# global variables @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# command-line options
my $max_length = MAX_LINE_LENGTH;
my $sloppy_bodylen = 0;
my $sloppy_SPC = 0;
my $sloppy_hang = 0;
my $sloppy_cmt = 0;
my $sloppy_macro = 0;
my $eol_cmt = 0;
my $extended_1_stmt = 0;
while ($ARGV[0] =~ m/^-(\w|-[\w\-]+)$/) {
my $arg = $1; shift;
if ($arg =~ m/^(l|-sloppy-len)$/) {
$max_length += INDENT_LEVEL;
} elsif ($arg =~ m/^(b|-sloppy-bodylen)$/) {
$sloppy_bodylen = 1;
} elsif ($arg =~ m/^(s|-sloppy-space)$/) {
$sloppy_SPC= 1;
} elsif ($arg =~ m/^(c|-sloppy-comment)$/) {
$sloppy_cmt = 1;
} elsif ($arg =~ m/^(m|-sloppy-macro)$/) {
$sloppy_macro = 1;
} elsif ($arg =~ m/^(h|-sloppy-hang)$/) {
$sloppy_hang = 1;
} elsif ($arg =~ m/^(e|-eol-comment)$/) {
$eol_cmt = 1;
} elsif ($arg =~ m/^(1|-1-stmt)$/) {
$extended_1_stmt = 1;
} else {
die("unknown option: -$arg");
}
}
# state variables
my $self_test; # whether the current input file is regarded to contain (positive/negative) self-tests
my $in_comment; # number of lines so far within multi-line comment, 0 if no comment, < 0 when end is on current line
my $leading_comment; # multi-line comment has no code before its beginning delimiter, if $in_comment != 0
my $formatted_comment; # multi-line comment beginning with "/*-", which indicates/allows special formatting, if $in_comment != 0
my $comment_indent; # comment indent, if $in_comment != 0
my $ifdef__cplusplus; # line before contained '#ifdef __cplusplus' (used in header files)
my $preproc_if_nesting; # currently required indentation of preprocessor directive according to #if(n)(def)
my $in_preproc; # 0 or number of lines so far within preprocessor directive, e.g., macro definition
my $preproc_directive; # name of current preprocessor directive, if $in_preproc != 0
my $preproc_offset; # offset to $block_indent within multi-line preprocessor directive, else 0
my $in_macro_header; # number of open parentheses + 1 in (multi-line) header of #define, if $in_preproc != 0
my $line; # current line number
my $line_before; # number of previous not essentially blank line (containing at most whitespace and '\')
my $line_before2; # number of not essentially blank line before previous not essentially blank line
# indentation state
my $contents; # contents of current line (without blinding)
# $_ # current line, where comments etc. get blinded
my $code_contents_before; # contents of previous non-comment non-preprocessor-directive line (without blinding), initially ""
my $contents_before; # contents of $line_before (without blinding), if $line_before > 0
my $contents_before_; # contents of $line_before after blinding comments etc., if $line_before > 0
my $contents_before2; # contents of $line_before2 (without blinding), if $line_before2 > 0
my $contents_before_2; # contents of $line_before2 after blinding comments etc., if $line_before2 > 0
my $in_multiline_string; # line starts within multi-line string literal
my $count; # -1 or number of leading whitespace characters (except newline) in current line,
# which should be $block_indent + $hanging_offset + $local_offset or $expr_indent
my $count_before; # number of leading whitespace characters (except line ending chars) in $contents_before
my $has_label; # current line contains label
my $local_offset; # current extra indent due to label, switch case/default, or leading closing brace(s)
my $line_body_start; # number of line where last function body started, or 0
my $line_function_start; # number of line where last function definition started, used for $line_body_start
my $last_function_header; # header containing name of last function defined, used if $line_body_start != 0
my $line_opening_brace; # number of previous line with opening brace after if/do/while/for, optionally for 'else'
my $keyword_opening_brace; # name of previous keyword, used if $line_opening_brace != 0
my $block_indent; # currently required normal indentation at block/statement level
my $hanging_offset; # extra indent, which may be nested, for just one hanging statement or expr or typedef
my @in_do_hanging_offsets; # stack of hanging offsets for nested 'do' ... 'while'
my @in_if_hanging_offsets; # stack of hanging offsets for nested 'if' (but not its potential 'else' branch)
my $if_maybe_terminated; # 'if' ends and $hanging_offset should be reset unless the next line starts with 'else'
my @nested_block_indents; # stack of indentations at block/statement level, needed due to hanging statements
my @nested_hanging_offsets;# stack of nested $hanging_offset values, in parallel to @nested_block_indents
my @nested_in_typedecl; # stack of nested $in_typedecl values, partly in parallel to @nested_block_indents
my @nested_indents; # stack of hanging indents due to parentheses, braces, brackets, or conditionals
my @nested_symbols; # stack of hanging symbols '(', '{', '[', or '?', in parallel to @nested_indents
my @nested_conds_indents; # stack of hanging indents due to conditionals ('?' ... ':')
my $expr_indent; # resulting hanging indent within (multi-line) expressions including type exprs, else 0
my $hanging_symbol; # character ('(', '{', '[', not: '?') responsible for $expr_indent, if $expr_indent != 0
my $in_block_decls; # number of local declaration lines after block opening before normal statements, or -1 if no block opening
my $in_expr; # in expression after if/while/for/switch/return/enum/LHS of assignment
my $in_paren_expr; # in parenthesized if/while/for condition and switch expression, if $expr_indent != 0
my $in_typedecl; # nesting level of typedef/struct/union/enum
my $num_reports_line = 0; # number of issues found on current line
my $num_reports = 0; # total number of issues found
my $num_indent_reports = 0;# total number of indentation issues found
my $num_nesting_issues = 0;# total number of preprocessor #if nesting issues found
my $num_syntax_issues = 0; # total number of syntax issues found during sanity checks
my $num_SPC_reports = 0; # total number of whitespace issues found
my $num_length_reports = 0;# total number of line length issues found
sub reset_file_state {
$in_comment = 0;
$ifdef__cplusplus = 0;
$preproc_if_nesting = 0;
$in_preproc = 0;
$line = 0;
$line_before = 0;
$line_before2 = 0;
reset_indentation_state();
}
sub reset_indentation_state {
$code_contents_before = "";
@nested_block_indents = ();
@nested_hanging_offsets = ();
@nested_in_typedecl = ();
@nested_symbols = ();
@nested_indents = ();
@nested_conds_indents = ();
$expr_indent = 0;
$in_block_decls = -1;
$in_expr = 0;
$in_paren_expr = 0;
$hanging_offset = 0;
@in_do_hanging_offsets = ();
@in_if_hanging_offsets = ();
$if_maybe_terminated = 0;
$block_indent = 0;
$in_multiline_string = 0;
$line_body_start = 0;
$line_opening_brace = 0;
$in_typedecl = 0;
}
my $bak_line_before;
my $bak_line_before2;
my $bak_code_contents_before;
my @bak_nested_block_indents;
my @bak_nested_hanging_offsets;
my @bak_nested_in_typedecl;
my @bak_nested_symbols;
my @bak_nested_indents;
my @bak_nested_conds_indents;
my $bak_expr_indent;
my $bak_in_block_decls;
my $bak_in_expr;
my $bak_in_paren_expr;
my $bak_hanging_offset;
my @bak_in_do_hanging_offsets;
my @bak_in_if_hanging_offsets;
my $bak_if_maybe_terminated;
my $bak_block_indent;
my $bak_in_multiline_string;
my $bak_line_body_start;
my $bak_line_opening_brace;
my $bak_in_typedecl;
sub backup_indentation_state {
$bak_code_contents_before = $code_contents_before;
@bak_nested_block_indents = @nested_block_indents;
@bak_nested_hanging_offsets = @nested_hanging_offsets;
@bak_nested_in_typedecl = @nested_in_typedecl;
@bak_nested_symbols = @nested_symbols;
@bak_nested_indents = @nested_indents;
@bak_nested_conds_indents = @nested_conds_indents;
$bak_expr_indent = $expr_indent;
$bak_in_block_decls = $in_block_decls;
$bak_in_expr = $in_expr;
$bak_in_paren_expr = $in_paren_expr;
$bak_hanging_offset = $hanging_offset;
@bak_in_do_hanging_offsets = @in_do_hanging_offsets;
@bak_in_if_hanging_offsets = @in_if_hanging_offsets;
$bak_if_maybe_terminated = $if_maybe_terminated;
$bak_block_indent = $block_indent;
$bak_in_multiline_string = $in_multiline_string;
$bak_line_body_start = $line_body_start;
$bak_line_opening_brace = $line_opening_brace;
$bak_in_typedecl = $in_typedecl;
}
sub restore_indentation_state {
$code_contents_before = $bak_code_contents_before;
@nested_block_indents = @bak_nested_block_indents;
@nested_hanging_offsets = @bak_nested_hanging_offsets;
@nested_in_typedecl = @bak_nested_in_typedecl;
@nested_symbols = @bak_nested_symbols;
@nested_indents = @bak_nested_indents;
@nested_conds_indents = @bak_nested_conds_indents;
$expr_indent = $bak_expr_indent;
$in_block_decls = $bak_in_block_decls;
$in_expr = $bak_in_expr;
$in_paren_expr = $bak_in_paren_expr;
$hanging_offset = $bak_hanging_offset;
@in_do_hanging_offsets = @bak_in_do_hanging_offsets;
@in_if_hanging_offsets = @bak_in_if_hanging_offsets;
$if_maybe_terminated = $bak_if_maybe_terminated;
$block_indent = $bak_block_indent;
$in_multiline_string = $bak_in_multiline_string;
$line_body_start = $bak_line_body_start;
$line_opening_brace = $bak_line_opening_brace;
$in_typedecl = $bak_in_typedecl;
}
# auxiliary submodules @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
sub report_flexibly {
my $line = shift;
my $msg = shift;
my $contents = shift;
my $report_SPC = $msg =~ /space|blank/;
return if $report_SPC && $sloppy_SPC;
print "$ARGV:$line:$msg:$contents" unless $self_test;
$num_reports_line++;
$num_reports++;
$num_indent_reports++ if $msg =~ m/:indent /;
$num_nesting_issues++ if $msg =~ m/ nesting indent /;
$num_syntax_issues++ if $msg =~ m/unclosed|unexpected/;
$num_SPC_reports++ if $report_SPC;
$num_length_reports++ if $msg =~ m/length/;
}
sub report {
my $msg = shift;
report_flexibly($line, $msg, $contents);
}
sub parens_balance { # count balance of opening parentheses - closing parentheses
my $str = shift;
return $str =~ tr/\(// - $str =~ tr/\)//;
}
sub blind_nonspace { # blind non-space text of comment as @, preserving length and spaces
# the @ character is used because it cannot occur in normal program code so there is no confusion
# comment text is not blinded to whitespace in order to be able to check extra SPC also in comments
my $comment_text = shift;
$comment_text =~ s/([\.\?\!])\s\s/$1. /g; # in extra SPC checks allow one extra SPC after period '.', '?', or '!' in comments
return $comment_text =~ tr/ /@/cr;
}
# submodule for indentation checking/reporting @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
sub check_indent { # used for lines outside multi-line string literals
my $stmt_indent = $block_indent + $hanging_offset + $local_offset;
# print "DEBUG: expr_indent $expr_indent; stmt_indent $stmt_indent = block_indent $block_indent + hanging_offset $hanging_offset + local_offset $local_offset\n";
$stmt_indent = 0 if $stmt_indent < 0; # TODO maybe give warning/error
my $stmt_desc = $contents =~
m/^\s*\/\*/ ? "intra-line comment" :
$has_label ? "label" :
($hanging_offset != 0 ? "hanging " : "").
($hanging_offset != 0 ? "stmt/expr" : "stmt/decl"); # $in_typedecl is not fully to the point here
my ($ref_desc, $ref_indent) = $expr_indent == 0 ? ($stmt_desc, $stmt_indent)
: ("hanging '$hanging_symbol'", $expr_indent);
my ($alt_desc, $alt_indent) = ("", $ref_indent);
# allow indent 1 for labels - this cannot happen for leading ':'
($alt_desc, $alt_indent) = ("outermost position", 1) if $expr_indent == 0 && $has_label;
if (@nested_conds_indents != 0 && substr($_, $count, 1) eq ":") {
# leading ':' within stmt/expr/decl - this cannot happen for labels, leading '&&', or leading '||'
# allow special indent at level of corresponding "?"
($alt_desc, $alt_indent) = ("leading ':'", @nested_conds_indents[-1]);
}
# allow extra indent offset leading '&&' or '||' - this cannot happen for leading ":"
($alt_desc, $alt_indent) = ("leading '$1'", $ref_indent + INDENT_LEVEL) if $contents =~ m/^[\s@]*(\&\&|\|\|)/;
if ($expr_indent < 0) { # implies @nested_symbols != 0 && @nested_symbols[0] eq "{" && @nested_indents[-1] < 0
# allow normal stmt indentation level for hanging initializer/enum expressions after trailing '{'
# this cannot happen for labels and overrides special treatment of ':', '&&' and '||' for this line
($alt_desc, $alt_indent) = ("lines after '{'", $stmt_indent);
# decide depending on current actual indentation, preventing forth and back
@nested_indents[-1] = $count == $stmt_indent ? $stmt_indent : -@nested_indents[-1]; # allow $stmt_indent
$ref_indent = $expr_indent = @nested_indents[-1];
}
# check consistency of indentation within multi-line comment (i.e., between its first, inner, and last lines)
if ($in_comment != 0 && $in_comment != 1) { # in multi-line comment but not on its first line
if (!$sloppy_cmt) {
if ($in_comment > 0) { # not at its end
report("indent = $count != $comment_indent within multi-line comment")
if $count != $comment_indent;
} else {
my $tweak = $in_comment == -2 ? 1 : 0;
report("indent = ".($count + $tweak)." != $comment_indent at end of multi-line comment")
if $count + $tweak != $comment_indent;
}
}
# do not check indentation of last line of non-leading multi-line comment
if ($in_comment < 0 && !$leading_comment) {
s/^(\s*)@/$1*/; # blind first '@' as '*' to prevent below delayed check for the line before
return;
}
return if $in_comment > 0; # not on its last line
# $comment_indent will be checked by the below checks for end of multi-line comment
}
# else check indentation of entire-line comment or entire-line end of multi-line comment
# ... w.r.t. indent of the following line by delayed check for the line before
if (($in_comment == 0 || $in_comment == 1) # no comment, intra-line comment, or begin of multi-line comment
&& $line_before > 0 # there is a line before
&& $contents_before_ =~ m/^(\s*)@[\s@]*$/) { # line before begins with '@', no code follows (except '\')
report_flexibly($line_before, "entire-line comment indent = $count_before != $count (of following line)",
$contents_before) if !$sloppy_cmt && $count_before != -1 && $count_before != $count;
}
# ... but allow normal indentation for the current line, else above check will be done for the line before
if (($in_comment == 0 || $in_comment < 0) # (no comment,) intra-line comment or end of multi-line comment
&& m/^(\s*)@[\s@]*$/) { # line begins with '@', no code follows (except '\')
if ($count == $ref_indent) { # indentation is like for (normal) code in this line
s/^(\s*)@/$1*/; # blind first '@' as '*' to prevent above delayed check for the line before
return;
}
return if !eof; # defer check of entire-line comment to next line
}
# else check indentation of leading intra-line comment or end of multi-line comment
if (m/^(\s*)@/) { # line begins with '@', i.e., any (remaining type of) comment
if (!$sloppy_cmt && $count != $ref_indent) {
report("intra-line comment indent = $count != $ref_indent") if $in_comment == 0;
report("multi-line comment indent = $count != $ref_indent") if $in_comment < 0;
}
return;
}
if ($sloppy_hang && ($hanging_offset != 0 || $expr_indent != 0)) {
# do not report same indentation as on the line before (potentially due to same violations)
return if $line_before > 0 && $count == $count_before;
# do not report indentation at normal indentation level while hanging expression indent would be required
return if $expr_indent != 0 && $count == $stmt_indent;
# do not report if contents have been shifted left of nested expr indent (but not as far as stmt indent)
# apparently aligned to the right in order to fit within line length limit
return if $stmt_indent < $count && $count < $expr_indent &&
length($contents) == MAX_LINE_LENGTH + length("\n");
}
report("indent = $count != $ref_indent for $ref_desc".
($alt_desc eq ""
|| $alt_indent == $ref_indent # prevent showing alternative that happens to have equal value
? "" : " or $alt_indent for $alt_desc"))
if $count != $ref_indent && $count != $alt_indent;
}
# submodules handling indentation within expressions @@@@@@@@@@@@@@@@@@@@@@@@@@@
sub update_nested_indents { # may reset $in_paren_expr and in this case also resets $in_expr
my $str = shift;
my $start = shift; # defaults to 0
my $terminator_position = -1;
for (my $i = $start; $i < length($str); $i++) {
my $c;
my $curr = substr($str, $i);
if ($curr =~ m/^(.*?)([{}()?:;\[\]])(.*)$/) { # match from position $i the first {}()?:;[]
$c = $2;
} else {
last;
}
my ($head, $tail) = (substr($str, 0, $i).$1, $3);
$i += length($1) + length($2) - 1;
# stop at terminator outside 'for (..;..;..)', assuming that 'for' is followed by '('
return $i if $c eq ";" && (!$in_paren_expr || @nested_indents == 0);
my $in_stmt = $in_expr || @nested_symbols != 0; # not: || $in_typedecl != 0
if ($c =~ m/[{([?]/) { # $c is '{', '(', '[', or '?'
if ($c eq "{") { # '{' in any context
$in_block_decls = 0 if !$in_expr && $in_typedecl == 0;
# cancel newly hanging_offset if opening brace '{' is after non-whitespace non-comment:
$hanging_offset -= INDENT_LEVEL if $hanging_offset > 0 && $head =~ m/[^\s\@]/;
push @nested_block_indents, $block_indent;
push @nested_hanging_offsets, $in_expr ? $hanging_offset : 0;
push @nested_in_typedecl, $in_typedecl if $in_typedecl != 0;
$block_indent += INDENT_LEVEL + $hanging_offset;
$hanging_offset = 0;
}
if ($c ne "{" || $in_stmt) { # for '{' inside stmt/expr (not: decl), for '(', '[', or '?' anywhere
$tail =~ m/^([\s@]*)([^\s\@])/;
push @nested_indents, defined $2
? $i + 1 + length($1) # actual indentation of following non-space non-comment
: $c ne "{" ? +($i + 1) # just after '(' or '[' if only whitespace thereafter
: -($i + 1); # allow also $stmt_indent if '{' with only whitespace thereafter
push @nested_symbols, $c; # done also for '?' to be able to check correct nesting
push @nested_conds_indents, $i if $c eq "?"; # remember special alternative indent for ':'
}
} elsif ($c =~ m/[})\]:]/) { # $c is '}', ')', ']', or ':'
my $opening_c = ($c =~ tr/})]:/{([/r);
if (($c ne ":" || $in_stmt # ignore ':' outside stmt/expr/decl
# in the presence of ':', one could add this sanity check:
# && !(# ':' after initial label/case/default
# $head =~ m/^([\s@]*)(case\W.*$|\w+$)/ || # this matching would not work for
# # multi-line expr after 'case'
# # bitfield length within unsigned type decl
# $tail =~ m/^[\s@]*\d+/ # this matching would need improvement
# )
)) {
if ($c ne "}" || $in_stmt) { # for '}' inside stmt/expr/decl, ')', ']', or ':'
if (@nested_symbols != 0 &&
@nested_symbols[-1] == $opening_c) { # for $c there was a corresponding $opening_c
pop @nested_indents;
pop @nested_symbols;
pop @nested_conds_indents if $opening_c eq "?";
} else {
report("unexpected '$c' @ ".($in_paren_expr ? "(expr)" : "expr"));
next;
}
}
if ($c eq "}") { # '}' at block level but also inside stmt/expr/decl
if (@nested_block_indents == 0) {
report("unexpected '}'");
} else {
$block_indent = pop @nested_block_indents;
$hanging_offset = pop @nested_hanging_offsets;
$in_typedecl = pop @nested_in_typedecl if @nested_in_typedecl != 0;
}
}
if ($in_paren_expr && !grep(/\(/, @nested_symbols)) { # end of (expr)
check_nested_nonblock_indents("(expr)");
$in_paren_expr = $in_expr = 0;
report("code after (expr)")
if $tail =~ m/^([^{]*)/ && $1 =~ m/[^\s\@;]/; # non-space non-';' before any '{'
}
}
}
}
return -1;
}
sub check_nested_nonblock_indents {
my $position = shift;
while (@nested_symbols != 0) {
my $symbol = pop @nested_symbols;
report("unclosed '$symbol' in $position");
if ($symbol eq "{") { # repair stack of blocks
$block_indent = pop @nested_block_indents;
$hanging_offset = pop @nested_hanging_offsets;
$in_typedecl = pop @nested_in_typedecl if @nested_in_typedecl != 0;
}
}
@nested_indents = ();
@nested_conds_indents = ();
}
# start of main program @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
reset_file_state();
while (<>) { # loop over all lines of all input files
$self_test = $ARGV =~ m/check-format-test/;
$_ = "" if $self_test && m/ blank line within local decls /;
$line++;
s/\r$//; # strip any trailing CR '\r' (which are typical on Windows systems)
$contents = $_;
# check for illegal characters
if (m/(.*?)([\x00-\x09\x0B-\x1F\x7F-\xFF])/) {
my $col = length($1);
report(($2 eq "\x09" ? "TAB" : $2 eq "\x0D" ? "CR " : $2 =~ m/[\x00-\x1F]/ ? "non-printable"
: "non-7bit char") . " at column $col") ;
}
# check for whitespace at EOL
report("trailing whitespace at EOL") if m/\s\n$/;
# assign to $count the actual indentation level of the current line
chomp; # remove trailing NL '\n'
m/^(\s*)/;
$count = length($1); # actual indentation
$has_label = 0;
$local_offset = 0;
# character/string literals @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
s/\\["']/@@/g; # blind all '"' and "'" escaped by '\' (typically within character literals or string literals)
# handle multi-line string literals to avoid confusion on starting/ending '"' and trailing '\'
if ($in_multiline_string) {
if (s#^([^"]*)"#($1 =~ tr/"/@/cr).'@'#e) { # string literal terminated by '"'
# string contents and its terminating '"' have been blinded as '@'
$count = -1; # do not check indentation
} else {
report("multi-line string literal not terminated by '\"' and trailing '\' is missing")
unless s#^([^\\]*)\s*\\\s*$#$1#; # strip trailing '\' plus any whitespace around
goto LINE_FINISHED;
}
}
# blind contents of character and string literals as @, preserving length (but not spaces)
# this prevents confusing any of the matching below, e.g., of whitespace and comment delimiters
s#('[^']*')#$1 =~ tr/'/@/cr#eg; # handle all intra-line character literals
s#("[^"]*")#$1 =~ tr/"/@/cr#eg; # handle all intra-line string literals
$in_multiline_string = # handle trailing string literal terminated by '\'
s#^(([^"]*"[^"]*")*[^"]*)("[^"]*)\\(\s*)$#$1.($3 =~ tr/"/@/cr).'"'.$4#e;
# its contents have been blinded and the trailing '\' replaced by '"'
# strip any other trailing '\' along with any whitespace around it such that it does not interfere with various matching below
my $trailing_backslash = s#^(.*?)\s*\\\s*$#$1#; # trailing '\' possibly preceded or followed by whitespace
my $essentially_blank_line = m/^\s*$/; # just whitespace and maybe a '\'
# comments @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# do/prepare checks within multi-line comments
my $self_test_exception = $self_test ? "@" : "";
if ($in_comment > 0) { # this still includes the last line of multi-line comment
my ($head, $any_symbol, $cmt_text) = m/^(\s*)(.?)(.*)$/;
if ($any_symbol eq "*") {
report("missing space or '*' after leading '*' in multi-line comment") if $cmt_text =~ m|^[^*\s/$self_test_exception]|;
} else {
report("missing leading '*' in multi-line comment");
}
$in_comment++;
}
# detect end of comment, must be within multi-line comment, check if it is preceded by non-whitespace text
if ((my ($head, $tail) = m|^(.*?)\*/(.*)$|) && $1 ne '/') { # ending comment: '*/'
report("missing space or '*' before '*/'") if $head =~ m/[^*\s]$/;
report("missing space (or ',', ';', ')', '}', ']') after '*/'") if $tail =~ m/^[^\s,;)}\]]/; # no space or ,;)}] after '*/'
if (!($head =~ m|/\*|)) { # not begin of comment '/*', which is is handled below
if ($in_comment == 0) {
report("unexpected '*/' outside comment");
$_ = "$head@@".$tail; # blind the "*/"
} else {
report("text before '*/' in multi-line comment") if ($head =~ m/[^*\s]/); # non-SPC before '*/'
$in_comment = -1; # indicate that multi-line comment ends on current line
if ($count > 0) {
# make indentation of end of multi-line comment appear like of leading intra-line comment
$head =~ s/^(\s*)\s/$1@/; # replace the last leading space by '@'
$count--;
$in_comment = -2; # indicate that multi-line comment ends on current line, with tweak
}
my $cmt_text = $head;
$_ = blind_nonspace($cmt_text)."@@".$tail;
}
}
}
# detect begin of comment, check if it is followed by non-space text
MATCH_COMMENT:
if (my ($head, $opt_minus, $tail) = m|^(.*?)/\*(-?)(.*)$|) { # begin of comment: '/*'
report("missing space before '/*'")
if $head =~ m/[^\s(\*]$/; # not space, '(', or or '*' (needed to allow '*/') before comment delimiter
report("missing space, '*', or '!' after '/*$opt_minus'") if $tail =~ m/^[^\s*!$self_test_exception]/;
my $cmt_text = $opt_minus.$tail; # preliminary
if ($in_comment > 0) {
report("unexpected '/*' inside multi-line comment");
} elsif ($tail =~ m|^(.*?)\*/(.*)$|) { # comment end: */ on same line
report("unexpected '/*' inside intra-line comment") if $1 =~ /\/\*/;
# blind comment text, preserving length and spaces
($cmt_text, my $rest) = ($opt_minus.$1, $2);
$_ = "$head@@".blind_nonspace($cmt_text)."@@".$rest;
goto MATCH_COMMENT;
} else { # begin of multi-line comment
my $self_test_exception = $self_test ? "(@\d?)?" : "";
report("text after '/*' in multi-line comment")
unless $tail =~ m/^$self_test_exception.?[*\s]*$/;
# tail not essentially blank, first char already checked
# adapt to actual indentation of first line
$comment_indent = length($head) + 1;
$_ = "$head@@".blind_nonspace($cmt_text);
$in_comment = 1;
$leading_comment = $head =~ m/^\s*$/; # there is code before beginning delimiter
$formatted_comment = $opt_minus eq "-";
}
} elsif (($head, $tail) = m|^\{-(.*)$|) { # begin of Perl pragma: '{-'
}
if ($in_comment > 1) { # still inside multi-line comment (not at its begin or end)
m/^(\s*)\*?(\s*)(.*)$/;
$_ = $1."@".$2.blind_nonspace($3);
}
# handle special case of line after '#ifdef __cplusplus' (which typically appears in header files)
if ($ifdef__cplusplus) {
$ifdef__cplusplus = 0;
$_ = "$1 $2" if $contents =~ m/^(\s*extern\s*"C"\s*)\{(\s*)$/; # ignore opening brace in 'extern "C" {'
goto LINE_FINISHED if m/^\s*\}\s*$/; # ignore closing brace '}'
}
# check for over-long lines,
# while allowing trailing (also multi-line) string literals to go past $max_length
my $len = length; # total line length (without trailing '\n')
if ($len > $max_length &&
!(m/^(.*)"[^"]*"\s*[\)\}\]]*[,;]?\s*$/ # string literal terminated by '"' (or '\'), then maybe )}],;
&& length($1) < $max_length)
# this allows over-long trailing string literals with beginning col before $max_length
) {
report("line length = $len > ".MAX_LINE_LENGTH);
}
# handle C++ / C99 - style end-of-line comments
if (my ($head, $cmt_text) = m|^(.*?)//(.*$)|) {
report("'//' end-of-line comment"); # the '//' comment style is not allowed for C90
# blind comment text, preserving length and spaces
$_ = "$head@@".blind_nonspace($cmt_text);
}
# at this point all non-space portions of any types of comments have been blinded as @
goto LINE_FINISHED if $essentially_blank_line;
# handle preprocessor directives @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
if (s/^(\s*#)(\s*)(\w+)//) { # line beginning with '#' and directive name;
# blank these portions to prevent confusion with C-level 'if', 'else', etc.
my ($lead, $space) = ($1, $2);
$preproc_directive = $3;
$_ = "$lead$space$preproc_directive$_" if $preproc_directive =~ m/^(define|include)$/; # yet do not blank #define or #include to prevent confusing the indentation or whitespace checks, resp.
$_ = blind_nonspace($_) if $preproc_directive eq "error"; # blind error message
if ($in_preproc != 0) {
report("preprocessor directive within multi-line directive");
reset_indentation_state();
}
$in_preproc++;
report("indent = $count != 0 for '#'") if $count != 0;
report("'#$preproc_directive' with constant condition")
if $preproc_directive =~ m/^(if|elif)$/ && m/^[\W0-9]+$/ && !$trailing_backslash;
$preproc_if_nesting-- if $preproc_directive =~ m/^(else|elif|endif)$/;
if ($preproc_if_nesting < 0) {
$preproc_if_nesting = 0;
report("unexpected '#$preproc_directive' according to '#if' nesting");
}
my $space_count = length($space); # maybe could also use indentation before '#'
report("'#if' nesting indent = $space_count != $preproc_if_nesting") if $space_count != $preproc_if_nesting;
$preproc_if_nesting++ if $preproc_directive =~ m/^(if|ifdef|ifndef|else|elif)$/;
$ifdef__cplusplus = $preproc_directive eq "ifdef" && m/\s+__cplusplus\s*$/;
# handle indentation of preprocessor directive independently of surrounding normal code
$count = -1; # do not check indentation of first line of preprocessor directive
backup_indentation_state();
reset_indentation_state();
}
# intra-line whitespace nits @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
my $in_multiline_comment = ($in_comment > 1 || $in_comment < 0); # $in_multiline_comment refers to line before
if (!$sloppy_SPC && !($in_multiline_comment && $formatted_comment)) {
sub extra_SPC {
my $intra_line = shift;
return "extra space".($intra_line =~ m/@\s\s/ ?
$in_comment != 0 ? " in multi-line comment"
: " in intra-line comment" : "");
}
sub split_line_head { # split line contents into header containing leading spaces and the first non-space char, and the rest of the line
my $comment_symbol =
$in_comment != 0 ? "@" : ""; # '@' will match the blinded leading '*' in multi-line comment
# $in_comment may pertain to the following line due to delayed check
# do not check for extra SPC in leading spaces including any '#' (or '*' within multi-line comment)
shift =~ m/^(\s*([#$comment_symbol]\s*)?)(.*?)\s*$/;
return ($1, $3);
}
my ($head , $intra_line ) = split_line_head($_);
my ($head1, $intra_line1) = split_line_head($contents_before_ ) if $line_before > 0;
my ($head2, $intra_line2) = split_line_head($contents_before_2) if $line_before2 > 0;
if ($line_before > 0) { # check with one line delay, such that at least $contents_before is available
sub column_alignments_only { # return 1 if the given line has multiple consecutive spaces only at columns that match the reference line
# all parameter strings are assumed to contain contents after blinding comments etc.
my $head = shift; # leading spaces and the first non-space char
my $intra = shift; # the rest of the line contents
my $contents = shift; # reference line
# check if all extra SPC in $intra is used only for multi-line column alignment with $contents
my $offset = length($head);
for (my $col = 0; $col < length($intra) - 2; $col++) {
my $substr = substr($intra, $col);
next unless $substr =~ m/^\s\s\S/; # extra SPC (but not in leading spaces of the line)
next if !$eol_cmt && $substr =~ m/^[@\s]+$/; # end-of-line comment
return 0 unless substr($contents, $col + $offset + 1, 2) =~ m/\s\S/; # reference line contents do not match
}
return 1;
}
report_flexibly($line_before, extra_SPC($intra_line1), $contents_before) if $intra_line1 =~ m/\s\s\S/ &&
!( column_alignments_only($head1, $intra_line1, $_ ) # compare with $line
|| ($line_before2 > 0 &&
column_alignments_only($head1, $intra_line1, $contents_before_2))); # compare w/ $line_before2
report(extra_SPC($intra_line)) if $intra_line =~ m/\s\s\S/ && eof
&& ! column_alignments_only($head , $intra_line , $contents_before_ ) ; # compare w/ $line_before
} elsif (eof) { # special case: just one line exists
report(extra_SPC($intra_line)) if $intra_line =~ m/\s\s\S/;
}
# ignore paths in #include
$intra_line =~ s/^(include\s*)(".*?"|<.*?>)/$1/e if $head =~ m/#/;
report("missing space before '$2'")
if $intra_line =~ m/(\S)((<<|>>)=)/ # '<<=' or >>=' without preceding space
|| ($intra_line =~ m/(\S)([\+\-\*\/\/%\&\|\^\!<>=]=)/
&& "$1$2" ne "<<=" && "$1$2" ne ">>=") # other <op>= or (in)equality without preceding space
|| ($intra_line =~ m/(\S)=/
&& !($1 =~ m/[\+\-\*\/\/%\&\|\^\!<>=]/)
&& $intra_line =~ m/(\S)(=)/); # otherwise, '=' without preceding space
# treat op= and comparison operators as simple '=', simplifying matching below
$intra_line =~ s/(<<|>>|[\+\-\*\/\/%\&\|\^\!<>=])=/=/g;
# treat (type) variables within macro, indicated by trailing '\', as 'int' simplifying matching below
$intra_line =~ s/[A-Z_]+/int/g if $trailing_backslash;
# treat double &&, ||, <<, and >> as single ones, simplifying matching below
$intra_line =~ s/(&&|\|\||<<|>>)/substr($1, 0, 1)/eg;
# remove blinded comments etc. directly after [{(
while ($intra_line =~ s/([\[\{\(])@+\s?/$1/e) {} # /g does not work here
# remove blinded comments etc. directly before ,;)}]
while ($intra_line =~ s/\s?@+([,;\)\}\]])/$1/e) {} # /g does not work here
# treat remaining blinded comments and string literal contents as (single) space during matching below
$intra_line =~ s/@+/ /g; # note that extra SPC has already been handled above
$intra_line =~ s/\s+$//; # strip any (resulting) space at EOL
- # replace ';;' or '; ;' by ';' in "for(;;)" and in "for (...)" unless "..." contains just SPC and ';' characters:
+ # replace ';;' or '; ;' by ';' in "for (;;)" and in "for (...)" unless "..." contains just SPC and ';' characters:
$intra_line =~ s/((^|\W)for\s*\()([^;]*?)(\s*)(;\s?);(\s*)([^;]*)(\))/
"$1$3$4".("$3$4$5$6$7" eq ";" || $3 ne "" || $7 ne "" ? "" : $5).";$6$7$8"/eg;
# strip trailing ';' or '; ' in "for (...)" except in "for (;;)" or "for (;; )":
$intra_line =~ s/((^|\W)for\s*\()([^;]*(;[^;]*)?)(;\s?)(\))/
"$1$3".($3 eq ";" ? $5 : "")."$6"/eg;
$intra_line =~ s/(=\s*)\{ /"$1@ "/eg; # do not report {SPC in initializers such as ' = { 0, };'
$intra_line =~ s/, \};/, @;/g; # do not report SPC} in initializers such as ' = { 0, };'
report("space before '$1'") if $intra_line =~ m/[\w)\]]\s+(\+\+|--)/; # postfix ++/-- with preceding space
report("space after '$1'") if $intra_line =~ m/(\+\+|--)\s+[a-zA-Z_(]/; # prefix ++/-- with following space
$intra_line =~ s/\.\.\./@/g; # blind '...'
report("space before '$1'") if $intra_line =~ m/\s(\.|->)/; # '.' or '->' with preceding space
report("space after '$1'") if $intra_line =~ m/(\.|->)\s/; # '.' or '->' with following space
$intra_line =~ s/\-\>|\+\+|\-\-/@/g; # blind '->,', '++', and '--'
report("space before '$1'") if $intra_line =~ m/[^:)]\s+(;)/; # space before ';' but not after ':' or ')' # note that
# exceptions for "for (;; )" are handled above
report("space before '$1'") if $intra_line =~ m/\s([,)\]])/; # space before ,)]
report("space after '$1'") if $intra_line =~ m/([(\[~!])\s/; # space after ([~!
report("space after '$1'") if $intra_line =~ m/(defined)\s/; # space after 'defined'
report("missing space before '$1'") if $intra_line =~ m/\S([|\/%<>^\?])/; # |/%<>^? without preceding space
# TODO ternary ':' without preceding SPC, while allowing no SPC before ':' after 'case'
report("missing space before binary '$2'") if $intra_line =~ m/([^\s{()\[e])([+\-])/; # '+'/'-' without preceding space or {()[e
# ')' may be used for type casts or before "->", 'e' may be used for numerical literals such as "1e-6"
report("missing space before binary '$1'") if $intra_line =~ m/[^\s{()\[*!]([*])/; # '*' without preceding space or {()[*!
report("missing space before binary '$1'") if $intra_line =~ m/[^\s{()\[]([&])/; # '&' without preceding space or {()[
report("missing space after ternary '$1'") if $intra_line =~ m/(:)[^\s\d]/; # ':' without following space or digit
report("missing space after '$1'") if $intra_line =~ m/([,;=|\/%<>^\?])\S/; # ,;=|/%<>^? without following space
report("missing space after binary '$1'") if $intra_line=~m/[^{(\[]([*])[^\sa-zA-Z_(),*]/;# '*' w/o space or \w(),* after
# TODO unary '*' must not be followed by SPC
report("missing space after binary '$1'") if $intra_line=~m/([&])[^\sa-zA-Z_(]/; # '&' w/o following space or \w(
# TODO unary '&' must not be followed by SPC
report("missing space after binary '$1'") if $intra_line=~m/[^{(\[]([+\-])[^\s\d(]/; # +/- w/o following space or \d(
# TODO unary '+' and '-' must not be followed by SPC
report("missing space after '$2'") if $intra_line =~ m/(^|\W)(if|while|for|switch|case)[^\w\s]/; # kw w/o SPC
report("missing space after '$2'") if $intra_line =~ m/(^|\W)(return)[^\w\s;]/; # return w/o SPC or ';'
report("space after function/macro name")
if $intra_line =~ m/(\w+)\s+\(/ # fn/macro name with space before '('
&& !($1 =~ m/^(sizeof|if|else|while|do|for|switch|case|default|break|continue|goto|return|void|char|signed|unsigned|int|short|long|float|double|typedef|enum|struct|union|auto|extern|static|const|volatile|register)$/) # not keyword
&& !(m/^\s*#\s*define\s+\w+\s+\(/); # not a macro without parameters having a body that starts with '('
report("missing space before '{'") if $intra_line =~ m/[^\s{(\[]\{/; # '{' without preceding space or {([
report("missing space after '}'") if $intra_line =~ m/\}[^\s,;\])}]/; # '}' without following space or ,;])}
}
# adapt required indentation @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
s/(\w*ASN1_[A-Z_]+END\w*([^(]|\(.*?\)|$))/$1;/g; # treat *ASN1_*END*(..) macro calls as if followed by ';'
my $nested_indents_position = 0;
# update indents according to leading closing brace(s) '}' or label or switch case
my $in_stmt = $in_expr || @nested_symbols != 0 || $in_typedecl != 0;
if ($in_stmt) { # expr/stmt/type decl/var def/fn hdr, i.e., not at block level
if (m/^([\s@]*\})/) { # leading '}' within stmt, any preceding blinded comment must not be matched
$in_block_decls = -1;
my $head = $1;
update_nested_indents($head);
$nested_indents_position = length($head);
if (@nested_symbols >= 1) {
$hanging_symbol = @nested_symbols[-1];
$expr_indent = @nested_indents[-1];
} else { # typically end of initialiizer expr or enum
$expr_indent = 0;
}
} elsif (m/^([\s@]*)(static_)?ASN1_ITEM_TEMPLATE_END(\W|$)/) { # workaround for ASN1 macro indented as '}'
$local_offset = -INDENT_LEVEL;
$expr_indent = 0;
} elsif (m/;.*?\}/) { # expr ends with ';' before '}'
report("code before '}'");
}
}
if (@in_do_hanging_offsets != 0 && # note there is nothing like "unexpected 'while'"
m/^[\s@]*while(\W|$)/) { # leading 'while'
$hanging_offset = pop @in_do_hanging_offsets;
}
if ($if_maybe_terminated) {
if (m/(^|\W)else(\W|$)/) { # (not necessarily leading) 'else'
if (@in_if_hanging_offsets == 0) {
report("unexpected 'else'");
} else {
$hanging_offset = pop @in_if_hanging_offsets;
}
} else {
@in_if_hanging_offsets = (); # note there is nothing like "unclosed 'if'"
$hanging_offset = 0;
}
}
if (!$in_stmt) { # at block level, i.e., outside expr/stmt/type decl/var def/fn hdr
$if_maybe_terminated = 0;
if (my ($head, $before, $tail) = m/^([\s@]*([^{}]*)\})[\s@]*(.*)$/) { # leading closing '}', but possibly
# with non-whitespace non-'{' before
report("code after '}'") unless $tail eq "" || $tail =~ m/(else|while|OSSL_TRACE_END)(\W|$)/;
my $outermost_level = @nested_block_indents == 1 && @nested_block_indents[0] == 0;
if (!$sloppy_bodylen && $outermost_level && $line_body_start != 0) {
my $body_len = $line - $line_body_start - 1;
report_flexibly($line_function_start, "function body length = $body_len > ".MAX_BODY_LENGTH." lines",
$last_function_header) if $body_len > MAX_BODY_LENGTH;
$line_body_start = 0;
}
if ($before ne "") { # non-whitespace non-'{' before '}'
report("code before '}'");
} else { # leading '}' outside stmt, any preceding blinded comment must not be matched
$in_block_decls = -1;
$local_offset = $block_indent + $hanging_offset - INDENT_LEVEL;
update_nested_indents($head);
$nested_indents_position = length($head);
$local_offset -= ($block_indent + $hanging_offset);
# in effect $local_offset = -INDENT_LEVEL relative to $block_indent + $hanging_offset values before
}
}
# handle opening brace '{' after if/else/while/for/switch/do on line before
if ($hanging_offset > 0 && m/^[\s@]*{/ && # leading opening '{'
$line_before > 0 &&
- $contents_before_ =~ m/(^|^.*\W)(if|else|while|for|switch|do)(\W.*$|$)/) {
+ $contents_before_ =~ m/(^|^.*\W)(if|else|while|for|(OSSL_)?LIST_FOREACH(_\w+)?|switch|do)(\W.*$|$)/) {
$keyword_opening_brace = $1;
$hanging_offset -= INDENT_LEVEL; # cancel newly hanging_offset
}
if (m/^[\s@]*(case|default)(\W.*$|$)/) { # leading 'case' or 'default'
my $keyword = $1;
report("code after $keyword: ") if $2 =~ /:.*[^\s@].*$/;
$local_offset = -INDENT_LEVEL;
} else {
if (m/^([\s@]*)(\w+):/) { # (leading) label, cannot be "default"
$local_offset = -INDENT_LEVEL;
$has_label = 1;
}
}
}
# potential adaptations of indent in first line of macro body in multi-line macro definition
if ($in_preproc != 0 && $in_macro_header > 0) {
if ($in_macro_header > 1) { # still in macro definition header
$in_macro_header += parens_balance($_);
} else { # begin of macro body
$in_macro_header = 0;
if ($count == $block_indent - $preproc_offset # body began with same indentation as preceding code
&& $sloppy_macro) { # workaround for this situation is enabled
$block_indent -= $preproc_offset;
$preproc_offset = 0;
}
}
}
# check required indentation @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
check_indent() if $count >= 0; # not for start of preprocessor directive and not if multi-line string literal is continued
# check for blank lines within/after local decls @@@@@@@@@@@@@@@@@@@@@@@@@@@
if ($in_block_decls >= 0 &&
$in_comment == 0 && !m/^\s*\*?@/ && # not in a multi-line or intra-line comment
!$in_expr && $expr_indent == 0 && $in_typedecl == 0) {
my $blank_line_before = $line > 1 && $code_contents_before =~ m/^\s*(\\\s*)?$/;
# essentially blank line before: just whitespace and maybe a '\'
if (m/^[\s(]*(char|signed|unsigned|int|short|long|float|double|enum|struct|union|auto|extern|static|const|volatile|register)(\W|$)/ # clear start of local decl
|| (m/^(\s*(\w+|\[\]|[\*()]))+?\s+[\*\(]*\w+(\s*(\)|\[[^\]]*\]))*\s*[;,=]/ # weak check for decl involving user-defined type
&& !m/^\s*(\}|sizeof|if|else|while|do|for|switch|case|default|break|continue|goto|return)(\W|$)/)) {
$in_block_decls++;
report_flexibly($line - 1, "blank line within local decls, before", $contents) if $blank_line_before;
} else {
report_flexibly($line, "missing blank line after local decls", "\n$contents_before$contents")
if $in_block_decls > 0 && !$blank_line_before;
$in_block_decls = -1 unless
m/^\s*(\\\s*)?$/ # essentially blank line: just whitespace (and maybe a trailing '\')
|| $in_comment != 0 || m/^\s*\*?@/; # in multi-line comment or an intra-line comment
}
}
$in_comment = 0 if $in_comment < 0; # multi-line comment has ended
# do some further checks @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
my $outermost_level = $block_indent - $preproc_offset == 0;
- report("more than one stmt") if !m/(^|\W)for(\W.*|$)/ && # no 'for' - TODO improve matching
+ report("more than one stmt") if !m/(^|\W)(for|(OSSL_)?LIST_FOREACH(_\w+)?)(\W.*|$)/ && # no 'for' - TODO improve matching
m/;.*;/; # two or more terminators ';', so more than one statement
# check for code block containing a single line/statement
if ($line_before2 > 0 && !$outermost_level && # within function body
$in_typedecl == 0 && @nested_indents == 0 && # neither within type declaration nor inside stmt/expr
m/^[\s@]*\}\s*(\w*)/) { # leading closing brace '}', any preceding blinded comment must not be matched
# TODO extend detection from single-line to potentially multi-line statement
my $next_word = $1;
if ($line_opening_brace > 0 &&
($keyword_opening_brace ne "if" ||
$extended_1_stmt || $next_word ne "else") &&
($line_opening_brace == $line_before2 ||
$line_opening_brace == $line_before)
&& $contents_before =~ m/;/) { # there is at least one terminator ';', so there is some stmt
# TODO do not report cases where a further else branch
# follows with a block containing more than one line/statement
report_flexibly($line_before, "'$keyword_opening_brace' { 1 stmt }", $contents_before);
}
}
report("single-letter name '$2'") if (m/(^|.*\W)([IO])(\W.*|$)/); # single-letter name 'I' or 'O' # maybe re-add 'l'?
# constant on LHS of comparison or assignment, e.g., NULL != x or 'a' < c, but not a + 1 == b
report("constant on LHS of '$3'")
if (m/(['"]|([\+\-\*\/\/%\&\|\^<>]\s*)?\W[0-9]+L?|\WNULL)\s*([\!<>=]=|[<=>])([<>]?)/ &&
$2 eq "" && (($3 ne "<" && $3 ne "='" && $3 ne ">") || $4 eq ""));
# TODO report needless use of parentheses, while
# macro parameters should always be in parens (except when passed on), e.g., '#define ID(x) (x)'
# adapt required indentation for following lines @@@@@@@@@@@@@@@@@@@@@@@@@@@
# set $in_expr, $in_paren_expr, and $hanging_offset for if/while/for/switch, return/enum, and assignment RHS
my $paren_expr_start = 0;
my $return_enum_start = 0;
my $assignment_start = 0;
my $tmp = $_;
$tmp =~ s/[\!<>=]=/@@/g; # blind (in-)equality symbols like '<=' as '@@' to prevent matching them as '=' below
- if (m/^((^|.*\W)(if|while|for|switch))(\W.*|$)$/) { # (last) if/for/while/switch
+ if (m/^((^|.*\W)(if|while|for|(OSSL_)?LIST_FOREACH(_\w+)?|switch))(\W.*|$)$/) { # (last) if/for/while/switch
$paren_expr_start = 1;
} elsif (m/^((^|.*\W)(return|enum))(\W.*|$)/ # (last) return/enum
&& !$in_expr && @nested_indents == 0 && parens_balance($1) == 0) { # not nested enum
$return_enum_start = 1;
} elsif ($tmp =~ m/^(([^=]*)(=))(.*)$/ # (last) '=', i.e., assignment
&& !$in_expr && @nested_indents == 0 && parens_balance($1) == 0) { # not nested assignment
$assignment_start = 1;
}
if ($paren_expr_start || $return_enum_start || $assignment_start)
{
my ($head, $mid, $tail) = ($1, $3, $4);
$keyword_opening_brace = $mid if $mid ne "=";
# to cope with multi-line expressions, do this also if !($tail =~ m/\{/)
push @in_if_hanging_offsets, $hanging_offset if $mid eq "if";
# already handle $head, i.e., anything before expression
update_nested_indents($head, $nested_indents_position);
$nested_indents_position = length($head);
# now can set $in_expr and $in_paren_expr
$in_expr = 1;
$in_paren_expr = 1 if $paren_expr_start;
if ($mid eq "while" && @in_do_hanging_offsets != 0) {
$hanging_offset = pop @in_do_hanging_offsets;
} else {
$hanging_offset += INDENT_LEVEL; # tentatively set hanging_offset, may be canceled by following '{'
}
}
# set $hanging_offset and $keyword_opening_brace for do/else
if (my ($head, $mid, $tail) = m/(^|^.*\W)(else|do)(\W.*|$)$/) { # last else/do, where 'do' is preferred, but not #else
my $code_before = $head =~ m/[^\s\@}]/; # leading non-whitespace non-comment non-'}'
report("code before '$mid'") if $code_before;
report("code after '$mid'" ) if $tail =~ m/[^\s\@{]/# trailing non-whitespace non-comment non-'{' (non-'\')
&& !($mid eq "else" && $tail =~ m/[\s@]*if(\W|$)/);
if ($mid eq "do") { # workarounds for code before 'do'
if ($head =~ m/(^|^.*\W)(else)(\W.*$|$)/) { # 'else' ... 'do'
$hanging_offset += INDENT_LEVEL; # tentatively set hanging_offset, may be canceled by following '{'
}
if ($head =~ m/;/) { # terminator ';' ... 'do'
@in_if_hanging_offsets = (); # note there is nothing like "unclosed 'if'"
$hanging_offset = 0;
}
}
push @in_do_hanging_offsets, $hanging_offset if $mid eq "do";
if ($code_before && $mid eq "do") {
$hanging_offset = length($head) - $block_indent;
}
if (!$in_paren_expr) {
$keyword_opening_brace = $mid if $tail =~ m/\{/;
$hanging_offset += INDENT_LEVEL;
}
}
# set $in_typedecl and potentially $hanging_offset for type declaration
if (!$in_expr && @nested_indents == 0 # not in expression
&& m/(^|^.*\W)(typedef|enum|struct|union)(\W.*|$)$/
&& parens_balance($1) == 0 # not in newly started expression or function arg list
&& ($2 eq "typedef" || !($3 =~ m/\s*\w++\s*(.)/ && $1 ne "{")) # 'struct'/'union'/'enum' <name> not followed by '{'
# not needed: && $keyword_opening_brace = $2 if $3 =~ m/\{/;
) {
$in_typedecl++;
$hanging_offset += INDENT_LEVEL if m/\*.*\(/; # '*' followed by '(' - seems consistent with Emacs C mode
}
my $local_in_expr = $in_expr;
my $terminator_position = update_nested_indents($_, $nested_indents_position);
if ($local_in_expr) {
# on end of non-if/while/for/switch (multi-line) expression (i.e., return/enum/assignment) and
# on end of statement/type declaration/variable definition/function header
if ($terminator_position >= 0 && ($in_typedecl == 0 || @nested_indents == 0)) {
check_nested_nonblock_indents("expr");
$in_expr = 0;
}
} else {
check_nested_nonblock_indents($in_typedecl == 0 ? "stmt" : "decl") if $terminator_position >= 0;
}
# on ';', which terminates the current statement/type declaration/variable definition/function declaration
if ($terminator_position >= 0) {
my $tail = substr($_, $terminator_position + 1);
if (@in_if_hanging_offsets != 0) {
if ($tail =~ m/\s*else(\W|$)/) {
pop @in_if_hanging_offsets;
$hanging_offset -= INDENT_LEVEL;
} elsif ($tail =~ m/[^\s@]/) { # code (not just comment) follows
@in_if_hanging_offsets = (); # note there is nothing like "unclosed 'if'"
$hanging_offset = 0;
} else {
$if_maybe_terminated = 1;
}
} elsif ($tail =~ m/^[\s@]*$/) { # ';' has been trailing, i.e. there is nothing but whitespace and comments
$hanging_offset = 0; # reset in case of terminated assignment ('=') etc.
}
$in_typedecl-- if $in_typedecl != 0 && @nested_in_typedecl == 0; # TODO handle multiple type decls per line
m/(;[^;]*)$/; # match last ';'
$terminator_position = length($_) - length($1) if $1;
# new $terminator_position value may be after the earlier one in case multiple terminators on current line
# TODO check treatment in case of multiple terminators on current line
update_nested_indents($_, $terminator_position + 1);
}
# set hanging expression indent according to nested indents - TODO maybe do better in update_nested_indents()
# also if $in_expr is 0: in statement/type declaration/variable definition/function header
$expr_indent = 0;
for (my $i = -1; $i >= -@nested_symbols; $i--) {
if (@nested_symbols[$i] ne "?") { # conditionals '?' ... ':' are treated specially in check_indent()
$hanging_symbol = @nested_symbols[$i];
$expr_indent = $nested_indents[$i];
# $expr_indent is guaranteed to be != 0 unless @nested_indents contains just outer conditionals
last;
}
}
# remember line number and header containing name of last function defined for reports w.r.t. MAX_BODY_LENGTH
if ($in_preproc == 0 && $outermost_level && m/(\w+)\s*\(/ && $1 ne "STACK_OF") {
$line_function_start = $line;
$last_function_header = $contents;
}
# special checks for last, typically trailing opening brace '{' in line
if (my ($head, $tail) = m/^(.*)\{(.*)$/) { # match last ... '{'
if (!$in_expr && $in_typedecl == 0) {
if ($outermost_level) {
if (!$assignment_start && !$local_in_expr) {
# at end of function definition header (or stmt or var definition)
report("'{' not at line start") if length($head) != $preproc_offset && $head =~ m/\)\s*/; # at end of function definition header
$line_body_start = $contents =~ m/LONG BODY/ ? 0 : $line if $line_function_start != 0;
}
} else {
- $line_opening_brace = $line if $keyword_opening_brace =~ m/if|do|while|for/;
+ $line_opening_brace = $line if $keyword_opening_brace =~ m/if|do|while|for|(OSSL_)?LIST_FOREACH(_\w+)?/;
# using, not assigning, $keyword_opening_brace here because it could be on an earlier line
$line_opening_brace = $line if $keyword_opening_brace eq "else" && $extended_1_stmt &&
# TODO prevent false positives for if/else where braces around single-statement branches
# should be avoided but only if all branches have just single statements
# The following helps detecting the exception when handling multiple 'if ... else' branches:
!($keyword_opening_brace eq "else" && $line_opening_brace < $line_before2);
}
report("code after '{'") if $tail=~ m/[^\s\@]/ && # trailing non-whitespace non-comment (non-'\')
!($tail=~ m/\}/); # missing '}' after last '{'
}
}
- # check for opening brace after if/while/for/switch/do not on same line
+ # check for opening brace after if/while/for/switch/do missing on same line
# note that "missing '{' on same line after '} else'" is handled further below
if (/^[\s@]*{/ && # leading '{'
$line_before > 0 && !($contents_before_ =~ m/^\s*#/) && # not preprocessor directive '#if
- (my ($head, $mid, $tail) = ($contents_before_ =~ m/(^|^.*\W)(if|while|for|switch|do)(\W.*$|$)/))) {
+ (my ($head, $mid, $tail) = ($contents_before_ =~ m/(^|^.*\W)(if|while|for|(OSSL_)?LIST_FOREACH(_\w+)?|switch|do)(\W.*$|$)/))) {
my $brace_after = $tail =~ /^[\s@]*{/; # any whitespace or comments then '{'
report("'{' not on same line as preceding '$mid'") if !$brace_after;
}
# check for closing brace on line before 'else' not followed by leading '{'
elsif (my ($head, $tail) = m/(^|^.*\W)else(\W.*$|$)/) {
if (parens_balance($tail) == 0 && # avoid false positive due to unfinished expr on current line
!($tail =~ m/{/) && # after 'else' missing '{' on same line
!($head =~ m/}[\s@]*$/) && # not: '}' then any whitespace or comments before 'else'
$line_before > 0 && $contents_before_ =~ /}[\s@]*$/) { # trailing '}' on line before
report("missing '{' on same line after '} else'");
}
}
# check for closing brace before 'while' not on same line
if (my ($head, $tail) = m/(^|^.*\W)while(\W.*$|$)/) {
my $brace_before = $head =~ m/}[\s@]*$/; # '}' then any whitespace or comments
# possibly 'if (...)' (with potentially inner '(' and ')') then any whitespace or comments then '{'
if (!$brace_before &&
# does not work here: @in_do_hanging_offsets != 0 && #'while' terminates loop
parens_balance($tail) == 0 && # avoid false positive due to unfinished expr on current line
$tail =~ /;/ && # 'while' terminates loop (by ';')
$line_before > 0 &&
$contents_before_ =~ /}[\s@]*$/) { # on line before: '}' then any whitespace or comments
report("'while' not on same line as preceding '}'");
}
}
# check for missing brace on same line before or after 'else'
if (my ($head, $tail) = m/(^|^.*\W)else(\W.*$|$)/) {
my $brace_before = $head =~ /}[\s@]*$/; # '}' then any whitespace or comments
my $brace_after = $tail =~ /^[\s@]*if[\s@]*\(.*\)[\s@]*{|[\s@]*{/;
# possibly 'if (...)' (with potentially inner '(' and ')') then any whitespace or comments then '{'
if (!$brace_before) {
if ($line_before > 0 && $contents_before_ =~ /}[\s@]*$/) {
report("'else' not on same line as preceding '}'");
} elsif (parens_balance($tail) == 0) { # avoid false positive due to unfinished expr on current line
report("missing '}' on same line before 'else ... {'") if $brace_after;
}
} elsif (parens_balance($tail) == 0) { # avoid false positive due to unfinished expr on current line
report("missing '{' on same line after '} else'") if $brace_before && !$brace_after;
}
}
# on begin of multi-line preprocessor directive, adapt indent
if ($in_comment == 0 && $trailing_backslash) {
# trailing '\'typically used in preprocessor directive like '#define'
if ($in_preproc == 1) { # start of multi-line preprocessor directive
# note that backup+reset_indentation_state() has already been called
$in_macro_header = m/^\s*#\s*define(\W|$)?(.*)/ ? 1 + parens_balance($2) : 0; # '#define' is beginning
$preproc_offset = INDENT_LEVEL;
$block_indent = $preproc_offset;
}
$in_preproc += 1;
}
# post-processing at end of line @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
LINE_FINISHED:
$code_contents_before = $contents if
!m/^\s*#(\s*)(\w+)/ && # not single-line preprocessor directive
$in_comment == 0 && !m/^\s*\*?@/; # not in a multi-line comment nor in an intra-line comment
# on end of (possibly multi-line) preprocessor directive, adapt indent
if ($in_preproc != 0 && !$trailing_backslash) { # no trailing '\'
$in_preproc = 0;
$preproc_offset = 0;
restore_indentation_state();
}
if ($essentially_blank_line) {
report("leading ".($1 eq "" ? "blank" :"whitespace")." line") if $line == 1 && !$sloppy_SPC;
} else {
if ($line_before > 0) {
my $linediff = $line - $line_before - 1;
report("$linediff blank lines before") if $linediff > 1 && !$sloppy_SPC;
}
$line_before2 = $line_before;
$contents_before2 = $contents_before;
$contents_before_2 = $contents_before_;
$line_before = $line;
$contents_before = $contents;
$contents_before_ = $_;
$count_before = $count;
}
if ($self_test) { # debugging
my $should_report = $contents =~ m/\*@(\d)?/ ? 1 : 0;
$should_report = +$1 if $should_report != 0 && defined $1;
print("$ARGV:$line:$num_reports_line reports on:$contents")
if $num_reports_line != $should_report;
}
$num_reports_line = 0;
# post-processing at end of file @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
if (eof) {
# check for essentially blank line (which may include a '\') just before EOF
report(($1 eq "\n" ? "blank line" : $2 ne "" ? "'\\'" : "whitespace")." at EOF")
if $contents =~ m/^(\s*(\\?)\s*)$/ && !$sloppy_SPC;
# report unclosed expression-level nesting
check_nested_nonblock_indents("expr at EOF"); # also adapts @nested_block_indents
# sanity-check balance of block-level { ... } via final $block_indent at end of file
report_flexibly($line, +@nested_block_indents." unclosed '{'", "(EOF)\n") if @nested_block_indents != 0;
# sanity-check balance of #if ... #endif via final preprocessor directive indent at end of file
report_flexibly($line, "$preproc_if_nesting unclosed '#if'", "(EOF)\n") if $preproc_if_nesting != 0;
reset_file_state();
}
}
# final summary report @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
my $num_other_reports = $num_reports - $num_indent_reports - $num_nesting_issues
- $num_syntax_issues - $num_SPC_reports - $num_length_reports;
print "$num_reports ($num_indent_reports indentation, $num_nesting_issues '#if' nesting indent, ".
"$num_syntax_issues syntax, $num_SPC_reports whitespace, $num_length_reports length, $num_other_reports other)".
" issues have been found by $0\n" if $num_reports != 0 && !$self_test;
diff --git a/crypto/openssl/util/mkbuildinf.pl b/crypto/openssl/util/mkbuildinf.pl
index 1c273872be11..799ed3cdcd09 100755
--- a/crypto/openssl/util/mkbuildinf.pl
+++ b/crypto/openssl/util/mkbuildinf.pl
@@ -1,56 +1,60 @@
#! /usr/bin/env perl
-# Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
use strict;
use warnings;
-my ($cflags, $platform) = @ARGV;
+my $platform = pop @ARGV;
+my $cflags = join(' ', @ARGV);
+$cflags =~ s(\\)(\\\\)g;
$cflags = "compiler: $cflags";
-my $date = gmtime($ENV{'SOURCE_DATE_EPOCH'} || time()) . " UTC";
+# Use the value of the envvar SOURCE_DATE_EPOCH, even if it's
+# zero or the empty string.
+my $date = gmtime($ENV{'SOURCE_DATE_EPOCH'} // time()) . " UTC";
print <<"END_OUTPUT";
/*
* WARNING: do not edit!
* Generated by util/mkbuildinf.pl
*
- * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#define PLATFORM "platform: $platform"
#define DATE "built on: $date"
/*
* Generate compiler_flags as an array of individual characters. This is a
* workaround for the situation where CFLAGS gets too long for a C90 string
* literal
*/
static const char compiler_flags[] = {
END_OUTPUT
my $ctr = 0;
foreach my $c (split //, $cflags) {
$c =~ s|([\\'])|\\$1|;
# Max 16 characters per line
if (($ctr++ % 16) == 0) {
if ($ctr != 1) {
print "\n";
}
print " ";
}
print "'$c',";
}
print <<"END_OUTPUT";
'\\0'
};
END_OUTPUT
diff --git a/crypto/openssl/util/perl/OpenSSL/Template.pm b/crypto/openssl/util/perl/OpenSSL/Template.pm
index 7411dd8ae8d7..ad93278ca761 100644
--- a/crypto/openssl/util/perl/OpenSSL/Template.pm
+++ b/crypto/openssl/util/perl/OpenSSL/Template.pm
@@ -1,150 +1,159 @@
#! /usr/bin/env perl
# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not 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
# Implements the functionality to read one or more template files and run
# them through Text::Template
package OpenSSL::Template;
=head1 NAME
OpenSSL::Template - a private extension of Text::Template
=head1 DESCRIPTION
This provides exactly the functionality from Text::Template, with the
following additions:
=over 4
=item *
The template perl code delimiters (given with the C<DELIMITER> option)
are set to C<{-> and C<-}> by default.
=item *
A few extra functions are offered to be used by the template perl code, see
L</Functions>.
=back
=cut
use File::Basename;
use File::Spec::Functions;
use Text::Template 1.46;
our @ISA = qw(Text::Template); # parent
+sub tmpl_error {
+ my (%err_dict) = @_;
+
+ $ERROR = $err_dict{"error"};
+
+ return undef;
+}
+
sub new {
my $class = shift;
# Call the constructor of the parent class.
my $self = $class->SUPER::new(DELIMITERS => [ '{-', '-}'],
@_ );
# Add few more attributes
$self->{_output_off} = 0; # Default to output hunks
return bless $self, $class;
}
sub fill_in {
my $self = shift;
my %opts = @_;
my %hash = ( %{$opts{HASH}} );
delete $opts{HASH};
$self->SUPER::fill_in(HASH => { quotify1 => \&quotify1,
quotify_l => \&quotify_l,
output_on => sub { $self->output_on() },
output_off => sub { $self->output_off() },
%hash },
+ BROKEN => \&tmpl_error,
%opts);
}
=head2 Functions
=cut
# Override Text::Template's append_text_to_result, as recommended here:
#
# http://search.cpan.org/~mjd/Text-Template-1.46/lib/Text/Template.pm#Automatic_postprocessing_of_template_hunks
sub append_text_to_output {
my $self = shift;
if ($self->{_output_off} == 0) {
$self->SUPER::append_text_to_output(@_);
}
return;
}
=begin comment
We lie about the OO nature of output_on() and output_off(), 'cause that's
not how we pass them, see the HASH option used in fill_in() above
=end comment
=over 4
=item output_on()
=item output_off()
Switch on or off template output. Here's an example usage:
=over 4
{- output_off() if CONDITION -}
whatever
{- output_on() if CONDITION -}
=back
In this example, C<whatever> will only become part of the template output
if C<CONDITION> is true.
=back
=cut
sub output_on {
my $self = shift;
if (--$self->{_output_off} < 0) {
$self->{_output_off} = 0;
}
}
sub output_off {
my $self = shift;
$self->{_output_off}++;
}
# Helper functions for the templates #################################
=head1 SEE ALSO
L<Text::Template>
=head1 AUTHORS
Richard Levitte E<lt>levitte@openssl.orgE<gt>
=head1 COPYRIGHT
Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not 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

File Metadata

Mime Type
application/octet-stream
Expires
Tue, Oct 21, 11:26 AM (2 d)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
sxqcnIOt3OYD
Default Alt Text
(4 MB)

Event Timeline